public inbox for pve-devel@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal