public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH network v2 0/4] sdn: evpn: IPv6 underlay support
@ 2026-05-15 11:06 Hannes Laimer
  2026-05-15 11:06 ` [PATCH pve-network v2 1/4] sdn: evpn: prepare " Hannes Laimer
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Hannes Laimer @ 2026-05-15 11:06 UTC (permalink / raw)
  To: pve-devel

After we bumped frr this will work now, so rebased it and sent it again. Adds
IPv6 underlay support for EVPN: IPv6-capable underlays can be selected and IPv6
peers configured. On a dual-stack underlay the EVPN session picks IPv6.

I mostly tested this on top of the bgp-fabric series[2], but it does not depend
on the changes in the that series.

v2:
 - dropped two patches that have already been applied
 - rebased on top of current master


[v1] https://lore.proxmox.com/pve-devel/20260122135151.292794-1-h.laimer@proxmox.com/
[2] https://lore.proxmox.com/pve-devel/20260515102500.216264-1-h.laimer@proxmox.com/


pve-network:

Hannes Laimer (4):
  sdn: evpn: prepare IPv6 underlay support
  sdn: evpn: keep router-id valid on IPv6 underlay
  sdn: stabilize peer IP ordering when generating sdn config
  sdn: evpn: add tests covering ipv6 underlays

 src/PVE/Network/SDN/Controllers/EvpnPlugin.pm | 68 ++++++++++++---
 src/PVE/Network/SDN/Zones/EvpnPlugin.pm       | 18 ++--
 src/PVE/Network/SDN/Zones/VxlanPlugin.pm      |  2 +-
 .../expected_controller_config                | 63 ++++++++++++++
 .../expected_sdn_interfaces                   | 58 +++++++++++++
 .../exitnode_local_routing_ipv6/interfaces    |  7 ++
 .../exitnode_local_routing_ipv6/sdn_config    | 27 ++++++
 .../expected_controller_config                | 85 +++++++++++++++++++
 .../expected_sdn_interfaces                   | 64 ++++++++++++++
 .../evpn/openfabric_fabric_ipv6/interfaces    |  6 ++
 .../evpn/openfabric_fabric_ipv6/sdn_config    | 83 ++++++++++++++++++
 .../expected_controller_config                | 74 ++++++++++++++++
 .../expected_sdn_interfaces                   | 58 +++++++++++++
 .../openfabric_fabric_ipv6_only/interfaces    |  6 ++
 .../openfabric_fabric_ipv6_only/sdn_config    | 79 +++++++++++++++++
 15 files changed, 679 insertions(+), 19 deletions(-)
 create mode 100644 src/test/zones/evpn/exitnode_local_routing_ipv6/expected_controller_config
 create mode 100644 src/test/zones/evpn/exitnode_local_routing_ipv6/expected_sdn_interfaces
 create mode 100644 src/test/zones/evpn/exitnode_local_routing_ipv6/interfaces
 create mode 100644 src/test/zones/evpn/exitnode_local_routing_ipv6/sdn_config
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6/expected_controller_config
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6/expected_sdn_interfaces
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6/interfaces
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6/sdn_config
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6_only/expected_controller_config
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6_only/expected_sdn_interfaces
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6_only/interfaces
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6_only/sdn_config


Summary over all repositories:
  15 files changed, 679 insertions(+), 19 deletions(-)

-- 
Generated by murpp 0.11.0




^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH pve-network v2 1/4] sdn: evpn: prepare IPv6 underlay support
  2026-05-15 11:06 [PATCH network v2 0/4] sdn: evpn: IPv6 underlay support Hannes Laimer
@ 2026-05-15 11:06 ` Hannes Laimer
  2026-05-15 11:06 ` [PATCH pve-network v2 2/4] sdn: evpn: keep router-id valid on IPv6 underlay Hannes Laimer
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Hannes Laimer @ 2026-05-15 11:06 UTC (permalink / raw)
  To: pve-devel

Allow IPv6-capable underlays to be selected and IPv6 peers to be
configured. On a dual-stack underlay (every node carries both an IPv4
and IPv6 address) the EVPN session picks IPv6.

Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
 src/PVE/Network/SDN/Controllers/EvpnPlugin.pm | 66 ++++++++++++++++---
 src/PVE/Network/SDN/Zones/EvpnPlugin.pm       | 16 +++--
 2 files changed, 67 insertions(+), 15 deletions(-)

diff --git a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
index 8953418..0246788 100644
--- a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
@@ -137,22 +137,30 @@ sub generate_frr_config {
             return;
         }
 
-        if (!$current_node->{ip}) {
+        my $addr_key = fabric_addr_key($nodes);
+        if (!$addr_key) {
             log_warn(
-                "Node $local_node requires an IP in the fabric $fabric->{id} to configure the EVPN controller"
+                "Fabric $fabric->{id} has no consistent address family for all nodes (need all v6 or all v4)"
+            );
+            return;
+        }
+
+        if (!$current_node->{$addr_key}) {
+            log_warn(
+                "Node $local_node requires a $addr_key address in the fabric $fabric->{id} to configure the EVPN controller"
             );
             return;
         }
 
         for my $node_id (sort keys %$nodes) {
             my $node = $nodes->{$node_id};
-            push @peers, $node->{ip} if $node->{ip};
+            push @peers, $node->{$addr_key};
         }
 
         $loopback = "dummy_$fabric->{id}";
 
-        $ifaceip = $current_node->{ip};
-        $routerid = $current_node->{ip};
+        $ifaceip = $current_node->{$addr_key};
+        $routerid = $current_node->{$addr_key};
 
         if ($fabric->{protocol} eq 'bgp' && $bgp_mode eq 'external') {
             if (!$current_node->{asn}) {
@@ -357,21 +365,29 @@ sub generate_zone_frr_config {
             return;
         }
 
-        if (!$current_node->{ip}) {
+        my $addr_key = fabric_addr_key($nodes);
+        if (!$addr_key) {
+            log_warn(
+                "Fabric $fabric->{id} has no consistent address family for all nodes (need all v6 or all v4)"
+            );
+            return;
+        }
+
+        if (!$current_node->{$addr_key}) {
             log_warn(
-                "Node $local_node requires an IP in the fabric $fabric->{id} to configure the EVPN controller"
+                "Node $local_node requires a $addr_key address in the fabric $fabric->{id} to configure the EVPN controller"
             );
             return;
         }
 
         for my $node (values %$nodes) {
-            push @peers, $node->{ip} if $node->{ip};
+            push @peers, $node->{$addr_key};
         }
 
         $loopback = "dummy_$fabric->{id}";
 
-        $ifaceip = $current_node->{ip};
-        $routerid = $current_node->{ip};
+        $ifaceip = $current_node->{$addr_key};
+        $routerid = $current_node->{$addr_key};
 
     } elsif ($controller->{peers}) {
         @peers = PVE::Tools::split_list($controller->{'peers'}) if $controller->{'peers'};
@@ -673,6 +689,18 @@ sub on_update_hook {
         die "must have exactly one of peers / fabric defined"
             if ($controller->{peers} && $controller->{fabric})
             || !($controller->{peers} || $controller->{fabric});
+        if ($controller->{peers}) {
+            my @peers = PVE::Tools::split_list($controller->{peers});
+            my $family;
+
+            foreach my $peer (@peers) {
+                my $peer_family = Net::IP::ip_is_ipv6($peer) ? 6 : 4;
+                if (defined($family) && $family != $peer_family) {
+                    die "peers must contain only IPv4 or only IPv6 addresses\n";
+                }
+                $family = $peer_family;
+            }
+        }
     }
 }
 
@@ -704,4 +732,22 @@ sub find_isis_controller {
     return $res;
 }
 
+# Returns 'ip6' if every node carries an ip6, 'ip' if every node carries an ip
+# (preferring v6 when both are present), or undef if the fabric has no
+# consistent address family across nodes.
+sub fabric_addr_key {
+    my ($nodes) = @_;
+
+    my $all_v6 = 1;
+    my $all_v4 = 1;
+    for my $node (values %$nodes) {
+        $all_v6 = 0 if !$node->{ip6};
+        $all_v4 = 0 if !$node->{ip};
+    }
+
+    return 'ip6' if $all_v6;
+    return 'ip' if $all_v4;
+    return undef;
+}
+
 1;
diff --git a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
index 5df7e5f..a78b646 100644
--- a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
@@ -188,17 +188,23 @@ sub generate_sdn_config {
         my $current_node = eval { $config->get_node($controller->{fabric}, $local_node) };
         die "could not configure EVPN zone $plugin_config->{id}: $@" if $@;
 
-        die "Node $local_node requires an IP in the fabric $fabric->{id} to configure the EVPN zone"
-            if !$current_node->{ip};
+        my $addr_key = PVE::Network::SDN::Controllers::EvpnPlugin::fabric_addr_key($nodes);
+        die
+            "Fabric $fabric->{id} has no consistent address family for all nodes (need all v6 or all v4)"
+            if !$addr_key;
+
+        die
+            "Node $local_node requires a $addr_key address in the fabric $fabric->{id} to configure the EVPN zone"
+            if !$current_node->{$addr_key};
 
         for my $node (values %$nodes) {
-            push @peers, $node->{ip} if $node->{ip};
+            push @peers, $node->{$addr_key};
         }
 
         $loopback = "dummy_$fabric->{id}";
 
-        $ifaceip = $current_node->{ip};
-        $routerid = $current_node->{ip};
+        $ifaceip = $current_node->{$addr_key};
+        $routerid = $current_node->{$addr_key};
     } else {
         die "neither fabric nor peers configured for EVPN controller $controller->{id}";
     }
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH pve-network v2 2/4] sdn: evpn: keep router-id valid on IPv6 underlay
  2026-05-15 11:06 [PATCH network v2 0/4] sdn: evpn: IPv6 underlay support Hannes Laimer
  2026-05-15 11:06 ` [PATCH pve-network v2 1/4] sdn: evpn: prepare " Hannes Laimer
