With TCP-timestamps (padded) taking 12 bytes and ADD_ADDR IPv6 + port taking 30 bytes, the 40-byte limit for the TCP options is reached. In this case, it is then not possible to send the signal. To be able to send this ADD_ADDR, the TCP timestamps option can now be dropped. This is done, when needed by setting the *drop_ts parameter from mptcp_established_options. This feature is controlled by a new net.mptcp.add_addr_v6_port_drop_ts sysctl knob, enabled by default. It is important to keep in mind that dropping the TCP timestamps option for one packet of the connection could eventually disrupt some middleboxes: even if it should be unlikely, they could drop the packet or even block the connection. That's why this new feature can be controlled by a sysctl knob. Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/448 Reviewed-by: Mat Martineau Signed-off-by: Matthieu Baerts (NGI0) --- net/mptcp/options.c | 9 +++++++-- net/mptcp/pm.c | 13 ++++++++++++- net/mptcp/protocol.h | 3 ++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/net/mptcp/options.c b/net/mptcp/options.c index 95f16f9f0ce2..8d0680a588dd 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -659,11 +659,13 @@ static u64 add_addr_generate_hmac(u64 key1, u64 key2, static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *skb, int *size, unsigned int remaining, + bool has_ts, struct mptcp_out_options *opts) { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); struct mptcp_sock *msk = mptcp_sk(subflow->conn); struct mptcp_addr_info addr; + bool drop_ts = has_ts; bool echo; /* add addr will strip the existing options, be sure to avoid breaking @@ -672,11 +674,13 @@ static bool mptcp_established_options_add_addr(struct sock *sk, if (!mptcp_pm_should_add_signal(msk) || (opts->suboptions & (OPTION_MPTCP_MPJ_ACK | OPTION_MPTCP_MPC_ACK)) || !skb || !skb_is_tcp_pure_ack(skb) || - !mptcp_pm_add_addr_signal(msk, size, remaining, &addr, &echo)) + !mptcp_pm_add_addr_signal(msk, size, remaining, &addr, &echo, + &drop_ts)) return false; pr_debug("drop other suboptions\n"); opts->suboptions = OPTION_MPTCP_ADD_ADDR; + opts->drop_ts = drop_ts; opts->addr = addr; if (!echo) { MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDRTX); @@ -859,7 +863,8 @@ int mptcp_established_options(struct sock *sk, struct sk_buff *skb, total_size += opt_size; remaining -= opt_size; - if (mptcp_established_options_add_addr(sk, skb, &opt_size, remaining, opts)) { + if (mptcp_established_options_add_addr(sk, skb, &opt_size, remaining, + has_ts, opts)) { total_size += opt_size; remaining -= opt_size; ret = true; diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c index 59dc598d343d..ac7de4141738 100644 --- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c @@ -903,7 +903,8 @@ static int mptcp_add_addr_len(int family, bool echo, bool port) } bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, int *size, int remaining, - struct mptcp_addr_info *addr, bool *echo) + struct mptcp_addr_info *addr, bool *echo, + bool *drop_ts) { bool skip_add_addr = false; bool ret = false; @@ -941,6 +942,13 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, int *size, int remaining, if (len > remaining) { struct net *net = sock_net((struct sock *)msk); + if (*drop_ts && mptcp_add_addr_v6_port_drop_ts(net)) { + /* OK without TCP Timestamps? */ + len -= TCPOLEN_TSTAMP_ALIGNED; + if (len <= remaining) + goto enough_space; + } + if (*echo) { MPTCP_INC_STATS(net, MPTCP_MIB_ECHOADDTXDROP); } else { @@ -950,6 +958,9 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, int *size, int remaining, goto drop_signal_mark; } + *drop_ts = false; + +enough_space: ret = true; *size = len; diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index b43dae72e7de..e69fcb4d48af 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -1208,7 +1208,8 @@ static inline bool mptcp_pm_is_kernel(const struct mptcp_sock *msk) } bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, int *size, int remaining, - struct mptcp_addr_info *addr, bool *echo); + struct mptcp_addr_info *addr, bool *echo, + bool *drop_ts); bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining, struct mptcp_rm_list *rm_list, int *len); int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc); -- 2.53.0