mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
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: 3aa7857fe1
("tcp: enable mid stream window clamp")
Reported-by: David Gibson <david@gibson.dropbear.id.au>
Reported-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/705dad54e6e6e9a010e571bf58e0b35a8ae70503.1701706073.git.pabeni@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
d007caaaf0
commit
58d3aade20
@ -1514,17 +1514,22 @@ static inline int tcp_full_space(const struct sock *sk)
|
||||
return tcp_win_from_space(sk, READ_ONCE(sk->sk_rcvbuf));
|
||||
}
|
||||
|
||||
static inline void tcp_adjust_rcv_ssthresh(struct sock *sk)
|
||||
static inline void __tcp_adjust_rcv_ssthresh(struct sock *sk, u32 new_ssthresh)
|
||||
{
|
||||
int unused_mem = sk_unused_reserved_mem(sk);
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
|
||||
tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss);
|
||||
tp->rcv_ssthresh = min(tp->rcv_ssthresh, new_ssthresh);
|
||||
if (unused_mem)
|
||||
tp->rcv_ssthresh = max_t(u32, tp->rcv_ssthresh,
|
||||
tcp_win_from_space(sk, unused_mem));
|
||||
}
|
||||
|
||||
static inline void tcp_adjust_rcv_ssthresh(struct sock *sk)
|
||||
{
|
||||
__tcp_adjust_rcv_ssthresh(sk, 4U * tcp_sk(sk)->advmss);
|
||||
}
|
||||
|
||||
void tcp_cleanup_rbuf(struct sock *sk, int copied);
|
||||
void __tcp_cleanup_rbuf(struct sock *sk, int copied);
|
||||
|
||||
|
@ -3368,9 +3368,25 @@ int tcp_set_window_clamp(struct sock *sk, int val)
|
||||
return -EINVAL;
|
||||
tp->window_clamp = 0;
|
||||
} else {
|
||||
tp->window_clamp = val < SOCK_MIN_RCVBUF / 2 ?
|
||||
SOCK_MIN_RCVBUF / 2 : val;
|
||||
tp->rcv_ssthresh = min(tp->rcv_wnd, tp->window_clamp);
|
||||
u32 new_rcv_ssthresh, old_window_clamp = tp->window_clamp;
|
||||
u32 new_window_clamp = val < SOCK_MIN_RCVBUF / 2 ?
|
||||
SOCK_MIN_RCVBUF / 2 : val;
|
||||
|
||||
if (new_window_clamp == old_window_clamp)
|
||||
return 0;
|
||||
|
||||
tp->window_clamp = new_window_clamp;
|
||||
if (new_window_clamp < old_window_clamp) {
|
||||
/* need to apply the reserved mem provisioning only
|
||||
* when shrinking the window clamp
|
||||
*/
|
||||
__tcp_adjust_rcv_ssthresh(sk, tp->window_clamp);
|
||||
|
||||
} else {
|
||||
new_rcv_ssthresh = min(tp->rcv_wnd, tp->window_clamp);
|
||||
tp->rcv_ssthresh = max(new_rcv_ssthresh,
|
||||
tp->rcv_ssthresh);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user