@ 2026-05-15 11:06 ` Hannes Laimer
  2026-05-15 11:06 ` [PATCH pve-network v2 3/4] sdn: stabilize peer IP ordering when generating sdn config Hannes Laimer
  2026-05-15 11:06 ` [PATCH pve-network v2 4/4] sdn: evpn: add tests covering ipv6 underlays Hannes Laimer
  3 siblings, 0 replies; 5+ messages in thread
From: Hannes Laimer @ 2026-05-15 11:06 UTC (permalink / raw)
  To: pve-devel

BGP router-ids are 32-bit values, so use get_router_id() instead of the
address directly, cause that would only work for IPv4 underlays.
And remove dead code in the EVPN zone plugin, we don't need the
router-id there anywhere.

Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
 src/PVE/Network/SDN/Controllers/EvpnPlugin.pm | 4 ++--
 src/PVE/Network/SDN/Zones/EvpnPlugin.pm       | 2 --
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
index 0246788..6568459 100644
--- a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
@@ -160,7 +160,7 @@ sub generate_frr_config {
         $loopback = "dummy_$fabric->{id}";
 
         $ifaceip = $current_node->{$addr_key};
-        $routerid = $current_node->{$addr_key};
+        $routerid = PVE::Network::SDN::Controllers::Plugin::get_router_id($ifaceip, $loopback);
 
         if ($fabric->{protocol} eq 'bgp' && $bgp_mode eq 'external') {
             if (!$current_node->{asn}) {
@@ -387,7 +387,7 @@ sub generate_zone_frr_config {
         $loopback = "dummy_$fabric->{id}";
 
         $ifaceip = $current_node->{$addr_key};
-        $routerid = $current_node->{$addr_key};
+        $routerid = PVE::Network::SDN::Controllers::Plugin::get_router_id($ifaceip, $loopback);
 
     } elsif ($controller->{peers}) {
         @peers = PVE::Tools::split_list($controller->{'peers'}) if $controller->{'peers'};
diff --git a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
index a78b646..0be304a 100644
--- a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
@@ -157,7 +157,6 @@ sub generate_sdn_config {
     my $loopback = undef;
     my $ifaceip = undef;
     my $iface = undef;
-    my $routerid = undef;
 
     if ($controller->{peers}) {
         @peers = PVE::Tools::split_list($controller->{'peers'});
@@ -204,7 +203,6 @@ sub generate_sdn_config {
         $loopback = "dummy_$fabric->{id}";
 
         $ifaceip = $current_node->{$addr_key};
-        $routerid = $current_node->{$addr_key};
     } else {
         die "neither fabric nor peers configured for EVPN controller $controller->{id}";
     }
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH pve-network v2 3/4] sdn: stabilize peer IP ordering when generating sdn config
  2026-05-15 11:06 [PATCH network v2 0/4] sdn: evpn: IPv6 underlay support Hannes Laimer
  2026-05-15 11:06 ` [PATCH pve-network v2 1/4] sdn: evpn: prepare " Hannes Laimer
  2026-05-15 11:06 ` [PATCH pve-network v2 2/4] sdn: evpn: keep router-id valid on IPv6 underlay Hannes Laimer
@ 2026-05-15 11:06 ` Hannes Laimer
  2026-05-15 11:06 ` [PATCH pve-network v2 4/4] sdn: evpn: add tests covering ipv6 underlays Hannes Laimer
  3 siblings, 0 replies; 5+ messages in thread
From: Hannes Laimer @ 2026-05-15 11:06 UTC (permalink / raw)
  To: pve-devel

Sort peer iteration so the generated config is stable across runs.
Without this, hash iteration order leaks into the output and multi-peer
tests fail randomly.

Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
 src/PVE/Network/SDN/Controllers/EvpnPlugin.pm | 4 ++--
 src/PVE/Network/SDN/Zones/EvpnPlugin.pm       | 4 ++--
 src/PVE/Network/SDN/Zones/VxlanPlugin.pm      | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
index 6568459..f23cb8b 100644
--- a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
@@ -380,8 +380,8 @@ sub generate_zone_frr_config {
             return;
         }
 
-        for my $node (values %$nodes) {
-            push @peers, $node->{$addr_key};
+        for my $node_id (sort keys %$nodes) {
+            push @peers, $nodes->{$node_id}->{$addr_key};
         }
 
         $loopback = "dummy_$fabric->{id}";
diff --git a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
index 0be304a..9b06d66 100644
--- a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
@@ -196,8 +196,8 @@ sub generate_sdn_config {
             "Node $local_node requires a $addr_key address in the fabric $fabric->{id} to configure the EVPN zone"
             if !$current_node->{$addr_key};
 
-        for my $node (values %$nodes) {
-            push @peers, $node->{$addr_key};
+        for my $node_id (sort keys %$nodes) {
+            push @peers, $nodes->{$node_id}->{$addr_key};
         }
 
         $loopback = "dummy_$fabric->{id}";
diff --git a/src/PVE/Network/SDN/Zones/VxlanPlugin.pm b/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
index 1db610f..a408261 100644
--- a/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
@@ -127,7 +127,7 @@ sub generate_sdn_config {
     my @iface_config = ();
     push @iface_config, "vxlan-id $tag";
 
-    for my $address (@peers) {
+    for my $address (sort @peers) {
         next if $address eq $ifaceip;
         push @iface_config, "vxlan_remoteip $address";
     }
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH pve-network v2 4/4] sdn: evpn: add tests covering ipv6 underlays
  2026-05-15 11:06 [PATCH network v2 0/4] sdn: evpn: IPv6 underlay support Hannes Laimer
                   ` (2 preceding siblings ...)
  2026-05-15 11:06 ` [PATCH pve-network v2 3/4] sdn: stabilize peer IP ordering when generating sdn config Hannes Laimer
@ 2026-05-15 11:06 ` Hannes Laimer
  3 siblings, 0 replies; 5+ messages in thread
From: Hannes Laimer @ 2026-05-15 11:06 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
 .../expected_controller_config                | 63 ++++++++++++++
 .../expected_sdn_interfaces                   | 58 +++++++++++++
 .../exitnode_local_routing_ipv6/interfaces    |  7 ++
 .../exitnode_local_routing_ipv6/sdn_config    | 27 ++++++
 .../expected_controller_config                | 85 +++++++++++++++++++
 .../expected_sdn_interfaces                   | 64 ++++++++++++++
 .../evpn/openfabric_fabric_ipv6/interfaces    |  6 ++
 .../evpn/openfabric_fabric_ipv6/sdn_config    | 83 ++++++++++++++++++
 .../expected_controller_config                | 74 ++++++++++++++++
 .../expected_sdn_interfaces                   | 58 +++++++++++++
 .../openfabric_fabric_ipv6_only/interfaces    |  6 ++
 .../openfabric_fabric_ipv6_only/sdn_config    | 79 +++++++++++++++++
 12 files changed, 610 insertions(+)
 create mode 100644 src/test/zones/evpn/exitnode_local_routing_ipv6/expected_controller_config
 create mode 100644 src/test/zones/evpn/exitnode_local_routing_ipv6/expected_sdn_interfaces
 create mode 100644 src/test/zones/evpn/exitnode_local_routing_ipv6/interfaces
 create mode 100644 src/test/zones/evpn/exitnode_local_routing_ipv6/sdn_config
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6/expected_controller_config
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6/expected_sdn_interfaces
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6/interfaces
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6/sdn_config
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6_only/expected_controller_config
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6_only/expected_sdn_interfaces
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6_only/interfaces
 create mode 100644 src/test/zones/evpn/openfabric_fabric_ipv6_only/sdn_config

