[PATCH mptcp-next RFC v4 2/2] mptcp: send MP_FAIL and infinite mapping on the same ACK

Chenguang Zhao <[email protected]>
Newsgroups dev.linux.lists.mptcp
Message-ID <[email protected]>
From: Chenguang Zhao <[email protected]>

On a single subflow, accepting MP_FAIL must leave MPTCP mode at once
(RFC8684 §3.7). Emit the infinite mapping on the MP_FAIL reply ACK,
then call mptcp_try_fallback() immediately after.

Fixes: 1e39e5a32ad7 ("mptcp: infinite mapping sending")
Signed-off-by: Chenguang Zhao <[email protected]>
---
 net/mptcp/options.c  | 33 ++++++++++++++++++++++++++++++++-
 net/mptcp/pm.c       |  5 +++++
 net/mptcp/protocol.c |  8 +-------
 3 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index 97da22668dbe..ecf77e77d2de 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -638,7 +638,29 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
 	opts->csum_reqd = READ_ONCE(msk->csum_enabled);
 	mpext = skb ? mptcp_get_ext(skb) : NULL;
 
-	if (!skb || (mpext && mpext->use_map) || snd_data_fin_enable) {
+	if (unlikely(subflow->send_infinite_map)) {
+		unsigned int map_size = TCPOLEN_MPTCP_DSS_BASE + TCPOLEN_MPTCP_DSS_MAP64;
+
+		if (opts->csum_reqd)
+			map_size += TCPOLEN_MPTCP_DSS_CHECKSUM;
+
+		if (mpext) {
+			opts->ext_copy = *mpext;
+			opts->ext_copy.infinite_map = 1;
+			opts->ext_copy.data_len = 0;
+		} else {
+			opts->ext_copy.use_map = 1;
+			opts->ext_copy.dsn64 = 1;
+			opts->ext_copy.infinite_map = 1;
+			opts->ext_copy.data_len = 0;
+			opts->ext_copy.data_seq = READ_ONCE(msk->snd_nxt);
+			opts->ext_copy.subflow_seq = subflow->rel_write_seq;
+		}
+
+		dss_size = map_size;
+		opts->suboptions = OPTION_MPTCP_DSS;
+		ret = true;
+	} else if (!skb || (mpext && mpext->use_map) || snd_data_fin_enable) {
 		unsigned int map_size = TCPOLEN_MPTCP_DSS_BASE + TCPOLEN_MPTCP_DSS_MAP64;
 
 		if (mpext) {
@@ -1566,6 +1588,15 @@ void mptcp_write_options(struct tcphdr *th, __be32 *ptr, struct tcp_sock *tp,
 						   TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
 			}
 			ptr += 1;
+
+			if (unlikely(mpext->infinite_map)) {
+				subflow = mptcp_subflow_ctx(ssk);
+				if (subflow->send_infinite_map) {
+					subflow->send_infinite_map = 0;
+					MPTCP_INC_STATS(sock_net(ssk),
+							MPTCP_MIB_INFINITEMAPTX);
+				}
+			}
 		}
 
 		/* We might need to add MP_FAIL options in rare cases */
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index ba7c6f80a183..69701ac7e436 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -895,6 +895,11 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
 		pr_debug("MP_FAIL response received\n");
 		WRITE_ONCE(subflow->fail_tout, 0);
 	}
+
+	if (!mptcp_try_fallback(sk, MPTCP_MIB_MPFAILFALLBACK)) {
+		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_FALLBACKFAILED);
+		mptcp_subflow_reset(sk);
+	}
 }
 
 static int mptcp_add_addr_len(int family, bool echo, bool port)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index f879b1061f2d..abe45a31ca5f 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1417,13 +1417,7 @@ static void mptcp_update_infinite_map(struct mptcp_sock *msk,
 
 	mpext->infinite_map = 1;
 	mpext->data_len = 0;
-
-	if (!mptcp_try_fallback(ssk, MPTCP_MIB_INFINITEMAPTX)) {
-		MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_FALLBACKFAILED);
-		mptcp_subflow_reset(ssk);
-		return;
-	}
-
+	MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPTX);
 	mptcp_subflow_ctx(ssk)->send_infinite_map = 0;
 }
 
-- 
2.25.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.