[PATCH net 1/2] vxlan: keep reserved_bits across changelink
From: Hannes Laimer
Date: Fri Oct 23 2026 - 07:21:32 EST
vxlan_nl2conf() derives reserved_bits from the extension attributes
set in the netlink message if IFLA_VXLAN_RESERVED_BITS is absent. A
changelink having it set is rejected, so this means that every
changelink will reset all extension bits and reserve them again.
vxlan_nl2flag() rejects setting a flag on an attribute that is
create-only on changelink. So also setting an extension attribute will
fail before it can un-reserve its fields.
The extension's header bits being reserved again then makes
vxlan_rcv() drop frames that have them set in their header as invalid.
The device still reports the extension as enabled, because only the
reserved_bits are rebuilt and the flags are just copied.
A simple reproducer is
ip link add vxgbp type vxlan id 1 dstport 4789 local 10.0.0.1 gbp
ip link set dev vxgbp type vxlan ageing 300
After setting the unrelated ageing, incoming packets with the GBP bit
set in the header start getting dropped.
Keeping the reserved_bits on changelink is safe because anything a
changelink accepts leaves the header bits enabled extensions use
unchanged.
Ran into this when adding support for the GBP flag in ifupdown2, see
link below. The device kept dropping packets after some time, it
turned out it always started after a changelink.
Tested this by changing ageing by hand on a vxlan device that was
created by ifupdown2 with the gbp flag, and checking the reserved bits
using
ip -d link show vxgbp | grep -o 'reserved_bits 0x[0-9a-f]*'
Without the fix I got 0xf7ffffff000000ff after the changelink, and
with the fix it stayed 0x77000000000000ff. The following patch
contains a selftest that fails without the fix and passes with it.
Fixes: e4f8647767cf ("vxlan: Track reserved bits explicitly as part of the configuration")
Link: https://lore.proxmox.com/pve-devel/20260828134708.692354-1-h.laimer@xxxxxxxxxxx/
Signed-off-by: Hannes Laimer <h.laimer@xxxxxxxxxxx>
---
drivers/net/vxlan/vxlan_core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 278d41f58d89..223539099778 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -4488,7 +4488,7 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
}
conf->reserved_bits = reserved_bits;
- } else {
+ } else if (!changelink) {
/* For backwards compatibility, only allow reserved fields to be
* used by VXLAN extensions if explicitly requested.
*/
--
2.47.3