diff --git a/src/test/zones/evpn/exitnode_local_routing_ipv6/expected_controller_config b/src/test/zones/evpn/exitnode_local_routing_ipv6/expected_controller_config
new file mode 100644
index 0000000..382660f
--- /dev/null
+++ b/src/test/zones/evpn/exitnode_local_routing_ipv6/expected_controller_config
@@ -0,0 +1,63 @@
+frr version 10.6.1
+frr defaults datacenter
+hostname localhost
+log syslog informational
+service integrated-vtysh-config
+!
+vrf vrf_myzone
+ vni 1000
+exit-vrf
+!
+router bgp 65000
+ bgp router-id 192.168.0.1
+ no bgp hard-administrative-reset
+ no bgp default ipv4-unicast
+ coalesce-time 1000
+ no bgp graceful-restart notification
+ neighbor VTEP peer-group
+ neighbor VTEP remote-as 65000
+ neighbor VTEP bfd
+ neighbor 192.168.0.2 peer-group VTEP
+ neighbor 192.168.0.3 peer-group VTEP
+ !
+ address-family l2vpn evpn
+  neighbor VTEP activate
+  neighbor VTEP route-map MAP_VTEP_IN in
+  neighbor VTEP route-map MAP_VTEP_OUT out
+  advertise-all-vni
+ exit-address-family
+exit
+!
+router bgp 65000 vrf vrf_myzone
+ bgp router-id 192.168.0.1
+ no bgp hard-administrative-reset
+ no bgp graceful-restart notification
+ !
+ address-family l2vpn evpn
+  default-originate ipv4
+  default-originate ipv6
+ exit-address-family
+exit
+!
+ip prefix-list only_default seq 1 permit 0.0.0.0/0
+!
+ipv6 prefix-list only_default_v6 seq 1 permit ::/0
+!
+route-map MAP_VTEP_IN deny 1
+ match ip address prefix-list only_default
+exit
+!
+route-map MAP_VTEP_IN deny 2
+ match ipv6 address prefix-list only_default_v6
+exit
+!
+route-map MAP_VTEP_IN permit 3
+exit
+!
+route-map MAP_VTEP_OUT permit 1
+exit
+!
+ipv6 route 2a08:2142:302:3::/64 fe80::2 xvrf_myzone
+!
+line vty
+!
diff --git a/src/test/zones/evpn/exitnode_local_routing_ipv6/expected_sdn_interfaces b/src/test/zones/evpn/exitnode_local_routing_ipv6/expected_sdn_interfaces
new file mode 100644
index 0000000..b46d4e7
--- /dev/null
+++ b/src/test/zones/evpn/exitnode_local_routing_ipv6/expected_sdn_interfaces
@@ -0,0 +1,58 @@
+#version:1
+
+auto myvnet
+iface myvnet
+	address 2a08:2142:302:3::1/64
+	bridge_ports vxlan_myvnet
+	bridge_stp off
+	bridge_fd 0
+	mtu 1450
+	ip6-forward on
+	arp-accept on
+	vrf vrf_myzone
+
+auto vrf_myzone
+iface vrf_myzone
+	vrf-table auto
+	post-up ip route del vrf vrf_myzone unreachable default metric 4278198272
+
+auto vrfbr_myzone
+iface vrfbr_myzone
+	bridge-ports vrfvx_myzone
+	bridge_stp off
+	bridge_fd 0
+	mtu 1450
+	vrf vrf_myzone
+
+auto vrfvx_myzone
+iface vrfvx_myzone
+	vxlan-id 1000
+	vxlan-local-tunnelip 192.168.0.1
+	bridge-learning off
+	bridge-arp-nd-suppress on
+	mtu 1450
+
+auto vxlan_myvnet
+iface vxlan_myvnet
+	vxlan-id 100
+	vxlan-local-tunnelip 192.168.0.1
+	bridge-learning off
+	bridge-arp-nd-suppress on
+	mtu 1450
+
+auto xvrf_myzone
+iface xvrf_myzone
+	link-type veth
+	address 10.255.255.1/30
+	address fe80::1/126
+	veth-peer-name xvrfp_myzone
+	mtu 1500
+
+auto xvrfp_myzone
+iface xvrfp_myzone
+	link-type veth
+	address 10.255.255.2/30
+	address fe80::2/126
+	veth-peer-name xvrf_myzone
+	vrf vrf_myzone
+	mtu 1500
diff --git a/src/test/zones/evpn/exitnode_local_routing_ipv6/interfaces b/src/test/zones/evpn/exitnode_local_routing_ipv6/interfaces
new file mode 100644
index 0000000..66bb826
--- /dev/null
+++ b/src/test/zones/evpn/exitnode_local_routing_ipv6/interfaces
@@ -0,0 +1,7 @@
+auto vmbr0
+iface vmbr0 inet static
+	address 192.168.0.1/24
+	gateway 192.168.0.254
+        bridge-ports eth0
+        bridge-stp off
+        bridge-fd 0
diff --git a/src/test/zones/evpn/exitnode_local_routing_ipv6/sdn_config b/src/test/zones/evpn/exitnode_local_routing_ipv6/sdn_config
new file mode 100644
index 0000000..499b13a
--- /dev/null
+++ b/src/test/zones/evpn/exitnode_local_routing_ipv6/sdn_config
@@ -0,0 +1,27 @@
+{
+  version => 1,
+  vnets   => {
+               ids => {
+                        myvnet => { tag => "100", type => "vnet", zone => "myzone" },
+                      },
+             },
+
+  zones   => {
+               ids => { myzone => { ipam => "pve", type => "evpn", controller => "evpnctl", 'vrf-vxlan' => 1000, exitnodes => { 'localhost' => 1 }, 'exitnodes-local-routing' => 1 },
+		      },
+             },
+  controllers  => {
+               ids => { evpnctl => { type => "evpn", 'peers' => '192.168.0.1,192.168.0.2,192.168.0.3', asn => "65000" } },
+             },
+
+  subnets => {
+              ids => { 'myzone-2a08:2142:302:3::-64' => {
+							'type' => 'subnet',
+							'vnet' => 'myvnet',
+							'gateway' => '2a08:2142:302:3::1',
+						  },
+		     }
+	     }
+}
+
+
diff --git a/src/test/zones/evpn/openfabric_fabric_ipv6/expected_controller_config b/src/test/zones/evpn/openfabric_fabric_ipv6/expected_controller_config
new file mode 100644
index 0000000..fc6ebeb
--- /dev/null
+++ b/src/test/zones/evpn/openfabric_fabric_ipv6/expected_controller_config
@@ -0,0 +1,85 @@
+frr version 10.6.1
+frr defaults datacenter
+hostname localhost
+log syslog informational
+service integrated-vtysh-config
+!
+vrf vrf_evpn
+ vni 100
+exit-vrf
+!
+router bgp 65000
+ bgp router-id 17.29.105.96
+ no bgp hard-administrative-reset
+ no bgp default ipv4-unicast
+ coalesce-time 1000
+ no bgp graceful-restart notification
+ neighbor VTEP peer-group
+ neighbor VTEP remote-as 65000
+ neighbor VTEP bfd
+ neighbor VTEP update-source dummy_test
+ neighbor fd00::2 peer-group VTEP
+ neighbor fd00::3 peer-group VTEP
+ !
+ address-family l2vpn evpn
+  neighbor VTEP activate
+  neighbor VTEP route-map MAP_VTEP_IN in
+  neighbor VTEP route-map MAP_VTEP_OUT out
+  advertise-all-vni
+ exit-address-family
+exit
+!
+router bgp 65000 vrf vrf_evpn
+ bgp router-id 17.29.105.96
+ no bgp hard-administrative-reset
+ no bgp graceful-restart notification
+exit
+!
+router openfabric test
+ net 49.0001.1720.2000.3001.00
+exit
+!
+interface dummy_test
+ ip router openfabric test
+ ipv6 router openfabric test
+ openfabric passive
+exit
+!
+interface ens20
+ ip router openfabric test
+ ipv6 router openfabric test
+ openfabric hello-interval 1
+exit
+!
+interface ens21
+ ip router openfabric test
+ ipv6 router openfabric test
+ openfabric hello-interval 1
+exit
+!
+ipv6 access-list pve_openfabric_test_ip6s permit fd00::/64
+!
+access-list pve_openfabric_test_ips permit 172.20.3.0/24
+!
+route-map MAP_VTEP_IN permit 1
+exit
+!
+route-map MAP_VTEP_OUT permit 1
+exit
+!
+route-map pve_openfabric permit 100
+ match ip address pve_openfabric_test_ips
+ set src 172.20.3.1
+exit
+!
+route-map pve_openfabric6 permit 110
+ match ipv6 address pve_openfabric_test_ip6s
+ set src fd00::1
+exit
+!
+ip protocol openfabric route-map pve_openfabric
+!
+ipv6 protocol openfabric route-map pve_openfabric6
+!
+line vty
+!
diff --git a/src/test/zones/evpn/openfabric_fabric_ipv6/expected_sdn_interfaces b/src/test/zones/evpn/openfabric_fabric_ipv6/expected_sdn_interfaces
new file mode 100644
index 0000000..d017713
--- /dev/null
+++ b/src/test/zones/evpn/openfabric_fabric_ipv6/expected_sdn_interfaces
@@ -0,0 +1,64 @@
+#version:1
+
+auto vnet0
+iface vnet0
+	address 10.123.123.1/24
+	hwaddress BC:24:11:3B:39:34
+	bridge_ports vxlan_vnet0
+	bridge_stp off
+	bridge_fd 0
+	mtu 1450
+	ip-forward on
+	arp-accept on
+	vrf vrf_evpn
+
+auto vrf_evpn
+iface vrf_evpn
+	vrf-table auto
+	post-up ip route add vrf vrf_evpn unreachable default metric 4278198272
+
+auto vrfbr_evpn
+iface vrfbr_evpn
+	bridge-ports vrfvx_evpn
+	bridge_stp off
+	bridge_fd 0
+	mtu 1450
+	vrf vrf_evpn
+
+auto vrfvx_evpn
+iface vrfvx_evpn
+	vxlan-id 100
+	vxlan-local-tunnelip fd00::1
+	bridge-learning off
+	bridge-arp-nd-suppress on
+	mtu 1450
+
+auto vxlan_vnet0
+iface vxlan_vnet0
+	vxlan-id 123456
+	vxlan-local-tunnelip fd00::1
+	bridge-learning off
+	bridge-arp-nd-suppress on
+	mtu 1450
+
+auto dummy_test
+iface dummy_test inet static
+	address 172.20.3.1/32
+	link-type dummy
+	ip-forward 1
+
+auto dummy_test
+iface dummy_test inet6 static
+	address fd00::1/128
+	link-type dummy
+	ip-forward 1
+
+auto ens20
+iface ens20 inet static
+	address 172.20.3.1/32
+	ip-forward 1
+
+auto ens21
+iface ens21 inet static
+	address 172.20.3.1/32
+	ip-forward 1
diff --git a/src/test/zones/evpn/openfabric_fabric_ipv6/interfaces b/src/test/zones/evpn/openfabric_fabric_ipv6/interfaces
new file mode 100644
index 0000000..1b4384b
--- /dev/null
+++ b/src/test/zones/evpn/openfabric_fabric_ipv6/interfaces
@@ -0,0 +1,6 @@
+auto vmbr0
+iface vmbr0 inet static
+	address 172.20.3.1/32
+    bridge-ports eth0
+    bridge-stp off
+    bridge-fd 0
diff --git a/src/test/zones/evpn/openfabric_fabric_ipv6/sdn_config b/src/test/zones/evpn/openfabric_fabric_ipv6/sdn_config
new file mode 100644
index 0000000..6fe01cc
--- /dev/null
+++ b/src/test/zones/evpn/openfabric_fabric_ipv6/sdn_config
@@ -0,0 +1,83 @@
+{
+          'zones' => {
+                       'ids' => {
+                                  'evpn' => {
+                                              'type' => 'evpn',
+                                              'ipam' => 'pve',
+                                              'mac' => 'BC:24:11:3B:39:34',
+                                              'controller' => 'ctrl',
+                                              'vrf-vxlan' => 100
+                                            }
+                                }
+                     },
+          'vnets' => {
+                       'ids' => {
+                                  'vnet0' => {
+                                               'zone' => 'evpn',
+                                               'type' => 'vnet',
+                                               'tag' => 123456
+                                             }
+                                }
+                     },
+          'version' => 1,
+          'subnets' => {
+                         'ids' => {
+                                    'evpn-10.123.123.0-24' => {
+                                                                'vnet' => 'vnet0',
+                                                                'type' => 'subnet',
+                                                                'gateway' => '10.123.123.1'
+                                                              }
+                                  }
+                       },
+          'controllers' => {
+                             'ids' => {
+                                        'ctrl' => {
+                                                    'fabric' => 'test',
+                                                    'asn' => 65000,
+                                                    'type' => 'evpn'
+                                                  }
+                                      }
+                           },
+           'fabrics' => {
+                 'ids' => {
+                               'test' => {
+                                           'type' => 'openfabric_fabric',
+                                           'id' => 'test',
+                                           'hello_interval' => 1,
+                                          'ip_prefix' => '172.20.3.0/24',
+                                          'ip6_prefix' => 'fd00::/64',
+                                         },
+                               'test_localhost' => {
+                                                   'interfaces' => [
+                                                                    'name=ens20',
+                                                                    'name=ens21'
+                                                                  ],
+                                                   'id' => 'test_localhost',
+                                                   'type' => 'openfabric_node',
+                                                 'ip' => '172.20.3.1',
+                                                 'ip6' => 'fd00::1',
+                                                 },
+                               'test_pathfinder' => {
+                                                      'id' => 'test_pathfinder',
+                                                      'interfaces' => [
+                                                                       'name=ens20',
+                                                                       'name=ens21'
+                                                                     ],
+                                                     'ip' => '172.20.3.2',
+                                                     'ip6' => 'fd00::2',
+                                                      'type' => 'openfabric_node',
+                                                    },
+                               'test_raider' => {
+                                                 'ip' => '172.20.3.3',
+                                                 'ip6' => 'fd00::3',
+                                                  'type' => 'openfabric_node',
+                                                  'interfaces' => [
+                                                                   'name=ens21',
+                                                                   'name=ens20'
+                                                                 ],
+                                                  'id' => 'test_raider',
+                                                }
+                                     }
+              }
+        };
+
diff --git a/src/test/zones/evpn/openfabric_fabric_ipv6_only/expected_controller_config b/src/test/zones/evpn/openfabric_fabric_ipv6_only/expected_controller_config
new file mode 100644
index 0000000..f3f633a
--- /dev/null
+++ b/src/test/zones/evpn/openfabric_fabric_ipv6_only/expected_controller_config
@@ -0,0 +1,74 @@
+frr version 10.6.1
+frr defaults datacenter
+hostname localhost
+log syslog informational
+service integrated-vtysh-config
+!
+vrf vrf_evpn
+ vni 100
+exit-vrf
+!
+router bgp 65000
+ bgp router-id 17.29.105.96
+ no bgp hard-administrative-reset
+ no bgp default ipv4-unicast
+ coalesce-time 1000
+ no bgp graceful-restart notification
+ neighbor VTEP peer-group
+ neighbor VTEP remote-as 65000
+ neighbor VTEP bfd
+ neighbor VTEP update-source dummy_test
+ neighbor fd00::2 peer-group VTEP
+ neighbor fd00::3 peer-group VTEP
+ !
+ address-family l2vpn evpn
+  neighbor VTEP activate
+  neighbor VTEP route-map MAP_VTEP_IN in
+  neighbor VTEP route-map MAP_VTEP_OUT out
+  advertise-all-vni
+ exit-address-family
+exit
+!
+router bgp 65000 vrf vrf_evpn
+ bgp router-id 17.29.105.96
+ no bgp hard-administrative-reset
+ no bgp graceful-restart notification
+exit
+!
+router openfabric test
+ net 49.0001.0000.0000.0001.00
+exit
+!
+interface dummy_test
+ ipv6 router openfabric test
+ openfabric passive
+exit
+!
+interface ens20
+ ipv6 router openfabric test
+ openfabric hello-interval 1
+exit
+!
+interface ens21
+ ipv6 router openfabric test
+ openfabric hello-interval 1
+exit
+!
+ipv6 access-list pve_openfabric_test_ip6s permit fd00::/64
+!
+route-map MAP_VTEP_IN permit 1
+exit
+!
+route-map MAP_VTEP_OUT permit 1
+exit
+!
+route-map pve_openfabric6 permit 100
+ match ipv6 address pve_openfabric_test_ip6s
+ set src fd00::1
+exit
+!
+!
+ipv6 protocol openfabric route-map pve_openfabric6
+!
+line vty
+!
diff --git a/src/test/zones/evpn/openfabric_fabric_ipv6_only/expected_sdn_interfaces b/src/test/zones/evpn/openfabric_fabric_ipv6_only/expected_sdn_interfaces
new file mode 100644
index 0000000..51507d7
--- /dev/null
+++ b/src/test/zones/evpn/openfabric_fabric_ipv6_only/expected_sdn_interfaces
@@ -0,0 +1,58 @@
+#version:1
+
+auto vnet0
+iface vnet0
+	address 10.123.123.1/24
+	hwaddress BC:24:11:3B:39:34
+	bridge_ports vxlan_vnet0
+	bridge_stp off
+	bridge_fd 0
+	mtu 1450
+	ip-forward on
+	arp-accept on
+	vrf vrf_evpn
+
+auto vrf_evpn
+iface vrf_evpn
+	vrf-table auto
+	post-up ip route add vrf vrf_evpn unreachable default metric 4278198272
+
+auto vrfbr_evpn
+iface vrfbr_evpn
+	bridge-ports vrfvx_evpn
+	bridge_stp off
+	bridge_fd 0
+	mtu 1450
+	vrf vrf_evpn
+
+auto vrfvx_evpn
+iface vrfvx_evpn
+	vxlan-id 100
+	vxlan-local-tunnelip fd00::1
+	bridge-learning off
+	bridge-arp-nd-suppress on
+	mtu 1450
+
+auto vxlan_vnet0
+iface vxlan_vnet0
+	vxlan-id 123456
+	vxlan-local-tunnelip fd00::1
+	bridge-learning off
+	bridge-arp-nd-suppress on
+	mtu 1450
+
+auto dummy_test
+iface dummy_test inet6 static
+	address fd00::1/128
+	link-type dummy
+	ip-forward 1
+
+auto ens20
+iface ens20 inet6 static
+	address fd00::1/128
+	ip-forward 1
+
+auto ens21
+iface ens21 inet6 static
+	address fd00::1/128
+	ip-forward 1
diff --git a/src/test/zones/evpn/openfabric_fabric_ipv6_only/interfaces b/src/test/zones/evpn/openfabric_fabric_ipv6_only/interfaces
new file mode 100644
index 0000000..1b4384b
--- /dev/null
+++ b/src/test/zones/evpn/openfabric_fabric_ipv6_only/interfaces
@@ -0,0 +1,6 @@
+auto vmbr0
+iface vmbr0 inet static
+	address 172.20.3.1/32
+    bridge-ports eth0
+    bridge-stp off
+    bridge-fd 0
diff --git a/src/test/zones/evpn/openfabric_fabric_ipv6_only/sdn_config b/src/test/zones/evpn/openfabric_fabric_ipv6_only/sdn_config
new file mode 100644
index 0000000..5dc2163
--- /dev/null
+++ b/src/test/zones/evpn/openfabric_fabric_ipv6_only/sdn_config
@@ -0,0 +1,79 @@
+{
+          'zones' => {
+                       'ids' => {
+                                  'evpn' => {
+                                              'type' => 'evpn',
+                                              'ipam' => 'pve',
+                                              'mac' => 'BC:24:11:3B:39:34',
+                                              'controller' => 'ctrl',
+                                              'vrf-vxlan' => 100
+                                            }
+                                }
+                     },
+          'vnets' => {
+                       'ids' => {
+                                  'vnet0' => {
+                                               'zone' => 'evpn',
+                                               'type' => 'vnet',
+                                               'tag' => 123456
+                                             }
+                                }
+                     },
+          'version' => 1,
+          'subnets' => {
+                         'ids' => {
+                                    'evpn-10.123.123.0-24' => {
+                                                                'vnet' => 'vnet0',
+                                                                'type' => 'subnet',
+                                                                'gateway' => '10.123.123.1'
+                                                              }
+                                  }
+                       },
+          'controllers' => {
+                             'ids' => {
+                                        'ctrl' => {
+                                                    'fabric' => 'test',
+                                                    'asn' => 65000,
+                                                    'type' => 'evpn'
+                                                  }
+                                      }
+                           },
+           'fabrics' => {
+                 'ids' => {
+                               'test' => {
+                                           'type' => 'openfabric_fabric',
+                                           'id' => 'test',
+                                           'hello_interval' => 1,
+                                          'ip6_prefix' => 'fd00::/64',
+                                         },
+                               'test_localhost' => {
+                                                   'interfaces' => [
+                                                                    'name=ens20',
+                                                                    'name=ens21'
+                                                                  ],
+                                                   'id' => 'test_localhost',
+                                                   'type' => 'openfabric_node',
+                                                 'ip6' => 'fd00::1',
+                                                 },
+                               'test_pathfinder' => {
+                                                      'id' => 'test_pathfinder',
+                                                      'interfaces' => [
+                                                                       'name=ens20',
+                                                                       'name=ens21'
+                                                                     ],
+                                                     'ip6' => 'fd00::2',
+                                                      'type' => 'openfabric_node',
+                                                    },
+                               'test_raider' => {
+                                                 'ip6' => 'fd00::3',
+                                                  'type' => 'openfabric_node',
+                                                  'interfaces' => [
+                                                                   'name=ens21',
+                                                                   'name=ens20'
+                                                                 ],
+                                                  'id' => 'test_raider',
+                                                }
+                                     }
+              }
+        };
+
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-05-15 11:07 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-15 11:06 [PATCH network v2 0/4] sdn: evpn: IPv6 underlay support Hannes Laimer
2026-05-15 11:06 ` [PATCH pve-network v2 1/4] sdn: evpn: prepare " Hannes Laimer
2026-05-15 11:06 ` [PATCH pve-network v2 2/4] sdn: evpn: keep router-id valid on IPv6 underlay Hannes Laimer
2026-05-15 11:06 ` [PATCH pve-network v2 3/4] sdn: stabilize peer IP ordering when generating sdn config Hannes Laimer
2026-05-15 11:06 ` [PATCH pve-network v2 4/4] sdn: evpn: add tests covering ipv6 underlays Hannes Laimer

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