Netdev List
 help / color / mirror / Atom feed
From: Vimal Agrawal <avimalin@gmail.com>
To: pabeni@redhat.com, netdev@vger.kernel.org
Cc: kuba@kernel.org, kuniyu@google.com, edumazet@google.com,
	vimal.agrawal@sophos.com
Subject: [PATCH v4 net-next] net: neigh: avoid calling neigh_forced_gc on every alloc when table is full
Date: Wed, 15 Jul 2026 05:53:11 +0000	[thread overview]
Message-ID: <20260715055311.90403-1-vimal.agrawal@sophos.com> (raw)
In-Reply-To: <20260714133909.82424-1-vimal.agrawal@sophos.com>

Once the neighbour table exceeds gc_thresh3, neigh_forced_gc() is called
on every allocation attempt with no rate limiting. In workloads with mostly
active/reachable entries, the GC walk traverses a large portion of the
neighbour table without reclaiming entries, holding tbl->lock for an
extended period. This causes severe lock contention and allocation
latencies exceeding 16ms under sustained neighbour creation.

Add a pre-lock check in neigh_forced_gc() to skip the GC run if one was
performed within the last 50 ms, but only when the table actually contains
NEIGH_FORCED_GC_LARGE_TABLE_THRESH (16384) or more entries. This avoids
repeated full table scans and lock acquisitions on the hot allocation path
while leaving tables with few entries completely unaffected regardless of
how gc_thresh3 is configured.

Profiling of neigh_create() shows ~3 orders of magnitude latency
improvement with this change.

Link: https://lore.kernel.org/netdev/CALkUMdSCpx_ywYCx_ePLdm6yioO1nQWx7sSM=AEgsq0kywHxTw@mail.gmail.com/
Signed-off-by: Vimal Agrawal <vimal.agrawal@sophos.com>
---
v4: Rate-limit based on actual gc_entries count (>= 16384) rather than
    gc_thresh3 configuration, so tables with few entries are never
    rate-limited regardless of how gc_thresh3 is configured.
v3: Restrict rate limiting to tables with gc_thresh3 >= 16384 to avoid
    breaking selftests and default deployments (gc_thresh3=1024).
v2: Changed rate-limit window from 1s (HZ) to 50ms (msecs_to_jiffies(50))
    based on profiling data showing 44% -> 2.56% CPU reduction.

 net/core/neighbour.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 1349c0eed..9977b9f32 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -250,6 +250,8 @@ bool neigh_remove_one(struct neighbour *n)
 	return retval;
 }
 
+#define NEIGH_FORCED_GC_LARGE_TABLE_THRESH    16384
+
 static int neigh_forced_gc(struct neigh_table *tbl)
 {
 	int max_clean = atomic_read(&tbl->gc_entries) -
@@ -260,6 +262,15 @@ static int neigh_forced_gc(struct neigh_table *tbl)
 	int shrunk = 0;
 	int loop = 0;
 
+	/*
+	 * For large neighbor tables, repeated forced GC passes can spend
+	 * significant CPU scanning neighbor entries when most remain active.
+	 * Rate-limit consecutive forced GC passes to reduce CPU overhead.
+	 */
+	if (atomic_read(&tbl->gc_entries) >= NEIGH_FORCED_GC_LARGE_TABLE_THRESH &&
+	    time_before(jiffies, READ_ONCE(tbl->last_flush) + msecs_to_jiffies(50)))
+		return 0;
+
 	NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
 
 	spin_lock_bh(&tbl->lock);
-- 
2.43.0


  reply	other threads:[~2026-07-15  5:53 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-18  8:17 neigh: poor scalability of forced GC when neighbour count exceeds gc_thresh3 Vimal Agrawal
2026-06-25 10:20 ` [PATCH net-next] net: neigh: avoid calling neigh_forced_gc on every alloc when table is full Vimal Agrawal
2026-06-25 15:42   ` Jakub Kicinski
2026-07-06  6:58     ` [PATCH v2 " Vimal Agrawal
2026-07-06 14:19       ` Paolo Abeni
2026-07-14 13:39         ` [PATCH v3 " Vimal Agrawal
2026-07-15  5:53           ` Vimal Agrawal [this message]
2026-07-21 21:09             ` [PATCH v4 " Jakub Kicinski
2026-07-24 23:17               ` Jakub Kicinski
2026-08-03 13:51                 ` Vimal Agrawal
2026-06-25 21:45   ` [PATCH " Kuniyuki Iwashima
2026-06-29  7:57     ` Vimal Agrawal
2026-06-29 18:05       ` Kuniyuki Iwashima
2026-06-30 12:01         ` Vimal Agrawal
2026-06-30 16:36           ` Kuniyuki Iwashima
2026-07-01  8:30             ` Vimal Agrawal

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=20260715055311.90403-1-vimal.agrawal@sophos.com \
    --to=avimalin@gmail.com \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=kuniyu@google.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=vimal.agrawal@sophos.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