summaryrefslogtreecommitdiff
path: root/net/core
diff options
context:
space:
mode:
authorPetr Machata <petrm@nvidia.com>2026-01-21 17:43:38 +0100
committerJakub Kicinski <kuba@kernel.org>2026-01-25 14:57:37 -0800
commit89246ef82d799e68d5e34873e95d4c1ca2486cc5 (patch)
treefcd4410d56377c9271037676d368e5385c2e5b25 /net/core
parent705ef89ac98648167f486b51bb8d9e2fefbe4fb4 (diff)
net: core: neighbour: Process ARP queue later
ARP queue processing unlocks the neighbor lock, which can allow another thread to asynchronously perform a neighbor update and send an out of order notification. Therefore this needs to be done after the notification is sent. Move it just before the end of the critical section. Since neigh_update_process_arp_queue() unlocks, it does not form a part of the critical section anymore but it can benefit from the lock being taken. The intention is to eventually do the RTNL notification before this call. This motion crosses a call to neigh_update_is_router(), which should not influence processing of the ARP queue. Signed-off-by: Petr Machata <petrm@nvidia.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/9ea7159e71430ebdc837ebcc880a76b7e82e52a4.1769012464.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/neighbour.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index b6cb127a5b8e..3d969f0190a1 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1369,6 +1369,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
struct netlink_ext_ack *extack)
{
bool gc_update = false, managed_update = false;
+ bool process_arp_queue = false;
int update_isrouter = 0;
struct net_device *dev;
int err, notify = 0;
@@ -1504,12 +1505,17 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
neigh_suspect(neigh);
if (!(old & NUD_VALID))
- neigh_update_process_arp_queue(neigh);
+ process_arp_queue = true;
out:
if (update_isrouter)
neigh_update_is_router(neigh, flags, &notify);
+
+ if (process_arp_queue)
+ neigh_update_process_arp_queue(neigh);
+
write_unlock_bh(&neigh->lock);
+
if (((new ^ old) & NUD_PERMANENT) || gc_update)
neigh_update_gc_list(neigh);
if (managed_update)