From: Wesley Atwell <atwellwea@gmail.com>
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 <atwellwea@gmail.com>
---
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