Skip to content

Commit 6982826

Browse files
matttbekuba-moo
authored andcommitted
mptcp: fallback to TCP after SYN+MPC drops
Some middleboxes might be nasty with MPTCP, and decide to drop packets with MPTCP options, instead of just dropping the MPTCP options (or letting them pass...). In this case, it sounds better to fallback to "plain" TCP after 2 retransmissions, and try again. Closes: multipath-tcp/mptcp_net-next#477 Signed-off-by: Matthieu Baerts (NGI0) <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Link: https://patch.msgid.link/20240909-net-next-mptcp-fallback-x-mpc-v1-2-da7ebb4cd2a3@kernel.org Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 65b0226 commit 6982826

File tree

5 files changed

+27
-0
lines changed

5 files changed

+27
-0
lines changed

include/net/mptcp.h

+4
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ static inline __be32 mptcp_reset_option(const struct sk_buff *skb)
223223

224224
return htonl(0u);
225225
}
226+
227+
void mptcp_active_detect_blackhole(struct sock *sk, bool expired);
226228
#else
227229

228230
static inline void mptcp_init(void)
@@ -307,6 +309,8 @@ static inline struct request_sock *mptcp_subflow_reqsk_alloc(const struct reques
307309
}
308310

309311
static inline __be32 mptcp_reset_option(const struct sk_buff *skb) { return htonl(0u); }
312+
313+
static inline void mptcp_active_detect_blackhole(struct sock *sk, bool expired) { }
310314
#endif /* CONFIG_MPTCP */
311315

312316
#if IS_ENABLED(CONFIG_MPTCP_IPV6)

net/ipv4/tcp_timer.c

+1
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ static int tcp_write_timeout(struct sock *sk)
282282
expired = retransmits_timed_out(sk, retry_until,
283283
READ_ONCE(icsk->icsk_user_timeout));
284284
tcp_fastopen_active_detect_blackhole(sk, expired);
285+
mptcp_active_detect_blackhole(sk, expired);
285286

286287
if (BPF_SOCK_OPS_TEST_FLAG(tp, BPF_SOCK_OPS_RTO_CB_FLAG))
287288
tcp_call_bpf_3arg(sk, BPF_SOCK_OPS_RTO_CB,

net/mptcp/ctrl.c

+20
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <net/netns/generic.h>
1313

1414
#include "protocol.h"
15+
#include "mib.h"
1516

1617
#define MPTCP_SYSCTL_PATH "net/mptcp"
1718

@@ -277,6 +278,25 @@ static void mptcp_pernet_del_table(struct mptcp_pernet *pernet) {}
277278

278279
#endif /* CONFIG_SYSCTL */
279280

281+
/* Check the number of retransmissions, and fallback to TCP if needed */
282+
void mptcp_active_detect_blackhole(struct sock *ssk, bool expired)
283+
{
284+
struct mptcp_subflow_context *subflow;
285+
u32 timeouts;
286+
287+
if (!sk_is_mptcp(ssk))
288+
return;
289+
290+
timeouts = inet_csk(ssk)->icsk_retransmits;
291+
subflow = mptcp_subflow_ctx(ssk);
292+
293+
if (subflow->request_mptcp && ssk->sk_state == TCP_SYN_SENT &&
294+
(timeouts == 2 || (timeouts < 2 && expired))) {
295+
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPCAPABLEACTIVEDROP);
296+
mptcp_subflow_early_fallback(mptcp_sk(subflow->conn), subflow);
297+
}
298+
}
299+
280300
static int __net_init mptcp_net_init(struct net *net)
281301
{
282302
struct mptcp_pernet *pernet = mptcp_get_pernet(net);

net/mptcp/mib.c

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ static const struct snmp_mib mptcp_snmp_list[] = {
1515
SNMP_MIB_ITEM("MPCapableACKRX", MPTCP_MIB_MPCAPABLEPASSIVEACK),
1616
SNMP_MIB_ITEM("MPCapableFallbackACK", MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK),
1717
SNMP_MIB_ITEM("MPCapableFallbackSYNACK", MPTCP_MIB_MPCAPABLEACTIVEFALLBACK),
18+
SNMP_MIB_ITEM("MPCapableSYNTXDrop", MPTCP_MIB_MPCAPABLEACTIVEDROP),
1819
SNMP_MIB_ITEM("MPFallbackTokenInit", MPTCP_MIB_TOKENFALLBACKINIT),
1920
SNMP_MIB_ITEM("MPTCPRetrans", MPTCP_MIB_RETRANSSEGS),
2021
SNMP_MIB_ITEM("MPJoinNoTokenFound", MPTCP_MIB_JOINNOTOKEN),

net/mptcp/mib.h

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ enum linux_mptcp_mib_field {
1010
MPTCP_MIB_MPCAPABLEPASSIVEACK, /* Received third ACK with MP_CAPABLE */
1111
MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK,/* Server-side fallback during 3-way handshake */
1212
MPTCP_MIB_MPCAPABLEACTIVEFALLBACK, /* Client-side fallback during 3-way handshake */
13+
MPTCP_MIB_MPCAPABLEACTIVEDROP, /* Client-side fallback due to a MPC drop */
1314
MPTCP_MIB_TOKENFALLBACKINIT, /* Could not init/allocate token */
1415
MPTCP_MIB_RETRANSSEGS, /* Segments retransmitted at the MPTCP-level */
1516
MPTCP_MIB_JOINNOTOKEN, /* Received MP_JOIN but the token was not found */

0 commit comments

Comments
 (0)