From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id D9FC71FF0AA for ; Fri, 21 Aug 2026 16:05:46 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 18729217BA; Fri, 21 Aug 2026 16:04:28 +0200 (CEST) From: Gabriel Goller To: pve-devel@lists.proxmox.com Subject: [PATCH proxmox-ve-rs 05/15] tests: fabrics: add test for fabrics in VRFs Date: Fri, 21 Aug 2026 16:03:49 +0200 Message-ID: <20260821140404.322081-6-g.goller@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260821140404.322081-1-g.goller@proxmox.com> References: <20260821140404.322081-1-g.goller@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1787321022946 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.650 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: DRJZRL7QAB25O6Z4VLBIEJ3OCMLVI67J X-Message-ID-Hash: DRJZRL7QAB25O6Z4VLBIEJ3OCMLVI67J X-MailFrom: g.goller@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Add an integration test covering OSPF and BGP fabrics assigned to multiple SDN zone VRFs. Signed-off-by: Gabriel Goller --- .../tests/fabric/cfg/vrf/fabrics.cfg | 43 ++++++ .../tests/fabric/cfg/vrf/route-maps.cfg | 15 ++ proxmox-ve-config/tests/fabric/helper.rs | 20 +++ proxmox-ve-config/tests/fabric/main.rs | 75 ++++++++-- .../fabric/snapshots/fabric__vrf_pve.snap | 134 ++++++++++++++++++ 5 files changed, 275 insertions(+), 12 deletions(-) create mode 100644 proxmox-ve-config/tests/fabric/cfg/vrf/fabrics.cfg create mode 100644 proxmox-ve-config/tests/fabric/cfg/vrf/route-maps.cfg create mode 100644 proxmox-ve-config/tests/fabric/snapshots/fabric__vrf_pve.snap diff --git a/proxmox-ve-config/tests/fabric/cfg/vrf/fabrics.cfg b/proxmox-ve-config/tests/fabric/cfg/vrf/fabrics.cfg new file mode 100644 index 000000000000..05a1cb57642a --- /dev/null +++ b/proxmox-ve-config/tests/fabric/cfg/vrf/fabrics.cfg @@ -0,0 +1,43 @@ +ospf_fabric: ospfred + area 0 + ip_prefix 10.0.0.0/24 + zone red + +ospf_fabric: ospfblue + area 0 + ip_prefix 10.0.0.0/24 + zone blue + +ospf_node: ospfred_pve + interfaces name=ens18 + ip 10.0.0.1 + +ospf_node: ospfblue_pve + interfaces name=ens19 + ip 10.0.0.1 + +bgp_fabric: bgpred + bfd 0 + ip_prefix 10.1.0.0/24 + route_map_in red-in + route_map_out red-out + zone red + +bgp_fabric: bgpblue + bfd 0 + ip_prefix 10.1.0.0/24 + route_map_in blue-in + route_map_out blue-out + zone blue + +bgp_node: bgpred_pve + asn 65001 + interfaces name=ens20 + ip 10.1.0.1 + role internal + +bgp_node: bgpblue_pve + asn 65002 + interfaces name=ens21 + ip 10.1.0.1 + role internal diff --git a/proxmox-ve-config/tests/fabric/cfg/vrf/route-maps.cfg b/proxmox-ve-config/tests/fabric/cfg/vrf/route-maps.cfg new file mode 100644 index 000000000000..b382fc369b51 --- /dev/null +++ b/proxmox-ve-config/tests/fabric/cfg/vrf/route-maps.cfg @@ -0,0 +1,15 @@ +route-map-entry: blue-in_10 + action permit + set key=local-preference,value=200 + +route-map-entry: blue-out_10 + action permit + set key=metric,value=20 + +route-map-entry: red-in_10 + action permit + set key=local-preference,value=100 + +route-map-entry: red-out_10 + action permit + set key=metric,value=10 diff --git a/proxmox-ve-config/tests/fabric/helper.rs b/proxmox-ve-config/tests/fabric/helper.rs index 93404b8eb7af..ec464d334a4c 100644 --- a/proxmox-ve-config/tests/fabric/helper.rs +++ b/proxmox-ve-config/tests/fabric/helper.rs @@ -18,6 +18,24 @@ macro_rules! get_fabrics_config { }}; } +#[allow(unused_macros)] +macro_rules! get_route_maps_config { + () => {{ + fn f() {} + fn type_name_of(_: T) -> &'static str { + std::any::type_name::() + } + let mut name = type_name_of(f); + + name = match &name[..name.len() - 3].rfind(':') { + Some(pos) => &name[pos + 1..name.len() - 3], + None => &name[..name.len() - 3], + }; + let real_filename = format!("tests/fabric/cfg/{name}/route-maps.cfg"); + &std::fs::read_to_string(real_filename).expect("cannot find route-map config file") + }}; +} + #[allow(unused_macros)] macro_rules! reference_name { ($suffix:expr) => {{ @@ -40,4 +58,6 @@ macro_rules! reference_name { #[allow(unused_imports)] pub(crate) use get_fabrics_config; #[allow(unused_imports)] +pub(crate) use get_route_maps_config; +#[allow(unused_imports)] pub(crate) use reference_name; diff --git a/proxmox-ve-config/tests/fabric/main.rs b/proxmox-ve-config/tests/fabric/main.rs index f65c5d26aeed..249816b54327 100644 --- a/proxmox-ve-config/tests/fabric/main.rs +++ b/proxmox-ve-config/tests/fabric/main.rs @@ -3,14 +3,19 @@ use std::net::Ipv4Addr; use std::str::FromStr; use proxmox_frr::ser::bgp::{AddressFamilies, BgpRouter, CommonAddressFamilyOptions, L2vpnEvpnAF}; -use proxmox_frr::ser::{FrrConfig, FrrProtocol, VrfName, serializer::dump}; -use proxmox_ve_config::sdn::fabric::{ - FabricConfig, - frr::build_fabric, - section_config::{ - fabric::{FabricId, FabricUpdater}, - node::NodeId, +use proxmox_frr::ser::route_map::{AccessAction, RouteMapEntry, RouteMapName}; +use proxmox_frr::ser::{FrrConfig, FrrProtocol, IpProtocolRouteMap, VrfName, serializer::dump}; +use proxmox_section_config::typed::ApiSectionDataEntry; +use proxmox_ve_config::sdn::{ + fabric::{ + FabricConfig, + frr::build_fabric, + section_config::{ + fabric::{FabricId, FabricUpdater}, + node::NodeId, + }, }, + route_map::{RouteMap, frr::build_frr_route_maps}, }; mod helper; @@ -286,9 +291,31 @@ bgp_node: bgp_pve "#; let config = FabricConfig::parse_section_config(raw).unwrap(); let mut frr_config = FrrConfig::default(); + let correct_src = RouteMapName::new("correct_src".to_owned()); + let correct_src_entry = RouteMapEntry { + seq: 1, + action: AccessAction::Permit, + matches: Vec::new(), + sets: Vec::new(), + custom_frr_config: Vec::new(), + call: None, + exit_action: None, + }; + frr_config + .routemaps + .insert(correct_src.clone(), vec![correct_src_entry.clone()]); + frr_config.protocol_routemaps.insert( + FrrProtocol::Bgp, + IpProtocolRouteMap { + v4: Some(correct_src.clone()), + v6: None, + }, + ); build_fabric(NodeId::from_str("pve").unwrap(), config, &mut frr_config).unwrap(); + assert_eq!(frr_config.routemaps[&correct_src], vec![correct_src_entry]); + let ospf_routemap = &frr_config.vrf_protocol_routemaps [&VrfName::Custom("vrf_zoneone".to_owned())][&FrrProtocol::Ospf]; assert_eq!( @@ -307,14 +334,38 @@ bgp_node: bgp_pve .get(&FrrProtocol::Ospf) .is_none() ); - assert!( - frr_config - .protocol_routemaps - .get(&FrrProtocol::Bgp) - .is_none() + assert_eq!( + frr_config.protocol_routemaps[&FrrProtocol::Bgp].v4, + Some(correct_src) ); } +#[test] +fn vrf() { + let config = FabricConfig::parse_section_config(helper::get_fabrics_config!()).unwrap(); + let route_maps = + RouteMap::parse_section_config("route-maps.cfg", helper::get_route_maps_config!()).unwrap(); + let mut frr_config = FrrConfig::default(); + + build_frr_route_maps( + route_maps + .into_iter() + .map(|(_, route_map_entry)| route_map_entry), + &mut frr_config, + ) + .unwrap(); + build_fabric( + NodeId::from_str("pve").expect("invalid nodeid"), + config, + &mut frr_config, + ) + .unwrap(); + + let output = dump(&frr_config).expect("error dumping stuff"); + + insta::assert_snapshot!(helper::reference_name!("pve"), output); +} + #[test] fn bgp_default() { let config = FabricConfig::parse_section_config(helper::get_fabrics_config!()).unwrap(); diff --git a/proxmox-ve-config/tests/fabric/snapshots/fabric__vrf_pve.snap b/proxmox-ve-config/tests/fabric/snapshots/fabric__vrf_pve.snap new file mode 100644 index 000000000000..84973240deb4 --- /dev/null +++ b/proxmox-ve-config/tests/fabric/snapshots/fabric__vrf_pve.snap @@ -0,0 +1,134 @@ +--- +source: proxmox-ve-config/tests/fabric/main.rs +expression: output +--- +! +router bgp 65002 vrf vrf_blue + bgp router-id 10.1.0.1 + no bgp default ipv4-unicast + neighbor bgpblue peer-group + neighbor bgpblue remote-as external + neighbor ens21 interface peer-group bgpblue + ! + address-family ipv4 unicast + network 10.1.0.1/32 + neighbor bgpblue activate + neighbor bgpblue soft-reconfiguration inbound + neighbor bgpblue route-map pve_bgp_bgpblue_in in + neighbor bgpblue route-map blue-out out + exit-address-family +exit +! +router bgp 65001 vrf vrf_red + bgp router-id 10.1.0.1 + no bgp default ipv4-unicast + neighbor bgpred peer-group + neighbor bgpred remote-as external + neighbor ens20 interface peer-group bgpred + ! + address-family ipv4 unicast + network 10.1.0.1/32 + neighbor bgpred activate + neighbor bgpred soft-reconfiguration inbound + neighbor bgpred route-map pve_bgp_bgpred_in in + neighbor bgpred route-map red-out out + exit-address-family +exit +! +router ospf vrf vrf_blue + ospf router-id 10.0.0.1 +exit +! +router ospf vrf vrf_red + ospf router-id 10.0.0.1 +exit +! +interface dummy_ospfblue vrf vrf_blue + ip ospf area 0 + ip ospf passive +exit +! +interface dummy_ospfred vrf vrf_red + ip ospf area 0 + ip ospf passive +exit +! +interface ens18 vrf vrf_red + ip ospf area 0 + ip ospf network point-to-point +exit +! +interface ens19 vrf vrf_blue + ip ospf area 0 + ip ospf network point-to-point +exit +! +access-list pve_bgp_bgpblue_ips permit 10.1.0.0/24 +! +access-list pve_bgp_bgpred_ips permit 10.1.0.0/24 +! +access-list pve_ospf_ospfblue_ips permit 10.0.0.0/24 +! +access-list pve_ospf_ospfred_ips permit 10.0.0.0/24 +! +route-map blue-in permit 10 + set local-preference 200 +exit +! +route-map blue-out permit 10 + set metric 20 +exit +! +route-map pve_bgp_bgpblue_in permit 10 + match ip address pve_bgp_bgpblue_ips + call blue-in +exit +! +route-map pve_bgp_bgpred_in permit 10 + match ip address pve_bgp_bgpred_ips + call red-in +exit +! +route-map pve_bgp_vrf_blue permit 100 + match ip address pve_bgp_bgpblue_ips + set src 10.1.0.1 +exit +! +route-map pve_bgp_vrf_blue permit 65535 +exit +! +route-map pve_bgp_vrf_red permit 110 + match ip address pve_bgp_bgpred_ips + set src 10.1.0.1 +exit +! +route-map pve_bgp_vrf_red permit 65535 +exit +! +route-map pve_ospf_vrf_blue permit 120 + match ip address pve_ospf_ospfblue_ips + set src 10.0.0.1 +exit +! +route-map pve_ospf_vrf_red permit 130 + match ip address pve_ospf_ospfred_ips + set src 10.0.0.1 +exit +! +route-map red-in permit 10 + set local-preference 100 +exit +! +route-map red-out permit 10 + set metric 10 +exit +! +vrf vrf_blue + ip protocol bgp route-map pve_bgp_vrf_blue + ip protocol ospf route-map pve_ospf_vrf_blue +exit-vrf +! +vrf vrf_red + ip protocol bgp route-map pve_bgp_vrf_red + ip protocol ospf route-map pve_ospf_vrf_red +exit-vrf -- 2.47.3