From: Ali Firas <alishmery18@gmail.com>
To: netdev@vger.kernel.org, idosch@nvidia.com
Cc: kuba@kernel.org, pabeni@redhat.com, davem@davemloft.net,
edumazet@kernel.org, andrew+netdev@lunn.ch, horms@kernel.org,
razor@blackwall.org, roopa@nvidia.com, kuniyu@google.com,
petrm@nvidia.com, aroulin@nvidia.com, shuah@kernel.org,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org,
Ali Firas <alishmery18@gmail.com>
Subject: [PATCH net-next v5 5/8] vxlan: leave FDB state and flags unchanged when an update fails
Date: Sun, 15 Nov 2026 01:14:09 +0300 [thread overview]
Message-ID: <20261114221412.255825-6-alishmery18@gmail.com> (raw)
In-Reply-To: <20261114221412.255825-1-alishmery18@gmail.com>
vxlan_fdb_update_existing() writes the requested state and flags into
the entry before the steps that can still fail: under NLM_F_REPLACE the
nexthop update and the check that refuses non-unicast entries, under
NLM_F_APPEND the allocation of the new remote, and the switchdev
notification. Each of them returns an error with the new state and
flags left in place, and no RTM_NEWNEIGH is sent for them, so the entry
changes while the request reports failure and nothing tells userspace.
For example, an RTM_NEWNEIGH asking to replace the permanent all-zeros
entry with a dynamic one is refused with -EOPNOTSUPP, yet leaves the
entry dynamic, and the ageing timer then deletes it.
Write the state and flags only after the nexthop update, the non-unicast
check and the allocation of the new remote, so that a request any of
them refuses never changes the entry, not even briefly. The switchdev
notification reports the new state, so it still follows the write; save
both fields on entry and put them back if a switchdev driver vetoes it.
A successful update ends in the same state and sends the same
notification as before. The ageing timer reads the state and flags
without the hash lock (see commit 7308ef8b4a67 ("vxlan: Stop rejecting
dynamic FDB entries with a nexthop ID")), so it can still age out an
entry that a concurrent successful update makes static; that race
predates this patch and is not addressed here.
The patch "vxlan: vnifilter: account the default FDB entry to memcg"
later in this series makes the NLM_F_APPEND allocation fail routinely
at a memory cgroup limit, on the path that changes a vnifilter VNI's
default entry; this is ordered before it so that failure leaves the
entry as it was. Like the rest of the series it targets net-next.
Found in the automated review of v4 of this series; the other error
exits were found by auditing the rest of the function. Each exit was
triggered in QEMU on net-next. The refused replace and the failed
nexthop update need only netlink requests; the failed append was
injected with the kernel's fail-nth fault injection, and the switchdev
veto was triggered with a test-only module that vetoes the notification,
as no switchdev hardware was available. In a production build (4 vCPU,
ageing 1 s), 356,026,806 refused requests in 1200 s, in equal parts
replaces of the permanent all-zeros entry refused with -EOPNOTSUPP,
appends to it failing on an injected -ENOMEM, and nexthop replaces of
another entry refused with -EINVAL, let the ageing timer delete the
all-zeros entry 1,193 times; the test re-added it after each deletion.
Tested in QEMU with the same requests: each exit now leaves the state
and flags as they were, and the loop above deleted the entry 0 times in
341,241,414 requests. test_vxlan_vnifiltering.sh, which gains a case
for the refused replace later in this series, passes with and without
KASAN and lockdep, and fib_nexthops.sh passes.
Fixes: 6681712d67ee ("vxlan: generalize forwarding tables")
Fixes: 906dc186e020 ("vxlan fdb replace an existing entry")
Fixes: 61f46fe8c646 ("vxlan: Allow vetoing of FDB notifications")
Fixes: 1274e1cc4226 ("vxlan: ecmp support for mac fdb entries")
Signed-off-by: Ali Firas <alishmery18@gmail.com>
---
v5: new patch (review of v4 6/7); says how the gap was found and what it
did in QEMU (sinfo bot); writes the state and flags after the steps that
can fail instead of writing and then reverting them, so a request those
steps refuse never changes them, not even briefly; a switchdev veto
still writes them and puts them back (local review and KCSAN runs).
drivers/net/vxlan/vxlan_core.c | 40 ++++++++++++++++++++--------------
1 file changed, 24 insertions(+), 16 deletions(-)
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index d11028b37472..2303d652d396 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -987,6 +987,8 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
struct netlink_ext_ack *extack)
{
__u16 fdb_flags = (ndm_flags & ~NTF_USE);
+ __u16 old_flags = f->flags;
+ __u16 old_state = f->state;
struct vxlan_rdst *rd = NULL;
struct vxlan_rdst oldrd;
int notify = 0;
@@ -1005,21 +1007,6 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
return -EOPNOTSUPP;
}
- /* Do not allow an externally learned entry to take over an entry added
- * by the user.
- */
- if (!(fdb_flags & NTF_EXT_LEARNED) ||
- !(f->flags & NTF_VXLAN_ADDED_BY_USER)) {
- if (f->state != state) {
- f->state = state;
- notify = 1;
- }
- if (f->flags != fdb_flags) {
- f->flags = fdb_flags;
- notify = 1;
- }
- }
-
if ((flags & NLM_F_REPLACE)) {
/* Only change unicasts */
if (!(is_multicast_ether_addr(f->key.eth_addr) ||
@@ -1048,6 +1035,23 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
notify |= rc;
}
+ /* Do not allow an externally learned entry to take over an entry added
+ * by the user. The state and flags are written only after the steps
+ * above that can fail, so that a request they refuse never changes
+ * them, not even briefly: the ageing timer reads them without the lock.
+ */
+ if (!(fdb_flags & NTF_EXT_LEARNED) ||
+ !(f->flags & NTF_VXLAN_ADDED_BY_USER)) {
+ if (f->state != state) {
+ f->state = state;
+ notify = 1;
+ }
+ if (f->flags != fdb_flags) {
+ f->flags = fdb_flags;
+ notify = 1;
+ }
+ }
+
if (ndm_flags & NTF_USE)
WRITE_ONCE(f->updated, jiffies);
@@ -1066,13 +1070,17 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
err_notify:
if (nhid)
- return err;
+ goto err_restore;
if ((flags & NLM_F_REPLACE) && rc)
*rd = oldrd;
else if ((flags & NLM_F_APPEND) && rc) {
list_del_rcu(&rd->list);
call_rcu(&rd->rcu, vxlan_dst_free);
}
+err_restore:
+ /* The notification was vetoed: put back the state and flags. */
+ f->state = old_state;
+ f->flags = old_flags;
return err;
}
--
2.53.0
next prev parent reply other threads:[~2026-11-14 22:15 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-14 22:14 [PATCH net-next v5 0/8] vxlan: vnifilter: bound a single request and account per-VNI memory Ali Firas
2026-11-14 22:14 ` [PATCH net-next v5 1/8] vxlan: vnifilter: reject VNIs outside the 24-bit space Ali Firas
2026-11-14 22:14 ` [PATCH net-next v5 2/8] vxlan: vnifilter: clamp the dumped VNI range to the request limit Ali Firas
2026-11-14 22:14 ` [PATCH net-next v5 3/8] vxlan: vnifilter: bound the number of VNIs one request may touch Ali Firas
2026-11-14 22:14 ` [PATCH net-next v5 4/8] vxlan: vnifilter: account per-VNI memory to memcg Ali Firas
2026-11-14 22:14 ` Ali Firas [this message]
2026-11-14 22:14 ` [PATCH net-next v5 6/8] vxlan: vnifilter: roll back a VNI add that fails Ali Firas
2026-11-14 22:14 ` [PATCH net-next v5 7/8] vxlan: vnifilter: account the default FDB entry to memcg Ali Firas
2026-11-14 22:14 ` [PATCH net-next v5 8/8] selftests: net: test the vxlan vnifilter request limit and dump replay Ali Firas
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=20261114221412.255825-6-alishmery18@gmail.com \
--to=alishmery18@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=aroulin@nvidia.com \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=petrm@nvidia.com \
--cc=razor@blackwall.org \
--cc=roopa@nvidia.com \
--cc=shuah@kernel.org \
/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
all inboxes | Powered by JetHome®