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


Reply via email to