all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Hannes Laimer <h.laimer@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH pve-network 2/2] sdn: vxlan: enforce single address family in peers list
Date: Fri, 16 Jan 2026 12:08:42 +0100	[thread overview]
Message-ID: <20260116110843.89615-3-h.laimer@proxmox.com> (raw)
In-Reply-To: <20260116110843.89615-1-h.laimer@proxmox.com>

We want the underlay to either be IPv4 or IPv6. A dual-stack underlay
adds ambiguity and extra complexity in source selection and validation
without a real use-case.

This includes tests for fabrics, we prefer IPv6 if the fabric offers
both.

Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
 src/PVE/Network/SDN/Zones/VxlanPlugin.pm      | 42 +++++++++++++--
 .../vxlan/fabric_ipv4/expected_sdn_interfaces | 26 +++++++++
 src/test/zones/vxlan/fabric_ipv4/interfaces   |  5 ++
 src/test/zones/vxlan/fabric_ipv4/sdn_config   | 50 +++++++++++++++++
 .../vxlan/fabric_ipv6/expected_sdn_interfaces | 32 +++++++++++
 src/test/zones/vxlan/fabric_ipv6/interfaces   |  5 ++
 src/test/zones/vxlan/fabric_ipv6/sdn_config   | 54 +++++++++++++++++++
 7 files changed, 210 insertions(+), 4 deletions(-)
 create mode 100644 src/test/zones/vxlan/fabric_ipv4/expected_sdn_interfaces
 create mode 100644 src/test/zones/vxlan/fabric_ipv4/interfaces
 create mode 100644 src/test/zones/vxlan/fabric_ipv4/sdn_config
 create mode 100644 src/test/zones/vxlan/fabric_ipv6/expected_sdn_interfaces
 create mode 100644 src/test/zones/vxlan/fabric_ipv6/interfaces
 create mode 100644 src/test/zones/vxlan/fabric_ipv6/sdn_config

diff --git a/src/PVE/Network/SDN/Zones/VxlanPlugin.pm b/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
index 1db610f..ac006b5 100644
--- a/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
@@ -4,6 +4,7 @@ use strict;
 use warnings;
 use PVE::Network::SDN::Zones::Plugin;
 use PVE::Tools qw($IPV4RE);
+use Net::IP qw(ip_is_ipv6);
 use PVE::INotify;
 use PVE::Network::SDN::Controllers::EvpnPlugin;
 use PVE::Exception qw(raise raise_param_exc);
@@ -104,15 +105,35 @@ sub generate_sdn_config {
         my $current_node = eval { $config->get_node($plugin_config->{fabric}, $local_node) };
         die "could not configure VXLAN zone $plugin_config->{id}: $@" if $@;
 
+        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};
+        }
+
+        # the following checks are not strictly necesarry cause we we shouldn't
+        # even get here if there are nodes on the fabric that don't have an
+        # address on any of the prefixes defined for the fabric
+        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 an IP in the fabric $fabric->{id} to configure the VXLAN zone $plugin_config->{id}"
-            if !$current_node->{ip};
+            "Node $local_node requires a $addr_key address in fabric $fabric->{id} to configure VXLAN zone $plugin_config->{id}"
+            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};
         }
 
-        $ifaceip = $current_node->{ip};
+        $ifaceip = $current_node->{$addr_key};
     } else {
         die "neither peers nor fabric configured for VXLAN zone $plugin_config->{id}";
     }
@@ -163,6 +184,19 @@ sub on_update_hook {
             fabric => "must have exactly one of peers / fabric defined",
         });
     }
