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: [PATCH pve-network v2 06/11] sdn: evpn: accept untracked IPv6 NA on EVPN vnet bridges
Date: Thu, 30 Apr 2026 16:29:48 +0200	[thread overview]
Message-ID: <20260430142953.315412-7-h.laimer@proxmox.com> (raw)
In-Reply-To: <20260430142953.315412-1-h.laimer@proxmox.com>

In EVPN setups with per-node anycast first-hop gateways, guests may use
the shared gateway link-local address as next-hop, while return traffic
targets the guest GUA. If an exit node has no neighbor entry for that
GUA, it sends an NS.

Only the exit-node kernel tracks that NS state. Because ND traffic is
seen across EVPN nodes, a non-exit node can receive the guest's NA
without a matching local INCOMPLETE entry and can treat it as untracked.
Ignoring that NA prevents neighbor learning and can break IPv6 return
traffic.

Set `accept_untracked_na=2`[1] on EVPN vnet bridges that have IPv6
subnets so valid NA replies are accepted in this distributed gateway
topology.

Router Advertisements can trigger this, but RA presence is neither a
necessary nor a sufficient selector. Keying this to EVPN vnets with IPv6
subnets is therefore more robust, even though it is broader than just
looking at whether RAs are enabled.

Without this, deployments depend on pre-populated neighbor state (for
example guest-initiated traffic/pings first), which is fragile and
causes intermittent first-packet IPv6 failures.

[1] https://docs.kernel.org/networking/ip-sysctl.html#proc-sys-net-ipv6-variables

Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
 src/PVE/Network/SDN/Zones/EvpnPlugin.pm                     | 6 ++++++
 src/test/zones/evpn/exitnode_snat/expected_sdn_interfaces   | 1 +
 .../zones/evpn/exitnodenullroute/expected_sdn_interfaces    | 1 +
 src/test/zones/evpn/ipv4ipv6/expected_sdn_interfaces        | 1 +
 .../zones/evpn/ipv4ipv6nogateway/expected_sdn_interfaces    | 1 +
 src/test/zones/evpn/ipv6/expected_sdn_interfaces            | 1 +
 src/test/zones/evpn/ipv6underlay/expected_sdn_interfaces    | 1 +
 src/test/zones/evpn/slaac/expected_sdn_interfaces           | 1 +
 8 files changed, 13 insertions(+)

diff --git a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
index a7daced..b3c6d6a 100644
--- a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
@@ -231,6 +231,7 @@ sub generate_sdn_config {
     my $address = {};
     my $ipv4 = undef;
     my $ipv6 = undef;
+    my $has_ipv6_subnet = undef;
     my $enable_forward_v4 = undef;
     my $enable_forward_v6 = undef;
     my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid, 1);
@@ -246,6 +247,8 @@ sub generate_sdn_config {
             $address->{$gateway} = 1;
         }
 
+        $has_ipv6_subnet = 1 if $subnet_ip && Net::IP::ip_is_ipv6($subnet_ip);
+
         my $iptables = undef;
         my $checkrouteip = undef;
         my $ipversion = 4;
