Skip to content

Commit 58d3aad

Browse files
Paolo Abenikuba-moo
authored andcommitted
tcp: fix mid stream window clamp.
After the blamed commit below, if the user-space application performs window clamping when tp->rcv_wnd is 0, the TCP socket will never be able to announce a non 0 receive window, even after completely emptying the receive buffer and re-setting the window clamp to higher values. Refactor tcp_set_window_clamp() to address the issue: when the user decreases the current clamp value, set rcv_ssthresh according to the same logic used at buffer initialization, but ensuring reserved mem provisioning. To avoid code duplication factor-out the relevant bits from tcp_adjust_rcv_ssthresh() in a new helper and reuse it in the above scenario. When increasing the clamp value, give the rcv_ssthresh a chance to grow according to previously implemented heuristic. Fixes: 3aa7857 ("tcp: enable mid stream window clamp") Reported-by: David Gibson <[email protected]> Reported-by: Stefano Brivio <[email protected]> Signed-off-by: Paolo Abeni <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Link: https://lore.kernel.org/r/705dad54e6e6e9a010e571bf58e0b35a8ae70503.1701706073.git.pabeni@redhat.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent d007caa commit 58d3aad

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

include/net/tcp.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,17 +1514,22 @@ static inline int tcp_full_space(const struct sock *sk)
15141514
return tcp_win_from_space(sk, READ_ONCE(sk->sk_rcvbuf));
15151515
}
15161516

1517-
static inline void tcp_adjust_rcv_ssthresh(struct sock *sk)
1517+
static inline void __tcp_adjust_rcv_ssthresh(struct sock *sk, u32 new_ssthresh)
15181518
{
15191519
int unused_mem = sk_unused_reserved_mem(sk);
15201520
struct tcp_sock *tp = tcp_sk(sk);
15211521

1522-
tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss);
1522+
tp->rcv_ssthresh = min(tp->rcv_ssthresh, new_ssthresh);
15231523
if (unused_mem)
15241524
tp->rcv_ssthresh = max_t(u32, tp->rcv_ssthresh,
15251525
tcp_win_from_space(sk, unused_mem));
15261526
}
15271527

1528+
static inline void tcp_adjust_rcv_ssthresh(struct sock *sk)
1529+
{
1530+
__tcp_adjust_rcv_ssthresh(sk, 4U * tcp_sk(sk)->advmss);
1531+
}
1532+
15281533
void tcp_cleanup_rbuf(struct sock *sk, int copied);
15291534
void __tcp_cleanup_rbuf(struct sock *sk, int copied);
15301535

net/ipv4/tcp.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3368,9 +3368,25 @@ int tcp_set_window_clamp(struct sock *sk, int val)
33683368
return -EINVAL;
33693369
tp->window_clamp = 0;
33703370
} else {
3371-
tp->window_clamp = val < SOCK_MIN_RCVBUF / 2 ?
3372-
SOCK_MIN_RCVBUF / 2 : val;
3373-
tp->rcv_ssthresh = min(tp->rcv_wnd, tp->window_clamp);
3371+
u32 new_rcv_ssthresh, old_window_clamp = tp->window_clamp;
3372+
u32 new_window_clamp = val < SOCK_MIN_RCVBUF / 2 ?
3373+
SOCK_MIN_RCVBUF / 2 : val;
3374+
3375+
if (new_window_clamp == old_window_clamp)
3376+
return 0;
3377+
3378+
tp->window_clamp = new_window_clamp;
3379+
if (new_window_clamp < old_window_clamp) {
3380+
/* need to apply the reserved mem provisioning only
3381+
* when shrinking the window clamp
3382+
*/
3383+
__tcp_adjust_rcv_ssthresh(sk, tp->window_clamp);
3384+
3385+
} else {
3386+
new_rcv_ssthresh = min(tp->rcv_wnd, tp->window_clamp);
3387+
tp->rcv_ssthresh = max(new_rcv_ssthresh,
3388+
tp->rcv_ssthresh);
3389+
}
33743390
}
33753391
return 0;
33763392
}

0 commit comments

Comments
 (0)