all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Gabriel Goller <g.goller@proxmox.com>
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	[thread overview]
Message-ID: <20260821140404.322081-6-g.goller@proxmox.com> (raw)
In-Reply-To: <20260821140404.322081-1-g.goller@proxmox.com>

Add an integration test covering OSPF and BGP fabrics assigned to
multiple SDN zone VRFs.

Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
---
 .../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>(_: T) -> &'static str {
+            std::any::type_name::<T>()
+        }
+        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





  parent reply	other threads:[~2026-08-21 14:05 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-21 14:03 [RFC manager/network/proxmox{-ve-rs,-perl-rs} 00/15] SDN VRF support Gabriel Goller
2026-08-21 14:03 ` [PATCH proxmox-ve-rs 01/15] frr: add VRF-aware OSPF rendering Gabriel Goller
2026-08-21 14:03 ` [PATCH proxmox-ve-rs 02/15] sdn: add zone references to OSPF and BGP fabrics Gabriel Goller
2026-08-21 14:03 ` [PATCH proxmox-ve-rs 03/15] sdn: generate fabric routing configuration in zone VRFs Gabriel Goller
2026-08-21 14:03 ` [PATCH proxmox-ve-rs 04/15] sdn: fix VRF route-map scoping and zone ID validation Gabriel Goller
2026-08-21 14:03 ` Gabriel Goller [this message]
2026-08-21 14:03 ` [PATCH proxmox-perl-rs 06/15] pve-rs: fabrics: assign network interfaces to configured VRFs Gabriel Goller
2026-08-21 14:03 ` [PATCH proxmox-perl-rs 07/15] pve-rs: fabrics: make per-fabric status queries VRF-aware Gabriel Goller
2026-08-21 14:03 ` [PATCH proxmox-perl-rs 08/15] pve-rs: fabrics: include VRF routes in aggregate status Gabriel Goller
2026-08-21 14:03 ` [PATCH pve-network 09/15] sdn: add optional VRFs for simple zones Gabriel Goller
2026-08-21 14:03 ` [PATCH pve-network 10/15] sdn: allow fabrics to use simple zone VRFs Gabriel Goller
2026-08-21 14:03 ` [PATCH pve-network 11/15] sdn: always generate EVPN " Gabriel Goller
2026-08-21 14:03 ` [PATCH pve-network 12/15] api: sdn: allow EVPN zones as fabric VRFs Gabriel Goller
2026-08-21 14:03 ` [PATCH pve-network 13/15] api: sdn: disallow BGP fabrics in EVPN zone VRFs Gabriel Goller
2026-08-21 14:03 ` [PATCH pve-manager 14/15] ui: sdn: add VRF zone selection for fabrics Gabriel Goller
2026-08-21 14:03 ` [PATCH pve-manager 15/15] ui: sdn: expose EVPN zones as fabric VRFs Gabriel Goller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260821140404.322081-6-g.goller@proxmox.com \
    --to=g.goller@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal