From: Wesley Atwell <[email protected]> When tcp_measure_rcv_mss() lowers scaling_ratio after a window was already advertised, grow sk_rcvbuf so the remaining live sender-visible window still has matching hard receive-memory backing.
This repairs the live advertised window only. Retracted-window rescue is handled separately in a later patch. Signed-off-by: Wesley Atwell <[email protected]> --- net/ipv4/tcp_input.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 32256519a085..d76e4e4c0e57 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -221,6 +221,31 @@ static __cold void tcp_gro_dev_warn(const struct sock *sk, const struct sk_buff rcu_read_unlock(); } +/* If scaling_ratio drops after we already advertised tp->rcv_wnd, grow + * sk_rcvbuf so the remaining live window still maps back to hard memory + * units under the old advertise-time basis. + */ +static void tcp_try_grow_advertised_window(struct sock *sk, + const struct sk_buff *skb) +{ + struct tcp_sock *tp = tcp_sk(sk); + int needed; + + /* Keep this repair aligned with tcp_rcvbuf_grow(): do not adjust + * receive-buffer backing for not-yet-accepted or orphaned sockets. + */ + if (!tcp_rcvbuf_grow_allowed(sk)) + return; + + if (!tcp_receive_window(tp)) + return; + + if (!tcp_space_from_rcv_wnd(tp, tcp_receive_window(tp), &needed)) + return; + + tcp_try_grow_rcvbuf(sk, needed); +} + /* Adapt the MSS value used to make delayed ack decision to the * real world. */ @@ -251,6 +276,7 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) if (old_ratio != tcp_sk(sk)->scaling_ratio) { struct tcp_sock *tp = tcp_sk(sk); + tcp_try_grow_advertised_window(sk, skb); val = tcp_win_from_space(sk, sk->sk_rcvbuf); tcp_set_window_clamp(sk, val); -- 2.43.0
