mptcp: fix rcv buffer auto-tuning

The MPTCP code uses the assumption that the tcp_win_from_space() helper
does not use any TCP-specific field, and thus works correctly operating
on an MPTCP socket.

The commit dfa2f04833 ("tcp: get rid of sysctl_tcp_adv_win_scale")
broke such assumption, and as a consequence most MPTCP connections stall
on zero-window event due to auto-tuning changing the rcv buffer size
quite randomly.

Address the issue syncing again the MPTCP auto-tuning code with the TCP
one. To achieve that, factor out the windows size logic in socket
independent helpers, and reuse them in mptcp_rcv_space_adjust(). The
MPTCP level scaling_ratio is selected as the minimum one from the all
the subflows, as a worst-case estimate.

Fixes: dfa2f04833 ("tcp: get rid of sysctl_tcp_adv_win_scale")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
Link: https://lore.kernel.org/r/20230720-upstream-net-next-20230720-mptcp-fix-rcv-buffer-auto-tuning-v1-1-175ef12b8380@tessares.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Paolo Abeni
2023-07-20 20:47:50 +02:00
committed by Jakub Kicinski
parent 004a04b97b
commit b8dc6d6ce9
4 changed files with 30 additions and 15 deletions

View File

@@ -1430,22 +1430,32 @@ void tcp_select_initial_window(const struct sock *sk, int __space,
__u32 *window_clamp, int wscale_ok,
__u8 *rcv_wscale, __u32 init_rcv_wnd);
static inline int tcp_win_from_space(const struct sock *sk, int space)
static inline int __tcp_win_from_space(u8 scaling_ratio, int space)
{
s64 scaled_space = (s64)space * tcp_sk(sk)->scaling_ratio;
s64 scaled_space = (s64)space * scaling_ratio;
return scaled_space >> TCP_RMEM_TO_WIN_SCALE;
}
/* inverse of tcp_win_from_space() */
static inline int tcp_space_from_win(const struct sock *sk, int win)
static inline int tcp_win_from_space(const struct sock *sk, int space)
{
return __tcp_win_from_space(tcp_sk(sk)->scaling_ratio, space);
}
/* inverse of __tcp_win_from_space() */
static inline int __tcp_space_from_win(u8 scaling_ratio, int win)
{
u64 val = (u64)win << TCP_RMEM_TO_WIN_SCALE;
do_div(val, tcp_sk(sk)->scaling_ratio);
do_div(val, scaling_ratio);
return val;
}
static inline int tcp_space_from_win(const struct sock *sk, int win)
{
return __tcp_space_from_win(tcp_sk(sk)->scaling_ratio, win);
}
static inline void tcp_scaling_ratio_init(struct sock *sk)
{
/* Assume a conservative default of 1200 bytes of payload per 4K page.