* [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 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.