* [pve-devel] [PATCH network 0/6] add EVPN IPv6 underlay support
@ 2026-01-22 13:51 Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 1/6] sdn: evpn: prepare " Hannes Laimer
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Hannes Laimer @ 2026-01-22 13:51 UTC (permalink / raw)
To: pve-devel
This adds basic IPv6 underlay support for EVPN zones.
This does rely on [1], without it FRR won't advertise v6 next-hops. So
this should not be applied before the FRR version we ship includes [1],
based on @Gabriel's estimate this could be included in a version that may
be released early next month(february). I did test this with the latest
master of FRR.
(this also needs the changes to `get_local_route_ip` added with [2])
Aside from that, like for VXLAN, we prefer IPv6 if the underlaying
fabric should offer both, and we don't support peer addresses with
different IP versions. So either all v6 or all v4.
[1] https://github.com/FRRouting/frr/pull/19498
[2] https://lore.proxmox.com/pve-devel/20260116110843.89615-2-h.laimer@proxmox.com/T/#u
pve-network:
Hannes Laimer (6):
sdn: evpn: prepare IPv6 underlay support
sdn: controller: fallback to interface mac if no master
sdn: controller: prevent invalid router-id generation from zero mac
sdn: evpn: keep router-id valid on IPv6 underlay
sdn: vxlan: sort peer IPs when generating sdn config
sdn: evpn: add tests covering ipv6 underlays
src/PVE/Network/SDN/Controllers/EvpnPlugin.pm | 70 ++++++++++++---
src/PVE/Network/SDN/Controllers/Plugin.pm | 9 +-
src/PVE/Network/SDN/Zones/EvpnPlugin.pm | 28 ++++--
src/PVE/Network/SDN/Zones/VxlanPlugin.pm | 2 +-
.../expected_controller_config | 64 ++++++++++++++
.../expected_sdn_interfaces | 56 ++++++++++++
.../exitnode_local_routing_ipv6/interfaces | 7 ++
.../exitnode_local_routing_ipv6/sdn_config | 27 ++++++
.../expected_controller_config | 86 +++++++++++++++++++
.../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 +++++++++++++++++
16 files changed, 701 insertions(+), 18 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:
16 files changed, 701 insertions(+), 18 deletions(-)
--
Generated by git-murpp 0.8.1
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH pve-network 1/6] sdn: evpn: prepare IPv6 underlay support
2026-01-22 13:51 [pve-devel] [PATCH network 0/6] add EVPN IPv6 underlay support Hannes Laimer
@ 2026-01-22 13:51 ` Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 2/6] sdn: controller: fallback to interface mac if no master Hannes Laimer
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Hannes Laimer @ 2026-01-22 13:51 UTC (permalink / raw)
To: pve-devel
Align EVPN's fabric and peer handling with VXLAN. So IPv6-capable
underlays can be selected and IPv6 peers configured.
Like with VXLAN, we don't support a dual-stack underlay, the reasoning
is the same. There is no real value adding that.
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/PVE/Network/SDN/Controllers/EvpnPlugin.pm | 70 ++++++++++++++++---
src/PVE/Network/SDN/Zones/EvpnPlugin.pm | 28 ++++++--
2 files changed, 83 insertions(+), 15 deletions(-)
diff --git a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
index e53000a..88bdcb8 100644
--- a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
@@ -82,22 +82,41 @@ sub generate_frr_config {
return;
}
- if (!$current_node->{ip}) {
+ 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};
+ }
+
+ my $addr_key;
+ if ($all_v6) {
+ $addr_key = 'ip6';
+ } elsif ($all_v4) {
+ $addr_key = 'ip';
+ } else {
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} if $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 ($plugin_config->{'peers'}) {
@peers = PVE::Tools::split_list($plugin_config->{'peers'});
@@ -216,21 +235,40 @@ sub generate_zone_frr_config {
return;
}
- if (!$current_node->{ip}) {
+ 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};
+ }
+
+ my $addr_key;
+ if ($all_v6) {
+ $addr_key = 'ip6';
+ } elsif ($all_v4) {
+ $addr_key = 'ip';
+ } else {
+ 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} if $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'};
@@ -497,6 +535,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;
+ }
+ }
}
}
diff --git a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
index 6d89499..227d917 100644
--- a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
@@ -176,17 +176,35 @@ 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 $all_v6 = 1;
+ my $all_v4 = 1;
+ for my $node (values %$nodes) {
+ $all_v6 = 0 if !$node->{ip6};
+ $all_v4 = 0 if !$node->{ip};
+ }
+
+ my $addr_key;
+ if ($all_v6) {
+ $addr_key = 'ip6';
+ } elsif ($all_v4) {
+ $addr_key = 'ip';
+ } else {
+ die
+ "Fabric $fabric->{id} has no consistent address family for all nodes (need all v6 or all v4)";
+ }
+
+ 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} if $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
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH pve-network 2/6] sdn: controller: fallback to interface mac if no master
2026-01-22 13:51 [pve-devel] [PATCH network 0/6] add EVPN IPv6 underlay support Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 1/6] sdn: evpn: prepare " Hannes Laimer
@ 2026-01-22 13:51 ` Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 3/6] sdn: controller: prevent invalid router-id generation from zero mac Hannes Laimer
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Hannes Laimer @ 2026-01-22 13:51 UTC (permalink / raw)
To: pve-devel
For IPv6 underlays, we can't directly use the IP for the router-id.
Therefore, `get_router_id` derives a unique ID from the last 4 bytes of
the interface MAC.
However, the current MAC retrieval logic only checks the master device.
This fails for standalone interfaces that do not have a master, such as
`dummy_` interfaces used for fabrics.
Update `read_iface_mac` to fall back to the interface's own address if
no master address is found.
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/PVE/Network/SDN/Controllers/Plugin.pm | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/PVE/Network/SDN/Controllers/Plugin.pm b/src/PVE/Network/SDN/Controllers/Plugin.pm
index d70e518..cab036a 100644
--- a/src/PVE/Network/SDN/Controllers/Plugin.pm
+++ b/src/PVE/Network/SDN/Controllers/Plugin.pm
@@ -105,7 +105,9 @@ sub on_update_hook {
sub read_iface_mac {
my ($iface) = @_;
- return PVE::Tools::file_read_firstline("/sys/class/net/$iface/master/address");
+ my $mac = PVE::Tools::file_read_firstline("/sys/class/net/$iface/master/address");
+ return $mac if $mac;
+ return PVE::Tools::file_read_firstline("/sys/class/net/$iface/address");
}
sub get_router_id {
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH pve-network 3/6] sdn: controller: prevent invalid router-id generation from zero mac
2026-01-22 13:51 [pve-devel] [PATCH network 0/6] add EVPN IPv6 underlay support Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 1/6] sdn: evpn: prepare " Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 2/6] sdn: controller: fallback to interface mac if no master Hannes Laimer
@ 2026-01-22 13:51 ` Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 4/6] sdn: evpn: keep router-id valid on IPv6 underlay Hannes Laimer
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Hannes Laimer @ 2026-01-22 13:51 UTC (permalink / raw)
To: pve-devel
When a standard loopback interface is used, the retrieved MAC is
typically 00:00:00:00:00:00. This causes the router-id generation logic
to produce "0.0.0.0", which is an invalid BGP ID.
Explicitly check for a zero MAC address and fail with a descriptive
error.
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/PVE/Network/SDN/Controllers/Plugin.pm | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/PVE/Network/SDN/Controllers/Plugin.pm b/src/PVE/Network/SDN/Controllers/Plugin.pm
index cab036a..45e2f46 100644
--- a/src/PVE/Network/SDN/Controllers/Plugin.pm
+++ b/src/PVE/Network/SDN/Controllers/Plugin.pm
@@ -120,6 +120,11 @@ sub get_router_id {
die "can't autofind a router-id value from ip or mac" if !$mac;
+ if ($mac eq '00:00:00:00:00:00') {
+ die "Interface $iface has a zero MAC address. Cannot derive a BGP router-id. "
+ . "Please use a dummy interface or assign an IPv4 address to $iface.\n";
+ }
+
my @mac_bytes = split(':', $mac);
return
hex($mac_bytes[2]) . "."
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH pve-network 4/6] sdn: evpn: keep router-id valid on IPv6 underlay
2026-01-22 13:51 [pve-devel] [PATCH network 0/6] add EVPN IPv6 underlay support Hannes Laimer
` (2 preceding siblings ...)
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 3/6] sdn: controller: prevent invalid router-id generation from zero mac Hannes Laimer
@ 2026-01-22 13:51 ` Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 5/6] sdn: vxlan: sort peer IPs when generating sdn config Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 6/6] sdn: evpn: add tests covering ipv6 underlays Hannes Laimer
5 siblings, 0 replies; 7+ messages in thread
From: Hannes Laimer @ 2026-01-22 13:51 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 88bdcb8..8bc00c7 100644
--- a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
@@ -116,7 +116,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);
} elsif ($plugin_config->{'peers'}) {
@peers = PVE::Tools::split_list($plugin_config->{'peers'});
@@ -268,7 +268,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 227d917..9aeced5 100644
--- a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
@@ -145,7 +145,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
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH pve-network 5/6] sdn: vxlan: sort peer IPs when generating sdn config
2026-01-22 13:51 [pve-devel] [PATCH network 0/6] add EVPN IPv6 underlay support Hannes Laimer
` (3 preceding siblings ...)
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 4/6] sdn: evpn: keep router-id valid on IPv6 underlay Hannes Laimer
@ 2026-01-22 13:51 ` Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 6/6] sdn: evpn: add tests covering ipv6 underlays Hannes Laimer
5 siblings, 0 replies; 7+ messages in thread
From: Hannes Laimer @ 2026-01-22 13:51 UTC (permalink / raw)
To: pve-devel
So we have a stable ordering of the `vxlan_remoteip` entries,
and tests with more than one peer don't fail randomly.
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/PVE/Network/SDN/Zones/VxlanPlugin.pm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/PVE/Network/SDN/Zones/VxlanPlugin.pm b/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
index ac006b5..5a3a706 100644
--- a/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
@@ -148,7 +148,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
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH pve-network 6/6] sdn: evpn: add tests covering ipv6 underlays
2026-01-22 13:51 [pve-devel] [PATCH network 0/6] add EVPN IPv6 underlay support Hannes Laimer
` (4 preceding siblings ...)
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 5/6] sdn: vxlan: sort peer IPs when generating sdn config Hannes Laimer
@ 2026-01-22 13:51 ` Hannes Laimer
5 siblings, 0 replies; 7+ messages in thread
From: Hannes Laimer @ 2026-01-22 13:51 UTC (permalink / raw)
To: pve-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
.../expected_controller_config | 64 ++++++++++++++
.../expected_sdn_interfaces | 56 ++++++++++++
.../exitnode_local_routing_ipv6/interfaces | 7 ++
.../exitnode_local_routing_ipv6/sdn_config | 27 ++++++
.../expected_controller_config | 86 +++++++++++++++++++
.../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..8d7c225
--- /dev/null
+++ b/src/test/zones/evpn/exitnode_local_routing_ipv6/expected_controller_config
@@ -0,0 +1,64 @@
+frr version 10.4.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
+!
+ip route 2a08:2142:302:3::/64 10.255.255.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..53a03a9
--- /dev/null
+++ b/src/test/zones/evpn/exitnode_local_routing_ipv6/expected_sdn_interfaces
@@ -0,0 +1,56 @@
+#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
+ veth-peer-name xvrfp_myzone
+ mtu 1500
+
+auto xvrfp_myzone
+iface xvrfp_myzone
+ link-type veth
+ address 10.255.255.2/30
+ 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..4402476
--- /dev/null
+++ b/src/test/zones/evpn/openfabric_fabric_ipv6/expected_controller_config
@@ -0,0 +1,86 @@
+frr version 10.4.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
+!
+route-map MAP_VTEP_IN permit 1
+exit
+!
+route-map MAP_VTEP_OUT permit 1
+exit
+router openfabric test
+ net 49.0001.1720.2000.3001.00
+exit
+!
+interface dummy_test
+ ipv6 router openfabric test
+ ip router openfabric test
+ openfabric passive
+exit
+!
+interface ens20
+ ipv6 router openfabric test
+ ip router openfabric test
+ openfabric hello-interval 1
+exit
+!
+interface ens21
+ ipv6 router openfabric test
+ ip router openfabric test
+ openfabric hello-interval 1
+exit
+!
+access-list pve_openfabric_test_ips permit 172.20.3.0/24
+!
+ipv6 access-list pve_openfabric_test_ip6s permit fd00::/64
+!
+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..fbdc168
--- /dev/null
+++ b/src/test/zones/evpn/openfabric_fabric_ipv6_only/expected_controller_config
@@ -0,0 +1,74 @@
+frr version 10.4.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
+!
+route-map MAP_VTEP_IN permit 1
+exit
+!
+route-map MAP_VTEP_OUT permit 1
+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 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
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-01-22 13:52 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-22 13:51 [pve-devel] [PATCH network 0/6] add EVPN IPv6 underlay support Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 1/6] sdn: evpn: prepare " Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 2/6] sdn: controller: fallback to interface mac if no master Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 3/6] sdn: controller: prevent invalid router-id generation from zero mac Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 4/6] sdn: evpn: keep router-id valid on IPv6 underlay Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 5/6] sdn: vxlan: sort peer IPs when generating sdn config Hannes Laimer
2026-01-22 13:51 ` [pve-devel] [PATCH pve-network 6/6] 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