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
next prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox