]> git.dujemihanovic.xyz Git - linux.git/commitdiff
mptcp: fallback to TCP after SYN+MPC drops
authorMatthieu Baerts (NGI0) <matttbe@kernel.org>
Mon, 9 Sep 2024 20:09:22 +0000 (22:09 +0200)
committerJakub Kicinski <kuba@kernel.org>
Wed, 11 Sep 2024 22:57:50 +0000 (15:57 -0700)
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: https://github.com/multipath-tcp/mptcp_net-next/issues/477
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20240909-net-next-mptcp-fallback-x-mpc-v1-2-da7ebb4cd2a3@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/mptcp.h
net/ipv4/tcp_timer.c
net/mptcp/ctrl.c
net/mptcp/mib.c
net/mptcp/mib.h

index 0bc4ab03f48786a11ee6be2b7aac60c0d8d176cb..814b5f2e3ed5e3e474a2bac5e4cca5a89abcfe1c 100644 (file)
@@ -223,6 +223,8 @@ static inline __be32 mptcp_reset_option(const struct sk_buff *skb)
 
        return htonl(0u);
 }
+
+void mptcp_active_detect_blackhole(struct sock *sk, bool expired);
 #else
 
 static inline void mptcp_init(void)
@@ -307,6 +309,8 @@ static inline struct request_sock *mptcp_subflow_reqsk_alloc(const struct reques
 }
 
 static inline __be32 mptcp_reset_option(const struct sk_buff *skb)  { return htonl(0u); }
+
+static inline void mptcp_active_detect_blackhole(struct sock *sk, bool expired) { }
 #endif /* CONFIG_MPTCP */
 
 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
index 86169127e4d1fe0e00c660b7ea718db5253a14e5..79064580c8c0d55daa2ab4dc6d27a5ab8802e599 100644 (file)
@@ -282,6 +282,7 @@ static int tcp_write_timeout(struct sock *sk)
                expired = retransmits_timed_out(sk, retry_until,
                                                READ_ONCE(icsk->icsk_user_timeout));
        tcp_fastopen_active_detect_blackhole(sk, expired);
+       mptcp_active_detect_blackhole(sk, expired);
 
        if (BPF_SOCK_OPS_TEST_FLAG(tp, BPF_SOCK_OPS_RTO_CB_FLAG))
                tcp_call_bpf_3arg(sk, BPF_SOCK_OPS_RTO_CB,
index 99382c317ebb62d7dc427cbbe9200d3f7667359a..0b23e3c5e8ff449ace899df75a52054e924d97cc 100644 (file)
@@ -12,6 +12,7 @@
 #include <net/netns/generic.h>
 
 #include "protocol.h"
+#include "mib.h"
 
 #define MPTCP_SYSCTL_PATH "net/mptcp"
 
@@ -277,6 +278,25 @@ static void mptcp_pernet_del_table(struct mptcp_pernet *pernet) {}
 
 #endif /* CONFIG_SYSCTL */
 
+/* Check the number of retransmissions, and fallback to TCP if needed */
+void mptcp_active_detect_blackhole(struct sock *ssk, bool expired)
+{
+       struct mptcp_subflow_context *subflow;
+       u32 timeouts;
+
+       if (!sk_is_mptcp(ssk))
+               return;
+
+       timeouts = inet_csk(ssk)->icsk_retransmits;
+       subflow = mptcp_subflow_ctx(ssk);
+
+       if (subflow->request_mptcp && ssk->sk_state == TCP_SYN_SENT &&
+           (timeouts == 2 || (timeouts < 2 && expired))) {
+               MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPCAPABLEACTIVEDROP);
+               mptcp_subflow_early_fallback(mptcp_sk(subflow->conn), subflow);
+       }
+}
+
 static int __net_init mptcp_net_init(struct net *net)
 {
        struct mptcp_pernet *pernet = mptcp_get_pernet(net);
index ec0d461cb921e0ef4d79700dd3d140b9c4314e5b..d70a3e2bfad624a96c079ef9377f360e8ef62fc7 100644 (file)
@@ -15,6 +15,7 @@ static const struct snmp_mib mptcp_snmp_list[] = {
        SNMP_MIB_ITEM("MPCapableACKRX", MPTCP_MIB_MPCAPABLEPASSIVEACK),
        SNMP_MIB_ITEM("MPCapableFallbackACK", MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK),
        SNMP_MIB_ITEM("MPCapableFallbackSYNACK", MPTCP_MIB_MPCAPABLEACTIVEFALLBACK),
+       SNMP_MIB_ITEM("MPCapableSYNTXDrop", MPTCP_MIB_MPCAPABLEACTIVEDROP),
        SNMP_MIB_ITEM("MPFallbackTokenInit", MPTCP_MIB_TOKENFALLBACKINIT),
        SNMP_MIB_ITEM("MPTCPRetrans", MPTCP_MIB_RETRANSSEGS),
        SNMP_MIB_ITEM("MPJoinNoTokenFound", MPTCP_MIB_JOINNOTOKEN),
index d68136f93dac5dfb9cd57c44b08e2223f87702ed..062775700b6328a620c5e6fb79fffacd7c465604 100644 (file)
@@ -10,6 +10,7 @@ enum linux_mptcp_mib_field {
        MPTCP_MIB_MPCAPABLEPASSIVEACK,  /* Received third ACK with MP_CAPABLE */
        MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK,/* Server-side fallback during 3-way handshake */
        MPTCP_MIB_MPCAPABLEACTIVEFALLBACK, /* Client-side fallback during 3-way handshake */
+       MPTCP_MIB_MPCAPABLEACTIVEDROP,  /* Client-side fallback due to a MPC drop */
        MPTCP_MIB_TOKENFALLBACKINIT,    /* Could not init/allocate token */
        MPTCP_MIB_RETRANSSEGS,          /* Segments retransmitted at the MPTCP-level */
        MPTCP_MIB_JOINNOTOKEN,          /* Received MP_JOIN but the token was not found */