@@ -296,6 +299,9 @@ sub generate_sdn_config {
     push @iface_config, "ip-forward on" if $enable_forward_v4;
     push @iface_config, "ip6-forward on" if $enable_forward_v6;
     push @iface_config, "arp-accept on" if $ipv4 || $ipv6;
+    push @iface_config,
+        "post-up echo 2 > /proc/sys/net/ipv6/conf/$vnetid/accept_untracked_na || true"
+        if $has_ipv6_subnet;
     push @iface_config, "vrf $vrf_iface" if $vrf_iface;
     push(@{ $config->{$vnetid} }, @iface_config) if !$config->{$vnetid};
 
diff --git a/src/test/zones/evpn/exitnode_snat/expected_sdn_interfaces b/src/test/zones/evpn/exitnode_snat/expected_sdn_interfaces
index 47df77a..e63c409 100644
--- a/src/test/zones/evpn/exitnode_snat/expected_sdn_interfaces
+++ b/src/test/zones/evpn/exitnode_snat/expected_sdn_interfaces
@@ -28,6 +28,7 @@ iface myvnet2
 	mtu 1450
 	ip6-forward on
 	arp-accept on
+	post-up echo 2 > /proc/sys/net/ipv6/conf/myvnet2/accept_untracked_na || true
 	vrf vrf_myzone
 
 auto vrf_myzone
diff --git a/src/test/zones/evpn/exitnodenullroute/expected_sdn_interfaces b/src/test/zones/evpn/exitnodenullroute/expected_sdn_interfaces
index 4bf5ccf..81a3b39 100644
--- a/src/test/zones/evpn/exitnodenullroute/expected_sdn_interfaces
+++ b/src/test/zones/evpn/exitnodenullroute/expected_sdn_interfaces
@@ -15,6 +15,7 @@ iface myvnet
 	ip-forward on
 	ip6-forward on
 	arp-accept on
+	post-up echo 2 > /proc/sys/net/ipv6/conf/myvnet/accept_untracked_na || true
 	vrf vrf_myzone
 
 auto myvnet2
diff --git a/src/test/zones/evpn/ipv4ipv6/expected_sdn_interfaces b/src/test/zones/evpn/ipv4ipv6/expected_sdn_interfaces
index 7a5d741..7b1727b 100644
--- a/src/test/zones/evpn/ipv4ipv6/expected_sdn_interfaces
+++ b/src/test/zones/evpn/ipv4ipv6/expected_sdn_interfaces
@@ -12,6 +12,7 @@ iface myvnet
 	ip-forward on
 	ip6-forward on
 	arp-accept on
+	post-up echo 2 > /proc/sys/net/ipv6/conf/myvnet/accept_untracked_na || true
 	vrf vrf_myzone
 
 auto vrf_myzone
diff --git a/src/test/zones/evpn/ipv4ipv6nogateway/expected_sdn_interfaces b/src/test/zones/evpn/ipv4ipv6nogateway/expected_sdn_interfaces
index 378fa77..4d904be 100644
--- a/src/test/zones/evpn/ipv4ipv6nogateway/expected_sdn_interfaces
+++ b/src/test/zones/evpn/ipv4ipv6nogateway/expected_sdn_interfaces
@@ -8,6 +8,7 @@ iface myvnet
 	bridge_fd 0
 	mtu 1450
 	arp-accept on
+	post-up echo 2 > /proc/sys/net/ipv6/conf/myvnet/accept_untracked_na || true
 	vrf vrf_myzone
 
 auto vrf_myzone
diff --git a/src/test/zones/evpn/ipv6/expected_sdn_interfaces b/src/test/zones/evpn/ipv6/expected_sdn_interfaces
index b2bdbfe..f776122 100644
--- a/src/test/zones/evpn/ipv6/expected_sdn_interfaces
+++ b/src/test/zones/evpn/ipv6/expected_sdn_interfaces
@@ -10,6 +10,7 @@ iface myvnet
 	mtu 1450
 	ip6-forward on
 	arp-accept on
+	post-up echo 2 > /proc/sys/net/ipv6/conf/myvnet/accept_untracked_na || true
 	vrf vrf_myzone
 
 auto vrf_myzone
diff --git a/src/test/zones/evpn/ipv6underlay/expected_sdn_interfaces b/src/test/zones/evpn/ipv6underlay/expected_sdn_interfaces
index 3b91f75..ab5988f 100644
--- a/src/test/zones/evpn/ipv6underlay/expected_sdn_interfaces
+++ b/src/test/zones/evpn/ipv6underlay/expected_sdn_interfaces
@@ -10,6 +10,7 @@ iface myvnet
 	mtu 1450
 	ip6-forward on
 	arp-accept on
+	post-up echo 2 > /proc/sys/net/ipv6/conf/myvnet/accept_untracked_na || true
 	vrf vrf_myzone
 
 auto vrf_myzone
diff --git a/src/test/zones/evpn/slaac/expected_sdn_interfaces b/src/test/zones/evpn/slaac/expected_sdn_interfaces
index 2e479a3..6853bd4 100644
--- a/src/test/zones/evpn/slaac/expected_sdn_interfaces
+++ b/src/test/zones/evpn/slaac/expected_sdn_interfaces
@@ -11,6 +11,7 @@ iface myvnet
 	mtu 1450
 	ip6-forward on
 	arp-accept on
+	post-up echo 2 > /proc/sys/net/ipv6/conf/myvnet/accept_untracked_na || true
 	vrf vrf_myzone
 
 auto vrf_myzone
-- 
2.47.3





  parent reply	other threads:[~2026-04-30 14:31 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-30 14:29 [PATCH docs/manager/network/proxmox{-ve-rs,-perl-rs} v2 00/11] sdn: evpn: add IPv6 RA / SLAAC support Hannes Laimer
2026-04-30 14:29 ` [PATCH proxmox-ve-rs v2 01/11] frr: add IPv6 router advertisement support Hannes Laimer
2026-04-30 14:29 ` [PATCH proxmox-ve-rs v2 02/11] ve-config: add per-vnet IPv6 RA configuration Hannes Laimer
2026-04-30 14:29 ` [PATCH proxmox-perl-rs v2 03/11] pve-rs: sdn: add IPv6 RA builder binding Hannes Laimer
2026-04-30 14:29 ` [PATCH pve-network v2 04/11] sdn: evpn: add IPv6 RA / SLAAC support Hannes Laimer
2026-04-30 14:29 ` [PATCH pve-network v2 05/11] sdn: evpn: derive IP version from CIDR for gateway-less subnets Hannes Laimer
2026-04-30 14:29 ` Hannes Laimer [this message]
2026-04-30 14:29 ` [PATCH pve-network v2 07/11] api: vnet: include zone-type in vnet list Hannes Laimer
2026-04-30 14:29 ` [PATCH pve-manager v2 08/11] ui: sdn: disable SNAT for IPv6 subnets Hannes Laimer
2026-04-30 14:29 ` [PATCH pve-manager v2 09/11] ui: sdn: add IPv6 RA / SLAAC support Hannes Laimer
2026-04-30 14:29 ` [PATCH pve-docs v2 10/11] sdn: document IPv6 RA / SLAAC configuration Hannes Laimer
2026-04-30 14:29 ` [PATCH pve-docs v2 11/11] sdn: add example for IPv6 in an EVPN zone 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=20260430142953.315412-7-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