diff mbox series

[mptcp-next,v6,3/9] mptcp: track and update contiguous data status

Message ID 9bed3d49d6b462cebc714587fc48d14402269349.1632900306.git.geliangtang@gmail.com (mailing list archive)
State Superseded, archived
Delegated to: Mat Martineau
Headers show
Series The infinite mapping support | expand

Commit Message

Geliang Tang Sept. 29, 2021, 7:35 a.m. UTC
This patch added a new member allow_infinite_fallback in mptcp_sock,
which gets initialized to 'true' when the connection begins and is set
to 'false' on any retransmit or successful MP_JOIN.

Rename the helper function mptcp_is_data_contiguous() to
mptcp_allow_infinite_fallback(). In it, only do infinite mapping fallback
if there is a single subflow AND there have been no retransmissions AND
there have never been any MP_JOINs.

Suggested-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
 net/mptcp/protocol.c |  2 ++
 net/mptcp/protocol.h | 10 +++++++---
 net/mptcp/subflow.c  |  2 +-
 3 files changed, 10 insertions(+), 4 deletions(-)

Comments

Mat Martineau Sept. 29, 2021, 10:12 p.m. UTC | #1
On Wed, 29 Sep 2021, Geliang Tang wrote:

> This patch added a new member allow_infinite_fallback in mptcp_sock,
> which gets initialized to 'true' when the connection begins and is set
> to 'false' on any retransmit or successful MP_JOIN.
>
> Rename the helper function mptcp_is_data_contiguous() to
> mptcp_allow_infinite_fallback(). In it, only do infinite mapping fallback
> if there is a single subflow AND there have been no retransmissions AND
> there have never been any MP_JOINs.
>
> Suggested-by: Paolo Abeni <pabeni@redhat.com>
> Signed-off-by: Geliang Tang <geliangtang@gmail.com>
> ---
> net/mptcp/protocol.c |  2 ++
> net/mptcp/protocol.h | 10 +++++++---
> net/mptcp/subflow.c  |  2 +-
> 3 files changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index f8ad049d6941..48979cb82126 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -2464,6 +2464,7 @@ static void __mptcp_retrans(struct sock *sk)
> 		dfrag->already_sent = max(dfrag->already_sent, info.sent);
> 		tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle,
> 			 info.size_goal);
> +		WRITE_ONCE(msk->allow_infinite_fallback, false);
> 	}
>
> 	release_sock(ssk);
> @@ -2542,6 +2543,7 @@ static int __mptcp_init_sock(struct sock *sk)
> 	msk->first = NULL;
> 	inet_csk(sk)->icsk_sync_mss = mptcp_sync_mss;
> 	WRITE_ONCE(msk->csum_enabled, mptcp_is_checksum_enabled(sock_net(sk)));
> +	WRITE_ONCE(msk->allow_infinite_fallback, true);
> 	msk->recovery = false;
>
> 	mptcp_pm_data_init(msk);
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index 7379ab580a7e..4807e486e762 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -249,6 +249,7 @@ struct mptcp_sock {
> 	bool		rcv_fastclose;
> 	bool		use_64bit_ack; /* Set when we received a 64-bit DSN */
> 	bool		csum_enabled;
> +	bool		allow_infinite_fallback;
> 	spinlock_t	join_list_lock;
> 	struct work_struct work;
> 	struct sk_buff  *ooo_last_skb;
> @@ -612,17 +613,20 @@ static inline void mptcp_subflow_tcp_fallback(struct sock *sk,
> 	inet_csk(sk)->icsk_af_ops = ctx->icsk_af_ops;
> }
>
> -static inline bool mptcp_has_another_subflow(struct sock *ssk)
> +static inline bool mptcp_allow_infinite_fallback(struct sock *ssk)
> {
> 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk), *tmp;
> 	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
>
> 	mptcp_for_each_subflow(msk, tmp) {
> +		if (tmp->mp_join)
> +			return false;
> +
> 		if (tmp != subflow)
> -			return true;
> +			return false;

Sorry I missed your patch-1 v5 reply yesterday! I think it's better for 
now to implement the simpler check discussed in the meeting last week and 
in the v5 review, which is to set allow_infinite_fallback = false when a 
join happens (in mptcp_finish_join() and __mptcp_subflow_connect()). Then 
there's no need to iterate over the subflows here.

We don't have a good answer yet for how to guarantee a subflow and the 
MPTCP-level stream are in a correct state to fallback *after* 
retransmissions or joins, so I think it's important to get this 
single-subflow infinite mapping working and tests implemented first. There 
must be absolute certainty that fallback will not corrupt the application 
data stream.

Mat

> 	}
>
> -	return false;
> +	return READ_ONCE(msk->allow_infinite_fallback);
> }
>
> void __init mptcp_proto_init(void);
> diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> index 87a9ffebcc42..28ed7dc6e170 100644
> --- a/net/mptcp/subflow.c
> +++ b/net/mptcp/subflow.c
> @@ -1167,7 +1167,7 @@ static bool subflow_check_data_avail(struct sock *ssk)
> 	if (!__mptcp_check_fallback(msk)) {
> 		/* RFC 8684 section 3.7. */
> 		if (subflow->send_mp_fail) {
> -			if (mptcp_has_another_subflow(ssk)) {
> +			if (!mptcp_allow_infinite_fallback(ssk)) {
> 				ssk->sk_err = EBADMSG;
> 				tcp_set_state(ssk, TCP_CLOSE);
> 				subflow->reset_transient = 0;
> -- 
> 2.31.1
>
>
>

--
Mat Martineau
Intel
diff mbox series

Patch

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index f8ad049d6941..48979cb82126 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -2464,6 +2464,7 @@  static void __mptcp_retrans(struct sock *sk)
 		dfrag->already_sent = max(dfrag->already_sent, info.sent);
 		tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle,
 			 info.size_goal);
+		WRITE_ONCE(msk->allow_infinite_fallback, false);
 	}
 
 	release_sock(ssk);
@@ -2542,6 +2543,7 @@  static int __mptcp_init_sock(struct sock *sk)
 	msk->first = NULL;
 	inet_csk(sk)->icsk_sync_mss = mptcp_sync_mss;
 	WRITE_ONCE(msk->csum_enabled, mptcp_is_checksum_enabled(sock_net(sk)));
+	WRITE_ONCE(msk->allow_infinite_fallback, true);
 	msk->recovery = false;
 
 	mptcp_pm_data_init(msk);
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 7379ab580a7e..4807e486e762 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -249,6 +249,7 @@  struct mptcp_sock {
 	bool		rcv_fastclose;
 	bool		use_64bit_ack; /* Set when we received a 64-bit DSN */
 	bool		csum_enabled;
+	bool		allow_infinite_fallback;
 	spinlock_t	join_list_lock;
 	struct work_struct work;
 	struct sk_buff  *ooo_last_skb;
@@ -612,17 +613,20 @@  static inline void mptcp_subflow_tcp_fallback(struct sock *sk,
 	inet_csk(sk)->icsk_af_ops = ctx->icsk_af_ops;
 }
 
-static inline bool mptcp_has_another_subflow(struct sock *ssk)
+static inline bool mptcp_allow_infinite_fallback(struct sock *ssk)
 {
 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk), *tmp;
 	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
 
 	mptcp_for_each_subflow(msk, tmp) {
+		if (tmp->mp_join)
+			return false;
+
 		if (tmp != subflow)
-			return true;
+			return false;
 	}
 
-	return false;
+	return READ_ONCE(msk->allow_infinite_fallback);
 }
 
 void __init mptcp_proto_init(void);
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 87a9ffebcc42..28ed7dc6e170 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1167,7 +1167,7 @@  static bool subflow_check_data_avail(struct sock *ssk)
 	if (!__mptcp_check_fallback(msk)) {
 		/* RFC 8684 section 3.7. */
 		if (subflow->send_mp_fail) {
-			if (mptcp_has_another_subflow(ssk)) {
+			if (!mptcp_allow_infinite_fallback(ssk)) {
 				ssk->sk_err = EBADMSG;
 				tcp_set_state(ssk, TCP_CLOSE);
 				subflow->reset_transient = 0;