]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
tcp: do not change rcv_ssthresh in tcp_measure_rcv_mss()
authorNathan Gao <zcgao@amazon.com>
Sat, 25 Jul 2026 03:08:06 +0000 (20:08 -0700)
committerJakub Kicinski <kuba@kernel.org>
Mon, 3 Aug 2026 21:20:45 +0000 (14:20 -0700)
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 <zcgao@amazon.com>
Link: https://patch.msgid.link/20260725030806.28135-1-zcgao@amazon.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv4/tcp_input.c

index daff93d5134287b1934d7e2891cdffe2a4efe191..5b6378b94701ef8f5ff7c5303931f7e5046cad4e 100644 (file)
@@ -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;