+
+    if ($zone->{peers}) {
+        my @peers = PVE::Tools::split_list($zone->{peers});
+        my $family;
+
+        foreach my $peer (@peers) {
+            my $peer_family = ip_is_ipv6($peer) ? 6 : 4;
+            if (defined($family) && $family != $peer_family) {
+                raise_param_exc({ peers => "must contain only IPv4 or only IPv6 addresses" });
+            }
+            $family = $peer_family;
+        }
+    }
 }
 
 sub vnet_update_hook {
diff --git a/src/test/zones/vxlan/fabric_ipv4/expected_sdn_interfaces b/src/test/zones/vxlan/fabric_ipv4/expected_sdn_interfaces
new file mode 100644
index 0000000..3423104
--- /dev/null
+++ b/src/test/zones/vxlan/fabric_ipv4/expected_sdn_interfaces
@@ -0,0 +1,26 @@
+#version:1
+
+auto myvnet
+iface myvnet
+	bridge_ports vxlan_myvnet
+	bridge_stp off
+	bridge_fd 0
+	mtu 1450
+
+auto vxlan_myvnet
+iface vxlan_myvnet
+	vxlan-id 100
+	vxlan_remoteip 172.20.3.2
+	vxlan_remoteip 172.20.3.3
+	mtu 1450
+
+auto dummy_test
+iface dummy_test inet static
+	address 172.20.3.1/32
+	link-type dummy
+	ip-forward 1
+
+auto ens18
+iface ens18 inet static
+	address 172.20.3.1/32
+	ip-forward 1
diff --git a/src/test/zones/vxlan/fabric_ipv4/interfaces b/src/test/zones/vxlan/fabric_ipv4/interfaces
new file mode 100644
index 0000000..68b6a88
--- /dev/null
+++ b/src/test/zones/vxlan/fabric_ipv4/interfaces
@@ -0,0 +1,5 @@
+auto vmbr0
+iface vmbr0 inet manual
+        bridge-ports eth0
+        bridge-stp off
+        bridge-fd 0
diff --git a/src/test/zones/vxlan/fabric_ipv4/sdn_config b/src/test/zones/vxlan/fabric_ipv4/sdn_config
new file mode 100644
index 0000000..eaaf3a9
--- /dev/null
+++ b/src/test/zones/vxlan/fabric_ipv4/sdn_config
@@ -0,0 +1,50 @@
+{
+  version => 1,
+  vnets   => {
+               ids => {
+                        myvnet => { tag => 100, type => "vnet", zone => "myzone" },
+                      },
+             },
+  zones   => {
+               ids => {
+                        myzone => {
+                                    ipam => "pve",
+                                    type => "vxlan",
+                                    fabric => "test",
+                                  },
+                      },
+             },
+  fabrics => {
+               ids => {
+                        test => {
+                                  type => 'openfabric_fabric',
+                                  id => 'test',
+                                  ip_prefix => '172.20.3.0/24',
+                                },
+                        test_localhost => {
+                                       id => 'test_localhost',
+                                       type => 'openfabric_node',
+                                       interfaces => [
+                                         'name=ens18',
+                                       ],
+                                       ip => '172.20.3.1',
+                                     },
+                        test_node2 => {
+                                   id => 'test_node2',
+                                   type => 'openfabric_node',
+                                   interfaces => [
+                                     'name=ens18',
+                                   ],
+                                   ip => '172.20.3.2',
+                                 },
+                        test_node3 => {
+                                   id => 'test_node3',
+                                   type => 'openfabric_node',
+                                   interfaces => [
+                                     'name=ens18',
+                                   ],
+                                   ip => '172.20.3.3',
+                                 },
+                      },
+             },
+}
diff --git a/src/test/zones/vxlan/fabric_ipv6/expected_sdn_interfaces b/src/test/zones/vxlan/fabric_ipv6/expected_sdn_interfaces
new file mode 100644
index 0000000..7351fc9
--- /dev/null
+++ b/src/test/zones/vxlan/fabric_ipv6/expected_sdn_interfaces
@@ -0,0 +1,32 @@
+#version:1
+
+auto myvnet
+iface myvnet
+	bridge_ports vxlan_myvnet
+	bridge_stp off
+	bridge_fd 0
+	mtu 1450
+
+auto vxlan_myvnet
+iface vxlan_myvnet
+	vxlan-id 100
+	vxlan_remoteip fd00::2
+	vxlan_remoteip fd00::3
+	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 ens18
+iface ens18 inet static
+	address 172.20.3.1/32
+	ip-forward 1
diff --git a/src/test/zones/vxlan/fabric_ipv6/interfaces b/src/test/zones/vxlan/fabric_ipv6/interfaces
new file mode 100644
index 0000000..68b6a88
--- /dev/null
+++ b/src/test/zones/vxlan/fabric_ipv6/interfaces
@@ -0,0 +1,5 @@
+auto vmbr0
+iface vmbr0 inet manual
+        bridge-ports eth0
+        bridge-stp off
+        bridge-fd 0
diff --git a/src/test/zones/vxlan/fabric_ipv6/sdn_config b/src/test/zones/vxlan/fabric_ipv6/sdn_config
new file mode 100644
index 0000000..f463a88
--- /dev/null
+++ b/src/test/zones/vxlan/fabric_ipv6/sdn_config
@@ -0,0 +1,54 @@
+{
+  version => 1,
+  vnets   => {
+               ids => {
+                        myvnet => { tag => 100, type => "vnet", zone => "myzone" },
+                      },
+             },
+  zones   => {
+               ids => {
+                        myzone => {
+                                    ipam => "pve",
+                                    type => "vxlan",
+                                    fabric => "test",
+                                  },
+                      },
+             },
+  fabrics => {
+               ids => {
+                        test => {
+                                  type => 'openfabric_fabric',
+                                  id => 'test',
+                                  ip_prefix => '172.20.3.0/24',
+                                  ip6_prefix => 'fd00::/64',
+                                },
+                        test_localhost => {
+                                       id => 'test_localhost',
+                                       type => 'openfabric_node',
+                                       interfaces => [
+                                         'name=ens18',
+                                       ],
+                                       ip => '172.20.3.1',
+                                       ip6 => 'fd00::1',
+                                     },
+                        test_node2 => {
+                                   id => 'test_node2',
+                                   type => 'openfabric_node',
+                                   interfaces => [
+                                     'name=ens18',
+                                   ],
+                                   ip => '172.20.3.2',
+                                   ip6 => 'fd00::2',
+                                 },
+                        test_node3 => {
+                                   id => 'test_node3',
+                                   type => 'openfabric_node',
+                                   interfaces => [
+                                     'name=ens18',
+                                   ],
+                                   ip => '172.20.3.3',
+                                   ip6 => 'fd00::3',
+                                 },
+                      },
+             },
+}
-- 
2.47.3



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  parent reply	other threads:[~2026-01-16 11:08 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-16 11:08 [pve-devel] [PATCH docs/network 0/3] SDN VXLAN IPv6 underlay support Hannes Laimer
2026-01-16 11:08 ` [pve-devel] [PATCH pve-network 1/2] sdn: vxlan: make local underlay selection work for IPv6 peers Hannes Laimer
2026-01-16 11:08 ` Hannes Laimer [this message]
2026-01-16 11:08 ` [pve-devel] [PATCH pve-docs 1/1] sdn: vxlan: add short section about underlay address family Hannes Laimer

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20260116110843.89615-3-h.laimer@proxmox.com \
    --to=h.laimer@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

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

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