[PATCH net 1/2] tcp: Fix fastreuse cache initialization on first bind

From: Zhewei Yuan

Date: Sun Oct 25 2026 - 05:01:24 EST


inet_csk_update_fastreuse() initializes the reuse caches only when
tb->bhash2 is empty. Both inet_csk_get_port() and __inet_inherit_port()
link tb2 before calling it, so this condition is never met.

Fresh buckets therefore miss fastreuse=1 for SO_REUSEADDR, forcing
repeated binds to scan existing owners. SO_REUSEPORT starts in STRICT
instead of ANY, causing repeated fast-path misses with alternating
addresses.

Initialize the caches when tb2 is the sole entry in tb->bhash2 and has
no owners. Both checks prevent reinitializing an already-used bucket.

On historical net f4377bf85887, 16000 SO_REUSEADDR binds to one IPv4
address/port take 4256.956 ms before and 20.004 ms after the fix in a
one-vCPU KVM guest (bind-only means of 3 boots x 3 rounds).

Found by manual inspection and GDB tracing. Codex assisted with
analysis, validation and wording; test/benchmark assistance is
described in the cover letter.

Fixes: 8002d44fe84d ("tcp: Check hlist_empty(&tb->bhash2) instead of hlist_empty(&tb->owners).")
Signed-off-by: Zhewei Yuan <yzwlhm@xxxxxxxxx>

---
net/ipv4/inet_connection_sock.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 8151c638a24..93b306d91b6 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -446,7 +446,8 @@ void inet_csk_update_fastreuse(const struct sock *sk,
{
bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;

- if (hlist_empty(&tb->bhash2)) {
+ if (hlist_is_singular_node(&tb2->bhash_node, &tb->bhash2) &&
+ hlist_empty(&tb2->owners)) {
tb->fastreuse = reuse;
if (sk->sk_reuseport) {
tb->fastreuseport = FASTREUSEPORT_ANY;
--
2.52.0