From 0e125ecfe20c077625cf0be8d750d5c3abc0dce9 Mon Sep 17 00:00:00 2001 From: Nathan Gao Date: Fri, 24 Jul 2026 20:08:06 -0700 Subject: [PATCH] tcp: do not change rcv_ssthresh in tcp_measure_rcv_mss() Commit f5da7c45188e ("tcp: adjust rcvq_space after updating scaling ratio") replaced the direct window_clamp update in tcp_measure_rcv_mss() with a call to tcp_set_window_clamp(), a helper that implements the TCP_WINDOW_CLAMP setsockopt. As a side effect, the helper also shrinks rcv_ssthresh via __tcp_adjust_rcv_ssthresh(). As a result, each scaling_ratio decrease detected by tcp_measure_rcv_mss() also cuts rcv_ssthresh. Elsewhere in TCP, rcv_ssthresh is usually cut under memory pressure and grows via tcp_grow_window(). Flows whose segment sizes vary keep scaling_ratio oscillating, which leads to an unstable rcv_ssthresh: a dip of rcv_ssthresh only recovers via tcp_grow_window(), keeping the advertised window at a relatively low level even after the ratio itself has recovered, and can even stall the sender. Observed on a customer's proxy gateway after upgrading from kernel 6.1 to 6.12: in the worst case, rcv_ssthresh was cut in half by a scaling_ratio dip. P99 latency jumped from <10ms on 6.1 to ~100ms on 6.12, and almost returned to the 6.1 level with this patch applied. Restore the plain WRITE_ONCE() update of window_clamp, as introduced in commit a2cbb1603943 ("tcp: Update window clamping condition"), and keep the rcvq_space.space adjustment. Now rcv_ssthresh is decoupled from scaling_ratio changes in tcp_measure_rcv_mss(). Fixes: f5da7c45188e ("tcp: adjust rcvq_space after updating scaling ratio") Signed-off-by: Nathan Gao Link: https://patch.msgid.link/20260725030806.28135-1-zcgao@amazon.com Signed-off-by: Jakub Kicinski --- net/ipv4/tcp_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index daff93d51342..5b6378b94701 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -252,7 +252,7 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) struct tcp_sock *tp = tcp_sk(sk); val = tcp_win_from_space(sk, sk->sk_rcvbuf); - tcp_set_window_clamp(sk, val); + WRITE_ONCE(tp->window_clamp, val); if (tp->window_clamp < tp->rcvq_space.space) tp->rcvq_space.space = tp->window_clamp;