Skip to content

Fix VPC manage vtep assumption #771

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions interface-manager/src/interface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ use rtnetlink::packet_route::link::{
InfoBridge, InfoData, InfoKind, InfoVrf, InfoVxlan, LinkAttribute, LinkFlags, LinkInfo,
LinkMessage, State,
};
use rtnetlink::{LinkBridge, LinkDummy, LinkUnspec, LinkVrf, LinkVxlan};
use rtnetlink::{LinkBridge, LinkUnspec, LinkVrf, LinkVxlan};
use serde::{Deserialize, Serialize};
use std::num::NonZero;
use tracing::{debug, error, warn};
Expand Down Expand Up @@ -150,7 +150,6 @@ impl Create for Manager<Interface> {
]))
.build()
}
InterfacePropertiesSpec::Dummy => LinkDummy::new(requirement.name.as_ref()).build(),
InterfacePropertiesSpec::Vtep(properties) => {
LinkVxlan::new(requirement.name.as_ref(), properties.vni.as_u32())
.set_info_data(InfoData::Vxlan(vec![
Expand Down Expand Up @@ -815,9 +814,6 @@ impl TryFromLinkMessage for Interface {

match (kind, pci_netdev_builder.build()) {
(Some(kind), Err(_)) => match kind {
InfoKind::Dummy => {
builder.properties(InterfaceProperties::Dummy);
}
InfoKind::Tun => {
builder.properties(InterfaceProperties::Tap);
}
Expand Down
3 changes: 0 additions & 3 deletions interface-manager/src/interface/properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ use serde::{Deserialize, Serialize};
pub enum InterfacePropertiesSpec {
/// The planned properties of a bridge.
Bridge(BridgePropertiesSpec),
/// The planned properties of a dummy interface
Dummy,
/// The planned properties of a tap device
Tap,
/// The expected properties of a pci netdev.
Expand All @@ -36,7 +34,6 @@ impl AsRequirement<InterfacePropertiesSpec> for InterfaceProperties {
InterfaceProperties::Bridge(props) => {
InterfacePropertiesSpec::Bridge(props.as_requirement())
}
InterfaceProperties::Dummy => InterfacePropertiesSpec::Dummy,
InterfaceProperties::Vtep(props) => {
InterfacePropertiesSpec::Vtep(props.as_requirement()?)
}
Expand Down
136 changes: 74 additions & 62 deletions mgmt/src/vpc_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::processor::confbuild::namegen::VpcInterfacesNames;

use config::InternalConfig;
use config::internal::interfaces::interface::InterfaceType;
use config::internal::interfaces::interface::{InterfaceConfigTable, InterfaceType};
use config::internal::routing::evpn::VtepConfig;
use derive_builder::Builder;
use futures::TryStreamExt;
Expand Down Expand Up @@ -152,8 +152,7 @@ impl Observe for VpcManager<RequiredInformationBase> {
InterfaceProperties::Other
| InterfaceProperties::Tap
| InterfaceProperties::Pci(_)
| InterfaceProperties::Bridge(_)
| InterfaceProperties::Dummy => { /* nothing to index */ }
| InterfaceProperties::Bridge(_) => { /* nothing to index */ }
}
}
for sliced in indexes_to_remove {
Expand Down Expand Up @@ -301,6 +300,58 @@ impl Vpc {
}
}

/// Create an InterfaceSpec for an InterfaceConfig
fn add_interface_specs(interfaces: &mut MultiIndexInterfaceSpecMap, ifaces: &InterfaceConfigTable) {
for iface in ifaces.values() {
match &iface.iftype {
InterfaceType::Ethernet(eth) => {
let mut tap = InterfaceSpecBuilder::default();
match InterfaceName::try_from(format!("{}-tap", iface.name.as_str())) {
Ok(name) => {
tap.name(name);
}
Err(e) => {
error!("{e}");
continue;
}
};
match eth.mac.map(SourceMac::try_from) {
Some(Ok(mac)) => {
tap.mac(Some(mac));
}
None => {
tap.mac(None);
}
Some(Err(e)) => {
error!("{e}");
continue;
}
};
tap.properties(InterfacePropertiesSpec::Tap);
tap.mtu(iface.mtu);
tap.admin_state(AdminState::Up);
match tap.build() {
Ok(iface) => match interfaces.try_insert(iface) {
Ok(added) => {
debug!("added proxy tap interface to spec: {added:?}");
}
Err(e) => {
error!("{e}");
}
},
Err(e) => {
error!("{e}");
continue;
}
}
}
_ => {
continue;
}
}
}
}

// TODO: break up this method into smaller components
impl TryFrom<&InternalConfig> for RequiredInformationBase {
type Error = RequiredInformationBaseBuilderError;
Expand All @@ -312,55 +363,10 @@ impl TryFrom<&InternalConfig> for RequiredInformationBase {
let mut vrfs = MultiIndexVrfPropertiesSpecMap::default();
let mut vteps = MultiIndexVtepPropertiesSpecMap::default();
let mut associations = MultiIndexInterfaceAssociationSpecMap::default();
for config in internal.vrfs.iter_by_tableid() {
for iface in config.interfaces.values() {
match &iface.iftype {
InterfaceType::Ethernet(eth) => {
let mut tap = InterfaceSpecBuilder::default();
match InterfaceName::try_from(format!("{}-tap", iface.name.as_str())) {
Ok(name) => {
tap.name(name);
}
Err(e) => {
error!("{e}");
continue;
}
};
match eth.mac.map(SourceMac::try_from) {
Some(Ok(mac)) => {
tap.mac(Some(mac));
}
None => {
tap.mac(None);
}
Some(Err(e)) => {
error!("{e}");
continue;
}
};
tap.properties(InterfacePropertiesSpec::Tap);
tap.mtu(iface.mtu);
tap.admin_state(AdminState::Up);
match tap.build() {
Ok(iface) => match interfaces.try_insert(iface) {
Ok(added) => {
debug!("added proxy tap interface to spec: {added:?}");
}
Err(e) => {
error!("{e}");
}
},
Err(e) => {
error!("{e}");
continue;
}
}
}
_ => {
continue;
}
}
}

// non-default VRFs
for vrfconfig in internal.vrfs.iter_by_tableid().filter(|cfg| !cfg.default) {
add_interface_specs(&mut interfaces, &vrfconfig.interfaces);
let main_vtep = internal.vtep.as_ref().unwrap_or_else(|| unreachable!());
let vtep_ip = match main_vtep.address {
UnicastIpAddr::V4(vtep_ip) => vtep_ip,
Expand All @@ -375,17 +381,17 @@ impl TryFrom<&InternalConfig> for RequiredInformationBase {
let mut bridge = InterfaceSpecBuilder::default();
vrf.controller(None);
vrf.admin_state(AdminState::Up);
match config.tableid {
None => {}
match vrfconfig.tableid {
None => unreachable!(),
Some(route_table_id) => {
debug!("route_table set for config: {config:?}");
debug!("route_table set for config: {vrfconfig:?}");
vrf.properties(InterfacePropertiesSpec::Vrf(VrfPropertiesSpec {
route_table_id,
}));
match &config.vpc_id {
match &vrfconfig.vpc_id {
None => {
error!("no vpc_id set for config: {config:?}");
panic!("no vpc_id set for config: {config:?}");
error!("no vpc_id set for config: {vrfconfig:?}");
panic!("no vpc_id set for config: {vrfconfig:?}");
}
Some(id) => {
vrf.name(id.vrf_name());
Expand All @@ -400,7 +406,7 @@ impl TryFrom<&InternalConfig> for RequiredInformationBase {
vlan_protocol: EthType::VLAN,
}));
vtep.properties(InterfacePropertiesSpec::Vtep(VtepPropertiesSpec {
vni: config.vni.expect("vni not set"),
vni: vrfconfig.vni.expect("vni not set"),
local: vtep_ip,
ttl: VtepConfig::TTL,
port: Vxlan::PORT,
Expand Down Expand Up @@ -498,6 +504,14 @@ impl TryFrom<&InternalConfig> for RequiredInformationBase {
}
}
}

// default VRF
let vrfconfig = internal
.vrfs
.default_vrf_config()
.unwrap_or_else(|| unreachable!());
add_interface_specs(&mut interfaces, &vrfconfig.interfaces);

rb_builder.interfaces(interfaces);
rb_builder.vteps(vteps);
rb_builder.vrfs(vrfs);
Expand Down Expand Up @@ -586,9 +600,7 @@ mod contract {
.unwrap();
}
}
InterfacePropertiesSpec::Tap
| InterfacePropertiesSpec::Dummy
| InterfacePropertiesSpec::Pci(_) => {}
InterfacePropertiesSpec::Tap | InterfacePropertiesSpec::Pci(_) => {}
}
}
if !bridges.is_empty() {
Expand Down
2 changes: 0 additions & 2 deletions mgmt/tests/reconcile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ async fn reconcile_demo() {
InterfacePropertiesSpec::Pci(prop) => {
pci_props.try_insert(prop.clone()).unwrap();
}
InterfacePropertiesSpec::Dummy => {}
InterfacePropertiesSpec::Tap => {}
}
}
Expand Down Expand Up @@ -260,7 +259,6 @@ async fn reconcile_demo() {
for interface in interfaces {
match &interface.properties {
InterfacePropertiesSpec::Bridge(_)
| InterfacePropertiesSpec::Dummy
| InterfacePropertiesSpec::Pci(_)
| InterfacePropertiesSpec::Tap => {}
InterfacePropertiesSpec::Vtep(props) => {
Expand Down
3 changes: 1 addition & 2 deletions net/src/interface/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl Display for InterfaceProperties {
InterfaceProperties::Vrf(vrf) => vrf.fmt(f),
InterfaceProperties::Vtep(vtep) => vtep.fmt(f),
InterfaceProperties::Pci(rep) => rep.fmt(f),
InterfaceProperties::Dummy | InterfaceProperties::Tap => "".fmt(f),
InterfaceProperties::Tap => "".fmt(f),
InterfaceProperties::Other => write!(f, "other"),
}
}
Expand All @@ -115,7 +115,6 @@ impl Display for InterfaceProperties {
fn ifproperty_to_str(properties: &InterfaceProperties) -> &'static str {
match properties {
InterfaceProperties::Bridge(_) => "bridge",
InterfaceProperties::Dummy => "dummy",
InterfaceProperties::Vrf(_) => "vrf",
InterfaceProperties::Vtep(_) => "vtep",
InterfaceProperties::Pci(_) => "pci",
Expand Down
2 changes: 0 additions & 2 deletions net/src/interface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,6 @@ impl Interface {
pub enum InterfaceProperties {
/// Properties of bridges
Bridge(BridgeProperties),
/// Dummy interface properties
Dummy,
/// Properties of VTEPs (vxlan devices)
Vtep(VtepProperties),
/// Properties of VRFs
Expand Down