All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH mptcp-next v4 00/11] refactor push pending
@ 2022-10-02 14:25 Geliang Tang
  2022-10-02 14:25 ` [PATCH mptcp-next v4 01/11] Squash to "mptcp: add get_subflow wrappers" Geliang Tang
                   ` (10 more replies)
  0 siblings, 11 replies; 18+ messages in thread
From: Geliang Tang @ 2022-10-02 14:25 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

v4:
- update __mptcp_subflow_push_pending as Mat suggested.
- add more patches from "BPF redundant scheduler" series.

v3:
- add a cleanup patch.
- remove msk->last_snd in mptcp_subflow_get_send().
- add the loop that calls the scheduler again in __mptcp_push_pending().

v2:
- add snd_burst check in dfrags loop as Mat suggested.

Refactor __mptcp_push_pending() and __mptcp_subflow_push_pending() to
remove duplicate code and support redundant scheduler more easily in
__mptcp_subflow_push_pending().

Geliang Tang (11):
  Squash to "mptcp: add get_subflow wrappers"
  mptcp: add new argument ssk_first
  mptcp: move burst check out of subflow_get_send
  mptcp: refactor push_pending logic
  mptcp: simplify push_pending
  mptcp: multi subflows push_pending
  mptcp: use msk instead of mptcp_sk
  mptcp: refactor subflow_push_pending logic
  mptcp: simplify subflow_push_pending
  mptcp: multi subflows subflow_push_pending
  mptcp: multi subflows retrans support

 net/mptcp/protocol.c | 259 ++++++++++++++++++++++---------------------
 net/mptcp/protocol.h |   4 +-
 net/mptcp/sched.c    |  59 +++++-----
 3 files changed, 164 insertions(+), 158 deletions(-)

-- 
2.35.3


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH mptcp-next v4 01/11] Squash to "mptcp: add get_subflow wrappers"
  2022-10-02 14:25 [PATCH mptcp-next v4 00/11] refactor push pending Geliang Tang
@ 2022-10-02 14:25 ` Geliang Tang
  2022-10-02 14:25 ` [PATCH mptcp-next v4 02/11] mptcp: add new argument ssk_first Geliang Tang
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 18+ messages in thread
From: Geliang Tang @ 2022-10-02 14:25 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

Please update the commit log:

'''
This patch defines two new wrappers mptcp_sched_get_send() and
mptcp_sched_get_retrans(), invoke get_subflow() of msk->sched in them.

Set the subflow pointers array in struct mptcp_sched_data before invoking
get_subflow(), then it can be used in get_subflow() in the BPF contexts.

Check the subflow scheduled flags to test which subflow or subflows are
picked by the scheduler.

Move sock_owned_by_me() and the fallback check code from
mptcp_subflow_get_send/retrans() into the wrappers.
'''
---
 net/mptcp/protocol.c |  8 +++---
 net/mptcp/protocol.h |  4 +--
 net/mptcp/sched.c    | 59 +++++++++++++++++++++-----------------------
 3 files changed, 34 insertions(+), 37 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 7ca21915b3d1..cc8e67543e76 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1547,7 +1547,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
 			int ret = 0;
 
 			prev_ssk = ssk;
-			ssk = mptcp_sched_get_send(msk);
+			ssk = mptcp_subflow_get_send(msk);
 
 			/* First check. If the ssk has changed since
 			 * the last round, release prev_ssk
@@ -1616,7 +1616,7 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
 			 * check for a different subflow usage only after
 			 * spooling the first chunk of data
 			 */
-			xmit_ssk = first ? ssk : mptcp_sched_get_send(mptcp_sk(sk));
+			xmit_ssk = first ? ssk : mptcp_subflow_get_send(mptcp_sk(sk));
 			if (!xmit_ssk)
 				goto out;
 			if (xmit_ssk != ssk) {
@@ -2478,7 +2478,7 @@ static void __mptcp_retrans(struct sock *sk)
 	mptcp_clean_una_wakeup(sk);
 
 	/* first check ssk: need to kick "stale" logic */
-	ssk = mptcp_sched_get_retrans(msk);
+	ssk = mptcp_subflow_get_retrans(msk);
 	dfrag = mptcp_rtx_head(sk);
 	if (!dfrag) {
 		if (mptcp_data_fin_enabled(msk)) {
@@ -3196,7 +3196,7 @@ void __mptcp_check_push(struct sock *sk, struct sock *ssk)
 		return;
 
 	if (!sock_owned_by_user(sk)) {
-		struct sock *xmit_ssk = mptcp_sched_get_send(mptcp_sk(sk));
+		struct sock *xmit_ssk = mptcp_subflow_get_send(mptcp_sk(sk));
 
 		if (xmit_ssk == ssk)
 			__mptcp_subflow_push_pending(sk, ssk);
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 93c535440a5c..e81399debff9 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -640,8 +640,8 @@ void mptcp_subflow_set_scheduled(struct mptcp_subflow_context *subflow,
 				 bool scheduled);
 struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk);
 struct sock *mptcp_subflow_get_retrans(struct mptcp_sock *msk);
-struct sock *mptcp_sched_get_send(struct mptcp_sock *msk);
-struct sock *mptcp_sched_get_retrans(struct mptcp_sock *msk);
+int mptcp_sched_get_send(struct mptcp_sock *msk);
+int mptcp_sched_get_retrans(struct mptcp_sock *msk);
 
 static inline bool __tcp_can_send(const struct sock *ssk)
 {
diff --git a/net/mptcp/sched.c b/net/mptcp/sched.c
index 044c5ec8bbfb..d1cad1eefb35 100644
--- a/net/mptcp/sched.c
+++ b/net/mptcp/sched.c
@@ -114,67 +114,64 @@ static int mptcp_sched_data_init(struct mptcp_sock *msk, bool reinject,
 	for (; i < MPTCP_SUBFLOWS_MAX; i++)
 		data->contexts[i] = NULL;
 
+	msk->snd_burst = 0;
+
 	return 0;
 }
 
-struct sock *mptcp_sched_get_send(struct mptcp_sock *msk)
+int mptcp_sched_get_send(struct mptcp_sock *msk)
 {
 	struct mptcp_sched_data data;
 	struct sock *ssk = NULL;
-	int i;
 
 	sock_owned_by_me((struct sock *)msk);
 
 	/* the following check is moved out of mptcp_subflow_get_send */
 	if (__mptcp_check_fallback(msk)) {
-		if (!msk->first)
-			return NULL;
-		return __tcp_can_send(msk->first) &&
-		       sk_stream_memory_free(msk->first) ? msk->first : NULL;
+		if (msk->first &&
+		    __tcp_can_send(msk->first) &&
+		    sk_stream_memory_free(msk->first)) {
+			mptcp_subflow_set_scheduled(mptcp_subflow_ctx(msk->first), true);
+			return 0;
+		}
+		return -EINVAL;
 	}
 
-	if (!msk->sched)
-		return mptcp_subflow_get_send(msk);
+	if (!msk->sched) {
+		ssk = mptcp_subflow_get_send(msk);
+		if (!ssk)
+			return -EINVAL;
+		mptcp_subflow_set_scheduled(mptcp_subflow_ctx(ssk), true);
+		return 0;
+	}
 
 	mptcp_sched_data_init(msk, false, &data);
 	msk->sched->get_subflow(msk, &data);
 
-	for (i = 0; i < MPTCP_SUBFLOWS_MAX; i++) {
-		if (data.contexts[i] && READ_ONCE(data.contexts[i]->scheduled)) {
-			ssk = data.contexts[i]->tcp_sock;
-			msk->last_snd = ssk;
-			break;
-		}
-	}
-
-	return ssk;
+	return 0;
 }
 
-struct sock *mptcp_sched_get_retrans(struct mptcp_sock *msk)
+int mptcp_sched_get_retrans(struct mptcp_sock *msk)
 {
 	struct mptcp_sched_data data;
 	struct sock *ssk = NULL;
-	int i;
 
 	sock_owned_by_me((const struct sock *)msk);
 
 	/* the following check is moved out of mptcp_subflow_get_retrans */
 	if (__mptcp_check_fallback(msk))
-		return NULL;
+		return -EINVAL;
 
-	if (!msk->sched)
-		return mptcp_subflow_get_retrans(msk);
+	if (!msk->sched) {
+		ssk = mptcp_subflow_get_retrans(msk);
+		if (!ssk)
+			return -EINVAL;
+		mptcp_subflow_set_scheduled(mptcp_subflow_ctx(ssk), true);
+		return 0;
+	}
 
 	mptcp_sched_data_init(msk, true, &data);
 	msk->sched->get_subflow(msk, &data);
 
-	for (i = 0; i < MPTCP_SUBFLOWS_MAX; i++) {
-		if (data.contexts[i] && READ_ONCE(data.contexts[i]->scheduled)) {
-			ssk = data.contexts[i]->tcp_sock;
-			msk->last_snd = ssk;
-			break;
-		}
-	}
-
-	return ssk;
+	return 0;
 }
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH mptcp-next v4 02/11] mptcp: add new argument ssk_first
  2022-10-02 14:25 [PATCH mptcp-next v4 00/11] refactor push pending Geliang Tang
  2022-10-02 14:25 ` [PATCH mptcp-next v4 01/11] Squash to "mptcp: add get_subflow wrappers" Geliang Tang
@ 2022-10-02 14:25 ` Geliang Tang
  2022-10-05  0:16   ` Mat Martineau
  2022-10-02 14:25 ` [PATCH mptcp-next v4 03/11] mptcp: move burst check out of subflow_get_send Geliang Tang
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 18+ messages in thread
From: Geliang Tang @ 2022-10-02 14:25 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

The function mptcp_subflow_process_delegated() uses the input ssk first,
while __mptcp_check_push() invokes the packet scheduler first.

So this patch adds a new argument named ssk_first for the function
__mptcp_subflow_push_pending() to deal with these two cases separately.

With this change, the code that invokes the packet scheduler in the
fuction __mptcp_check_push() can be removed, and replaced by invoking
__mptcp_subflow_push_pending() directly.

Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
 net/mptcp/protocol.c | 22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index cc8e67543e76..bbc43212a20f 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1593,16 +1593,17 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
 		__mptcp_check_send_data_fin(sk);
 }
 
-static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
+static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk,
+					 bool ssk_first)
 {
 	struct mptcp_sock *msk = mptcp_sk(sk);
 	struct mptcp_sendmsg_info info = {
 		.data_lock_held = true,
 	};
 	struct mptcp_data_frag *dfrag;
+	bool first = ssk_first;
 	struct sock *xmit_ssk;
 	int len, copied = 0;
-	bool first = true;
 
 	info.flags = 0;
 	while ((dfrag = mptcp_send_head(sk))) {
@@ -1612,8 +1613,7 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
 		while (len > 0) {
 			int ret = 0;
 
-			/* the caller already invoked the packet scheduler,
-			 * check for a different subflow usage only after
+			/* check for a different subflow usage only after
 			 * spooling the first chunk of data
 			 */
 			xmit_ssk = first ? ssk : mptcp_subflow_get_send(mptcp_sk(sk));
@@ -3195,16 +3195,10 @@ void __mptcp_check_push(struct sock *sk, struct sock *ssk)
 	if (!mptcp_send_head(sk))
 		return;
 
-	if (!sock_owned_by_user(sk)) {
-		struct sock *xmit_ssk = mptcp_subflow_get_send(mptcp_sk(sk));
-
-		if (xmit_ssk == ssk)
-			__mptcp_subflow_push_pending(sk, ssk);
-		else if (xmit_ssk)
-			mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk), MPTCP_DELEGATE_SEND);
-	} else {
+	if (!sock_owned_by_user(sk))
+		__mptcp_subflow_push_pending(sk, ssk, false);
+	else
 		__set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags);
-	}
 }
 
 #define MPTCP_FLAGS_PROCESS_CTX_NEED (BIT(MPTCP_PUSH_PENDING) | \
@@ -3295,7 +3289,7 @@ void mptcp_subflow_process_delegated(struct sock *ssk)
 	if (test_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status)) {
 		mptcp_data_lock(sk);
 		if (!sock_owned_by_user(sk))
-			__mptcp_subflow_push_pending(sk, ssk);
+			__mptcp_subflow_push_pending(sk, ssk, true);
 		else
 			__set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags);
 		mptcp_data_unlock(sk);
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH mptcp-next v4 03/11] mptcp: move burst check out of subflow_get_send
  2022-10-02 14:25 [PATCH mptcp-next v4 00/11] refactor push pending Geliang Tang
  2022-10-02 14:25 ` [PATCH mptcp-next v4 01/11] Squash to "mptcp: add get_subflow wrappers" Geliang Tang
  2022-10-02 14:25 ` [PATCH mptcp-next v4 02/11] mptcp: add new argument ssk_first Geliang Tang
@ 2022-10-02 14:25 ` Geliang Tang
  2022-10-05  0:20   ` Mat Martineau
  2022-10-02 14:25 ` [PATCH mptcp-next v4 04/11] mptcp: refactor push_pending logic Geliang Tang
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 18+ messages in thread
From: Geliang Tang @ 2022-10-02 14:25 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch moves the burst check conditions out of the function
mptcp_subflow_get_send(), check them in __mptcp_push_pending() and
__mptcp_subflow_push_pending() in the inner "for each pending dfrag" loop.

Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
 net/mptcp/protocol.c | 27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index bbc43212a20f..785c52b738cf 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1417,14 +1417,6 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk)
 	u64 linger_time;
 	long tout = 0;
 
-	/* re-use last subflow, if the burst allow that */
-	if (msk->last_snd && msk->snd_burst > 0 &&
-	    sk_stream_memory_free(msk->last_snd) &&
-	    mptcp_subflow_active(mptcp_subflow_ctx(msk->last_snd))) {
-		mptcp_set_timeout(sk);
-		return msk->last_snd;
-	}
-
 	/* pick the subflow with the lower wmem/wspace ratio */
 	for (i = 0; i < SSK_MODE_MAX; ++i) {
 		send_info[i].ssk = NULL;
@@ -1477,16 +1469,13 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk)
 
 	burst = min_t(int, MPTCP_SEND_BURST_SIZE, mptcp_wnd_end(msk) - msk->snd_nxt);
 	wmem = READ_ONCE(ssk->sk_wmem_queued);
-	if (!burst) {
-		msk->last_snd = NULL;
+	if (!burst)
 		return ssk;
-	}
 
 	subflow = mptcp_subflow_ctx(ssk);
 	subflow->avg_pacing_rate = div_u64((u64)subflow->avg_pacing_rate * wmem +
 					   READ_ONCE(ssk->sk_pacing_rate) * burst,
 					   burst + wmem);
-	msk->last_snd = ssk;
 	msk->snd_burst = burst;
 	return ssk;
 }
@@ -1579,6 +1568,13 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
 			mptcp_update_post_push(msk, dfrag, ret);
 		}
 		WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
+
+		if (msk->snd_burst <= 0 ||
+		    !sk_stream_memory_free(ssk) ||
+		    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
+			goto out;
+		}
+		mptcp_set_timeout(sk);
 	}
 
 	/* at this point we held the socket lock for the last subflow we used */
@@ -1637,6 +1633,13 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk,
 			mptcp_update_post_push(msk, dfrag, ret);
 		}
 		WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
+
+		if (msk->snd_burst <= 0 ||
+		    !sk_stream_memory_free(ssk) ||
+		    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
+			goto out;
+		}
+		mptcp_set_timeout(sk);
 	}
 
 out:
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH mptcp-next v4 04/11] mptcp: refactor push_pending logic
  2022-10-02 14:25 [PATCH mptcp-next v4 00/11] refactor push pending Geliang Tang
                   ` (2 preceding siblings ...)
  2022-10-02 14:25 ` [PATCH mptcp-next v4 03/11] mptcp: move burst check out of subflow_get_send Geliang Tang
@ 2022-10-02 14:25 ` Geliang Tang
  2022-10-05  0:23   ` Mat Martineau
  2022-10-02 14:25 ` [PATCH mptcp-next v4 05/11] mptcp: simplify push_pending Geliang Tang
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 18+ messages in thread
From: Geliang Tang @ 2022-10-02 14:25 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

To support redundant package schedulers more easily, this patch refactors
__mptcp_push_pending() logic from:

For each dfrag:
	While sends succeed:
		Call the scheduler (selects subflow and msk->snd_burst)
		Update subflow locks (push/release/acquire as needed)
		Send the dfrag data with mptcp_sendmsg_frag()
		Update already_sent, snd_nxt, snd_burst
	Update msk->first_pending
Push/release on final subflow

to:

While the scheduler selects one subflow:
	Lock the subflow
	For each pending dfrag:
		While sends succeed:
			Send the dfrag data with mptcp_sendmsg_frag()
			Update already_sent, snd_nxt, snd_burst
		Update msk->first_pending
		Break if required by msk->snd_burst / etc
	Push and release the subflow

Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
 net/mptcp/protocol.c | 76 +++++++++++++++++---------------------------
 1 file changed, 30 insertions(+), 46 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 785c52b738cf..296b7135e9cf 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1519,67 +1519,51 @@ void mptcp_check_and_set_pending(struct sock *sk)
 
 void __mptcp_push_pending(struct sock *sk, unsigned int flags)
 {
-	struct sock *prev_ssk = NULL, *ssk = NULL;
 	struct mptcp_sock *msk = mptcp_sk(sk);
 	struct mptcp_sendmsg_info info = {
 				.flags = flags,
 	};
 	bool do_check_data_fin = false;
 	struct mptcp_data_frag *dfrag;
+	struct sock *ssk;
 	int len;
 
-	while ((dfrag = mptcp_send_head(sk))) {
-		info.sent = dfrag->already_sent;
-		info.limit = dfrag->data_len;
-		len = dfrag->data_len - dfrag->already_sent;
-		while (len > 0) {
-			int ret = 0;
-
-			prev_ssk = ssk;
-			ssk = mptcp_subflow_get_send(msk);
-
-			/* First check. If the ssk has changed since
-			 * the last round, release prev_ssk
-			 */
-			if (ssk != prev_ssk && prev_ssk)
-				mptcp_push_release(prev_ssk, &info);
-			if (!ssk)
-				goto out;
+	while (mptcp_send_head(sk) && (ssk = mptcp_subflow_get_send(msk))) {
+		lock_sock(ssk);
 
-			/* Need to lock the new subflow only if different
-			 * from the previous one, otherwise we are still
-			 * helding the relevant lock
-			 */
-			if (ssk != prev_ssk)
-				lock_sock(ssk);
+		while ((dfrag = mptcp_send_head(sk))) {
+			info.sent = dfrag->already_sent;
+			info.limit = dfrag->data_len;
+			len = dfrag->data_len - dfrag->already_sent;
+			while (len > 0) {
+				int ret = 0;
+
+				ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
+				if (ret <= 0) {
+					if (ret == -EAGAIN)
+						continue;
+					mptcp_push_release(ssk, &info);
+					goto out;
+				}
+
+				do_check_data_fin = true;
+				info.sent += ret;
+				len -= ret;
+
+				mptcp_update_post_push(msk, dfrag, ret);
+			}
+			WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
 
-			ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
-			if (ret <= 0) {
-				if (ret == -EAGAIN)
-					continue;
-				mptcp_push_release(ssk, &info);
+			if (msk->snd_burst <= 0 ||
+			    !sk_stream_memory_free(ssk) ||
+			    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
 				goto out;
 			}
-
-			do_check_data_fin = true;
-			info.sent += ret;
-			len -= ret;
-
-			mptcp_update_post_push(msk, dfrag, ret);
-		}
-		WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
-
-		if (msk->snd_burst <= 0 ||
-		    !sk_stream_memory_free(ssk) ||
-		    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
-			goto out;
+			mptcp_set_timeout(sk);
 		}
-		mptcp_set_timeout(sk);
-	}
 
-	/* at this point we held the socket lock for the last subflow we used */
-	if (ssk)
 		mptcp_push_release(ssk, &info);
+	}
 
 out:
 	/* ensure the rtx timer is running */
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH mptcp-next v4 05/11] mptcp: simplify push_pending
  2022-10-02 14:25 [PATCH mptcp-next v4 00/11] refactor push pending Geliang Tang
                   ` (3 preceding siblings ...)
  2022-10-02 14:25 ` [PATCH mptcp-next v4 04/11] mptcp: refactor push_pending logic Geliang Tang
@ 2022-10-02 14:25 ` Geliang Tang
  2022-10-05  0:33   ` Mat Martineau
  2022-10-02 14:25 ` [PATCH mptcp-next v4 06/11] mptcp: multi subflows push_pending Geliang Tang
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 18+ messages in thread
From: Geliang Tang @ 2022-10-02 14:25 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch moves the duplicate code from __mptcp_push_pending() and
__mptcp_subflow_push_pending() into a new helper function, named
__subflow_push_pending(). And simplify __mptcp_push_pending() by
invoking this helper.

Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
 net/mptcp/protocol.c | 90 +++++++++++++++++++++++---------------------
 1 file changed, 48 insertions(+), 42 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 296b7135e9cf..66c97ac06a4e 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1480,12 +1480,6 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk)
 	return ssk;
 }
 
-static void mptcp_push_release(struct sock *ssk, struct mptcp_sendmsg_info *info)
-{
-	tcp_push(ssk, 0, info->mss_now, tcp_sk(ssk)->nonagle, info->size_goal);
-	release_sock(ssk);
-}
-
 static void mptcp_update_post_push(struct mptcp_sock *msk,
 				   struct mptcp_data_frag *dfrag,
 				   u32 sent)
@@ -1517,6 +1511,52 @@ void mptcp_check_and_set_pending(struct sock *sk)
 		mptcp_sk(sk)->push_pending |= BIT(MPTCP_PUSH_PENDING);
 }
 
+static int __subflow_push_pending(struct sock *sk, struct sock *ssk,
+				  struct mptcp_sendmsg_info *info)
+{
+	struct mptcp_sock *msk = mptcp_sk(sk);
+	struct mptcp_data_frag *dfrag;
+	int len, copied = 0;
+
+	while ((dfrag = mptcp_send_head(sk))) {
+		info->sent = dfrag->already_sent;
+		info->limit = dfrag->data_len;
+		len = dfrag->data_len - dfrag->already_sent;
+		while (len > 0) {
+			int ret = 0;
+
+			ret = mptcp_sendmsg_frag(sk, ssk, dfrag, info);
+			if (ret <= 0) {
+				if (ret == -EAGAIN)
+					continue;
+				goto out;
+			}
+
+			info->sent += ret;
+			copied += ret;
+			len -= ret;
+
+			mptcp_update_post_push(msk, dfrag, ret);
+		}
+		WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
+
+		if (msk->snd_burst <= 0 ||
+		    !sk_stream_memory_free(ssk) ||
+		    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
+			goto out;
+		}
+		mptcp_set_timeout(sk);
+	}
+
+out:
+	if (copied) {
+		tcp_push(ssk, 0, info->mss_now, tcp_sk(ssk)->nonagle,
+			 info->size_goal);
+	}
+
+	return copied;
+}
+
 void __mptcp_push_pending(struct sock *sk, unsigned int flags)
 {
 	struct mptcp_sock *msk = mptcp_sk(sk);
@@ -1524,48 +1564,14 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
 				.flags = flags,
 	};
 	bool do_check_data_fin = false;
-	struct mptcp_data_frag *dfrag;
 	struct sock *ssk;
-	int len;
 
 	while (mptcp_send_head(sk) && (ssk = mptcp_subflow_get_send(msk))) {
 		lock_sock(ssk);
-
-		while ((dfrag = mptcp_send_head(sk))) {
-			info.sent = dfrag->already_sent;
-			info.limit = dfrag->data_len;
-			len = dfrag->data_len - dfrag->already_sent;
-			while (len > 0) {
-				int ret = 0;
-
-				ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
-				if (ret <= 0) {
-					if (ret == -EAGAIN)
-						continue;
-					mptcp_push_release(ssk, &info);
-					goto out;
-				}
-
-				do_check_data_fin = true;
-				info.sent += ret;
-				len -= ret;
-
-				mptcp_update_post_push(msk, dfrag, ret);
-			}
-			WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
-
-			if (msk->snd_burst <= 0 ||
-			    !sk_stream_memory_free(ssk) ||
-			    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
-				goto out;
-			}
-			mptcp_set_timeout(sk);
-		}
-
-		mptcp_push_release(ssk, &info);
+		do_check_data_fin = __subflow_push_pending(sk, ssk, &info);
+		release_sock(ssk);
 	}
 
-out:
 	/* ensure the rtx timer is running */
 	if (!mptcp_timer_pending(sk))
 		mptcp_reset_timer(sk);
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH mptcp-next v4 06/11] mptcp: multi subflows push_pending
  2022-10-02 14:25 [PATCH mptcp-next v4 00/11] refactor push pending Geliang Tang
                   ` (4 preceding siblings ...)
  2022-10-02 14:25 ` [PATCH mptcp-next v4 05/11] mptcp: simplify push_pending Geliang Tang
@ 2022-10-02 14:25 ` Geliang Tang
  2022-10-02 14:25 ` [PATCH mptcp-next v4 07/11] mptcp: use msk instead of mptcp_sk Geliang Tang
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 18+ messages in thread
From: Geliang Tang @ 2022-10-02 14:25 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch adds the multiple subflows support for __mptcp_push_pending().
Use mptcp_sched_get_send() wrapper instead of mptcp_subflow_get_send() in
it.

Check the subflow scheduled flags to test which subflow or subflows are
picked by the scheduler, use them to send data.

Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
 net/mptcp/protocol.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 66c97ac06a4e..7108eda00b6f 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1560,16 +1560,26 @@ static int __subflow_push_pending(struct sock *sk, struct sock *ssk,
 void __mptcp_push_pending(struct sock *sk, unsigned int flags)
 {
 	struct mptcp_sock *msk = mptcp_sk(sk);
-	struct mptcp_sendmsg_info info = {
-				.flags = flags,
-	};
 	bool do_check_data_fin = false;
-	struct sock *ssk;
 
-	while (mptcp_send_head(sk) && (ssk = mptcp_subflow_get_send(msk))) {
-		lock_sock(ssk);
-		do_check_data_fin = __subflow_push_pending(sk, ssk, &info);
-		release_sock(ssk);
+	while (mptcp_send_head(sk) && !mptcp_sched_get_send(msk)) {
+		struct mptcp_subflow_context *subflow;
+		struct mptcp_sendmsg_info info = {
+			.flags = flags,
+		};
+
+		mptcp_for_each_subflow(msk, subflow) {
+			if (READ_ONCE(subflow->scheduled)) {
+				struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
+
+				lock_sock(ssk);
+				do_check_data_fin = __subflow_push_pending(sk, ssk, &info);
+				release_sock(ssk);
+
+				msk->last_snd = ssk;
+				mptcp_subflow_set_scheduled(subflow, false);
+			}
+		}
 	}
 
 	/* ensure the rtx timer is running */
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH mptcp-next v4 07/11] mptcp: use msk instead of mptcp_sk
  2022-10-02 14:25 [PATCH mptcp-next v4 00/11] refactor push pending Geliang Tang
                   ` (5 preceding siblings ...)
  2022-10-02 14:25 ` [PATCH mptcp-next v4 06/11] mptcp: multi subflows push_pending Geliang Tang
@ 2022-10-02 14:25 ` Geliang Tang
  2022-10-02 14:25 ` [PATCH mptcp-next v4 08/11] mptcp: refactor subflow_push_pending logic Geliang Tang
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 18+ messages in thread
From: Geliang Tang @ 2022-10-02 14:25 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

Use msk instead of mptcp_sk(sk) in the functions where the variable
"msk = mptcp_sk(sk)" has been defined.

Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
 net/mptcp/protocol.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 7108eda00b6f..a8674b431593 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1612,7 +1612,7 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk,
 			/* check for a different subflow usage only after
 			 * spooling the first chunk of data
 			 */
-			xmit_ssk = first ? ssk : mptcp_subflow_get_send(mptcp_sk(sk));
+			xmit_ssk = first ? ssk : mptcp_subflow_get_send(msk);
 			if (!xmit_ssk)
 				goto out;
 			if (xmit_ssk != ssk) {
@@ -2242,7 +2242,7 @@ bool __mptcp_retransmit_pending_data(struct sock *sk)
 	struct mptcp_data_frag *cur, *rtx_head;
 	struct mptcp_sock *msk = mptcp_sk(sk);
 
-	if (__mptcp_check_fallback(mptcp_sk(sk)))
+	if (__mptcp_check_fallback(msk))
 		return false;
 
 	if (tcp_rtx_and_write_queues_empty(sk))
@@ -2924,7 +2924,7 @@ bool __mptcp_close(struct sock *sk, long timeout)
 
 	sock_hold(sk);
 	pr_debug("msk=%p state=%d", sk, sk->sk_state);
-	if (mptcp_sk(sk)->token)
+	if (msk->token)
 		mptcp_event(MPTCP_EVENT_CLOSED, msk, NULL, GFP_KERNEL);
 
 	if (sk->sk_state == TCP_CLOSE) {
@@ -2983,8 +2983,8 @@ static int mptcp_disconnect(struct sock *sk, int flags)
 	mptcp_stop_timer(sk);
 	sk_stop_timer(sk, &sk->sk_timer);
 
-	if (mptcp_sk(sk)->token)
-		mptcp_event(MPTCP_EVENT_CLOSED, mptcp_sk(sk), NULL, GFP_KERNEL);
+	if (msk->token)
+		mptcp_event(MPTCP_EVENT_CLOSED, msk, NULL, GFP_KERNEL);
 
 	/* msk->subflow is still intact, the following will not free the first
 	 * subflow
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH mptcp-next v4 08/11] mptcp: refactor subflow_push_pending logic
  2022-10-02 14:25 [PATCH mptcp-next v4 00/11] refactor push pending Geliang Tang
                   ` (6 preceding siblings ...)
  2022-10-02 14:25 ` [PATCH mptcp-next v4 07/11] mptcp: use msk instead of mptcp_sk Geliang Tang
@ 2022-10-02 14:25 ` Geliang Tang
  2022-10-02 14:25 ` [PATCH mptcp-next v4 09/11] mptcp: simplify subflow_push_pending Geliang Tang
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 18+ messages in thread
From: Geliang Tang @ 2022-10-02 14:25 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch refactors __mptcp_subflow_push_pending logic from:

For each dfrag:
	While sends succeed:
		Call the scheduler (selects subflow and msk->snd_burst)
		Send the dfrag data with mptcp_subflow_delegate(), break
		Send the dfrag data with mptcp_sendmsg_frag()
		Update dfrag->already_sent, msk->snd_nxt, msk->snd_burst
	Update msk->first_pending

to:

While first_pending isn't empty:
	Call the scheduler (selects subflow and msk->snd_burst)
	Send the dfrag data with mptcp_subflow_delegate(), break
	Send the dfrag data with mptcp_sendmsg_frag()
	For each pending dfrag:
		While sends succeed:
			Send the dfrag data with mptcp_sendmsg_frag()
			Update already_sent, snd_nxt, snd_burst
		Update msk->first_pending
		Break if required by msk->snd_burst / etc

Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
 net/mptcp/protocol.c | 66 +++++++++++++++++++++++---------------------
 1 file changed, 34 insertions(+), 32 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index a8674b431593..c036a788fc27 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1602,44 +1602,46 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk,
 	int len, copied = 0;
 
 	info.flags = 0;
-	while ((dfrag = mptcp_send_head(sk))) {
-		info.sent = dfrag->already_sent;
-		info.limit = dfrag->data_len;
-		len = dfrag->data_len - dfrag->already_sent;
-		while (len > 0) {
-			int ret = 0;
+	while (mptcp_send_head(sk)) {
+		/* check for a different subflow usage only after
+		 * spooling the first chunk of data
+		 */
+		xmit_ssk = first ? ssk : mptcp_subflow_get_send(msk);
+		if (!xmit_ssk)
+			goto out;
+		if (xmit_ssk != ssk) {
+			mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk),
+					       MPTCP_DELEGATE_SEND);
+			goto out;
+		}
 
-			/* check for a different subflow usage only after
-			 * spooling the first chunk of data
-			 */
-			xmit_ssk = first ? ssk : mptcp_subflow_get_send(msk);
-			if (!xmit_ssk)
-				goto out;
-			if (xmit_ssk != ssk) {
-				mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk),
-						       MPTCP_DELEGATE_SEND);
-				goto out;
-			}
+		while ((dfrag = mptcp_send_head(sk))) {
+			info.sent = dfrag->already_sent;
+			info.limit = dfrag->data_len;
+			len = dfrag->data_len - dfrag->already_sent;
+			while (len > 0) {
+				int ret = 0;
 
-			ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
-			if (ret <= 0)
-				goto out;
+				ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
+				if (ret <= 0)
+					goto out;
 
-			info.sent += ret;
-			copied += ret;
-			len -= ret;
-			first = false;
+				info.sent += ret;
+				copied += ret;
+				len -= ret;
+				first = false;
 
-			mptcp_update_post_push(msk, dfrag, ret);
-		}
-		WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
+				mptcp_update_post_push(msk, dfrag, ret);
+			}
+			WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
 
-		if (msk->snd_burst <= 0 ||
-		    !sk_stream_memory_free(ssk) ||
-		    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
-			goto out;
+			if (msk->snd_burst <= 0 ||
+			    !sk_stream_memory_free(ssk) ||
+			    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
+				goto out;
+			}
+			mptcp_set_timeout(sk);
 		}
-		mptcp_set_timeout(sk);
 	}
 
 out:
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH mptcp-next v4 09/11] mptcp: simplify subflow_push_pending
  2022-10-02 14:25 [PATCH mptcp-next v4 00/11] refactor push pending Geliang Tang
                   ` (7 preceding siblings ...)
  2022-10-02 14:25 ` [PATCH mptcp-next v4 08/11] mptcp: refactor subflow_push_pending logic Geliang Tang
@ 2022-10-02 14:25 ` Geliang Tang
  2022-10-02 14:25 ` [PATCH mptcp-next v4 10/11] mptcp: multi subflows subflow_push_pending Geliang Tang
  2022-10-02 14:25 ` [PATCH mptcp-next v4 11/11] mptcp: multi subflows retrans support Geliang Tang
  10 siblings, 0 replies; 18+ messages in thread
From: Geliang Tang @ 2022-10-02 14:25 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch simplifies __mptcp_subflow_push_pending() by invoking
__subflow_push_pending() helper.

Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
 net/mptcp/protocol.c | 35 ++++-------------------------------
 1 file changed, 4 insertions(+), 31 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index c036a788fc27..439af075b144 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1596,10 +1596,9 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk,
 	struct mptcp_sendmsg_info info = {
 		.data_lock_held = true,
 	};
-	struct mptcp_data_frag *dfrag;
 	bool first = ssk_first;
 	struct sock *xmit_ssk;
-	int len, copied = 0;
+	int copied = 0;
 
 	info.flags = 0;
 	while (mptcp_send_head(sk)) {
@@ -1615,33 +1614,9 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk,
 			goto out;
 		}
 
-		while ((dfrag = mptcp_send_head(sk))) {
-			info.sent = dfrag->already_sent;
-			info.limit = dfrag->data_len;
-			len = dfrag->data_len - dfrag->already_sent;
-			while (len > 0) {
-				int ret = 0;
-
-				ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
-				if (ret <= 0)
-					goto out;
-
-				info.sent += ret;
-				copied += ret;
-				len -= ret;
-				first = false;
-
-				mptcp_update_post_push(msk, dfrag, ret);
-			}
-			WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
-
-			if (msk->snd_burst <= 0 ||
-			    !sk_stream_memory_free(ssk) ||
-			    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
-				goto out;
-			}
-			mptcp_set_timeout(sk);
-		}
+		copied = __subflow_push_pending(sk, ssk, &info);
+		if (!copied)
+			break;
 	}
 
 out:
@@ -1649,8 +1624,6 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk,
 	 * not going to flush it via release_sock()
 	 */
 	if (copied) {
-		tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle,
-			 info.size_goal);
 		if (!mptcp_timer_pending(sk))
 			mptcp_reset_timer(sk);
 
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH mptcp-next v4 10/11] mptcp: multi subflows subflow_push_pending
  2022-10-02 14:25 [PATCH mptcp-next v4 00/11] refactor push pending Geliang Tang
                   ` (8 preceding siblings ...)
  2022-10-02 14:25 ` [PATCH mptcp-next v4 09/11] mptcp: simplify subflow_push_pending Geliang Tang
@ 2022-10-02 14:25 ` Geliang Tang
  2022-10-02 14:25 ` [PATCH mptcp-next v4 11/11] mptcp: multi subflows retrans support Geliang Tang
  10 siblings, 0 replies; 18+ messages in thread
From: Geliang Tang @ 2022-10-02 14:25 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch adds the multiple subflows support for
__mptcp_subflow_push_pending(). Use mptcp_sched_get_send() wrapper
instead of mptcp_subflow_get_send() in it.

Check the subflow scheduled flags to test which subflow or subflows are
picked by the scheduler, use them to send data.

Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
 net/mptcp/protocol.c | 43 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 439af075b144..85f72cdfa2c4 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1593,11 +1593,11 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk,
 					 bool ssk_first)
 {
 	struct mptcp_sock *msk = mptcp_sk(sk);
+	struct mptcp_subflow_context *subflow;
 	struct mptcp_sendmsg_info info = {
 		.data_lock_held = true,
 	};
 	bool first = ssk_first;
-	struct sock *xmit_ssk;
 	int copied = 0;
 
 	info.flags = 0;
@@ -1605,18 +1605,39 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk,
 		/* check for a different subflow usage only after
 		 * spooling the first chunk of data
 		 */
-		xmit_ssk = first ? ssk : mptcp_subflow_get_send(msk);
-		if (!xmit_ssk)
-			goto out;
-		if (xmit_ssk != ssk) {
-			mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk),
-					       MPTCP_DELEGATE_SEND);
-			goto out;
+		if (first) {
+			copied = __subflow_push_pending(sk, ssk, &info);
+			if (!copied)
+				break;
+			first = false;
+			msk->last_snd = ssk;
+			continue;
 		}
 
-		copied = __subflow_push_pending(sk, ssk, &info);
-		if (!copied)
-			break;
+		if (mptcp_sched_get_send(msk))
+			goto out;
+
+		mptcp_for_each_subflow(msk, subflow) {
+			if (READ_ONCE(subflow->scheduled)) {
+				struct sock *xmit_ssk = mptcp_subflow_tcp_sock(subflow);
+
+				if (xmit_ssk != ssk) {
+					if (mptcp_subflow_has_delegated_action(subflow))
+						goto out;
+					mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk),
+							       MPTCP_DELEGATE_SEND);
+					msk->last_snd = xmit_ssk;
+					mptcp_subflow_set_scheduled(subflow, false);
+					continue;
+				}
+
+				copied = __subflow_push_pending(sk, ssk, &info);
+				if (!copied)
+					goto out;
+				msk->last_snd = ssk;
+				mptcp_subflow_set_scheduled(subflow, false);
+			}
+		}
 	}
 
 out:
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH mptcp-next v4 11/11] mptcp: multi subflows retrans support
  2022-10-02 14:25 [PATCH mptcp-next v4 00/11] refactor push pending Geliang Tang
                   ` (9 preceding siblings ...)
  2022-10-02 14:25 ` [PATCH mptcp-next v4 10/11] mptcp: multi subflows subflow_push_pending Geliang Tang
@ 2022-10-02 14:25 ` Geliang Tang
  2022-10-06 15:43   ` mptcp: multi subflows retrans support: Tests Results MPTCP CI
  10 siblings, 1 reply; 18+ messages in thread
From: Geliang Tang @ 2022-10-02 14:25 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch adds the multiple subflows support for __mptcp_retrans(). In
it, use sched_get_retrans() wrapper instead of mptcp_subflow_get_retrans().

Iterate each subflow of msk, check the scheduled flag to test if it is
picked by the scheduler. If so, use it to retrans data.

Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
 net/mptcp/protocol.c | 62 ++++++++++++++++++++++++++++----------------
 1 file changed, 39 insertions(+), 23 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 85f72cdfa2c4..b90b4bb70ec4 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -2468,16 +2468,17 @@ static void mptcp_check_fastclose(struct mptcp_sock *msk)
 static void __mptcp_retrans(struct sock *sk)
 {
 	struct mptcp_sock *msk = mptcp_sk(sk);
+	struct mptcp_subflow_context *subflow;
 	struct mptcp_sendmsg_info info = {};
 	struct mptcp_data_frag *dfrag;
-	size_t copied = 0;
 	struct sock *ssk;
-	int ret;
+	int ret, err;
+	u16 len = 0;
 
 	mptcp_clean_una_wakeup(sk);
 
 	/* first check ssk: need to kick "stale" logic */
-	ssk = mptcp_subflow_get_retrans(msk);
+	err = mptcp_sched_get_retrans(msk);
 	dfrag = mptcp_rtx_head(sk);
 	if (!dfrag) {
 		if (mptcp_data_fin_enabled(msk)) {
@@ -2496,31 +2497,46 @@ static void __mptcp_retrans(struct sock *sk)
 		goto reset_timer;
 	}
 
-	if (!ssk)
+	if (err)
 		goto reset_timer;
 
-	lock_sock(ssk);
+	mptcp_for_each_subflow(msk, subflow) {
+		if (READ_ONCE(subflow->scheduled)) {
+			u16 copied = 0;
+
+			ssk = mptcp_subflow_tcp_sock(subflow);
+			if (!ssk)
+				goto reset_timer;
+
+			lock_sock(ssk);
+
+			/* limit retransmission to the bytes already sent on some subflows */
+			info.sent = 0;
+			info.limit = READ_ONCE(msk->csum_enabled) ? dfrag->data_len :
+								    dfrag->already_sent;
+			while (info.sent < info.limit) {
+				ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
+				if (ret <= 0)
+					break;
+
+				MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RETRANSSEGS);
+				copied += ret;
+				info.sent += ret;
+			}
+			if (copied) {
+				len = max(copied, len);
+				tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle,
+					 info.size_goal);
+				WRITE_ONCE(msk->allow_infinite_fallback, false);
+			}
 
-	/* limit retransmission to the bytes already sent on some subflows */
-	info.sent = 0;
-	info.limit = READ_ONCE(msk->csum_enabled) ? dfrag->data_len : dfrag->already_sent;
-	while (info.sent < info.limit) {
-		ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
-		if (ret <= 0)
-			break;
+			release_sock(ssk);
 
-		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RETRANSSEGS);
-		copied += ret;
-		info.sent += ret;
-	}
-	if (copied) {
-		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);
+			msk->last_snd = ssk;
+			mptcp_subflow_set_scheduled(subflow, false);
+		}
 	}
-
-	release_sock(ssk);
+	dfrag->already_sent = max(dfrag->already_sent, len);
 
 reset_timer:
 	mptcp_check_and_set_pending(sk);
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH mptcp-next v4 02/11] mptcp: add new argument ssk_first
  2022-10-02 14:25 ` [PATCH mptcp-next v4 02/11] mptcp: add new argument ssk_first Geliang Tang
@ 2022-10-05  0:16   ` Mat Martineau
  0 siblings, 0 replies; 18+ messages in thread
From: Mat Martineau @ 2022-10-05  0:16 UTC (permalink / raw)
  To: Geliang Tang; +Cc: mptcp

On Sun, 2 Oct 2022, Geliang Tang wrote:

> The function mptcp_subflow_process_delegated() uses the input ssk first,
> while __mptcp_check_push() invokes the packet scheduler first.
>
> So this patch adds a new argument named ssk_first for the function
> __mptcp_subflow_push_pending() to deal with these two cases separately.
>
> With this change, the code that invokes the packet scheduler in the
> fuction __mptcp_check_push() can be removed, and replaced by invoking
> __mptcp_subflow_push_pending() directly.
>
> Signed-off-by: Geliang Tang <geliang.tang@suse.com>
> ---
> net/mptcp/protocol.c | 22 ++++++++--------------
> 1 file changed, 8 insertions(+), 14 deletions(-)
>
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index cc8e67543e76..bbc43212a20f 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -1593,16 +1593,17 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
> 		__mptcp_check_send_data_fin(sk);
> }
>
> -static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
> +static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk,
> +					 bool ssk_first)
> {
> 	struct mptcp_sock *msk = mptcp_sk(sk);
> 	struct mptcp_sendmsg_info info = {
> 		.data_lock_held = true,
> 	};
> 	struct mptcp_data_frag *dfrag;
> +	bool first = ssk_first;

Hi Geliang -

Thanks for the v4.

If you add 'first' as the new argument instead of ssk_first, then you can 
remove this line and use 'first' everywhere.


- Mat


> 	struct sock *xmit_ssk;
> 	int len, copied = 0;
> -	bool first = true;
>
> 	info.flags = 0;
> 	while ((dfrag = mptcp_send_head(sk))) {
> @@ -1612,8 +1613,7 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
> 		while (len > 0) {
> 			int ret = 0;
>
> -			/* the caller already invoked the packet scheduler,
> -			 * check for a different subflow usage only after
> +			/* check for a different subflow usage only after
> 			 * spooling the first chunk of data
> 			 */
> 			xmit_ssk = first ? ssk : mptcp_subflow_get_send(mptcp_sk(sk));
> @@ -3195,16 +3195,10 @@ void __mptcp_check_push(struct sock *sk, struct sock *ssk)
> 	if (!mptcp_send_head(sk))
> 		return;
>
> -	if (!sock_owned_by_user(sk)) {
> -		struct sock *xmit_ssk = mptcp_subflow_get_send(mptcp_sk(sk));
> -
> -		if (xmit_ssk == ssk)
> -			__mptcp_subflow_push_pending(sk, ssk);
> -		else if (xmit_ssk)
> -			mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk), MPTCP_DELEGATE_SEND);
> -	} else {
> +	if (!sock_owned_by_user(sk))
> +		__mptcp_subflow_push_pending(sk, ssk, false);
> +	else
> 		__set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags);
> -	}
> }
>
> #define MPTCP_FLAGS_PROCESS_CTX_NEED (BIT(MPTCP_PUSH_PENDING) | \
> @@ -3295,7 +3289,7 @@ void mptcp_subflow_process_delegated(struct sock *ssk)
> 	if (test_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status)) {
> 		mptcp_data_lock(sk);
> 		if (!sock_owned_by_user(sk))
> -			__mptcp_subflow_push_pending(sk, ssk);
> +			__mptcp_subflow_push_pending(sk, ssk, true);
> 		else
> 			__set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags);
> 		mptcp_data_unlock(sk);
> -- 
> 2.35.3
>
>
>

--
Mat Martineau
Intel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH mptcp-next v4 03/11] mptcp: move burst check out of subflow_get_send
  2022-10-02 14:25 ` [PATCH mptcp-next v4 03/11] mptcp: move burst check out of subflow_get_send Geliang Tang
@ 2022-10-05  0:20   ` Mat Martineau
  2022-10-05  0:24     ` Mat Martineau
  0 siblings, 1 reply; 18+ messages in thread
From: Mat Martineau @ 2022-10-05  0:20 UTC (permalink / raw)
  To: Geliang Tang; +Cc: mptcp

On Sun, 2 Oct 2022, Geliang Tang wrote:

> This patch moves the burst check conditions out of the function
> mptcp_subflow_get_send(), check them in __mptcp_push_pending() and
> __mptcp_subflow_push_pending() in the inner "for each pending dfrag" loop.
>
> Signed-off-by: Geliang Tang <geliang.tang@suse.com>

This patch changes behavior in a way that would break MPTCP sends if 
someone was bisecting git commits. I recommend squashing this with the 
next patch and making sure the code tests ok.

> ---
> net/mptcp/protocol.c | 27 +++++++++++++++------------
> 1 file changed, 15 insertions(+), 12 deletions(-)
>
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index bbc43212a20f..785c52b738cf 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -1417,14 +1417,6 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk)
> 	u64 linger_time;
> 	long tout = 0;
>
> -	/* re-use last subflow, if the burst allow that */
> -	if (msk->last_snd && msk->snd_burst > 0 &&
> -	    sk_stream_memory_free(msk->last_snd) &&
> -	    mptcp_subflow_active(mptcp_subflow_ctx(msk->last_snd))) {
> -		mptcp_set_timeout(sk);
> -		return msk->last_snd;

Once msk->last_snd is removed here, that member of msk is no longer used 
and it can be removed from struct mptcp_sock. I think I mentioned this in 
a previous review - if I'm mistaken please correct me here. Otherwise I 
will keep making the same suggestion :)


- Mat


> -	}
> -
> 	/* pick the subflow with the lower wmem/wspace ratio */
> 	for (i = 0; i < SSK_MODE_MAX; ++i) {
> 		send_info[i].ssk = NULL;
> @@ -1477,16 +1469,13 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk)
>
> 	burst = min_t(int, MPTCP_SEND_BURST_SIZE, mptcp_wnd_end(msk) - msk->snd_nxt);
> 	wmem = READ_ONCE(ssk->sk_wmem_queued);
> -	if (!burst) {
> -		msk->last_snd = NULL;
> +	if (!burst)
> 		return ssk;
> -	}
>
> 	subflow = mptcp_subflow_ctx(ssk);
> 	subflow->avg_pacing_rate = div_u64((u64)subflow->avg_pacing_rate * wmem +
> 					   READ_ONCE(ssk->sk_pacing_rate) * burst,
> 					   burst + wmem);
> -	msk->last_snd = ssk;
> 	msk->snd_burst = burst;
> 	return ssk;
> }
> @@ -1579,6 +1568,13 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
> 			mptcp_update_post_push(msk, dfrag, ret);
> 		}
> 		WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
> +
> +		if (msk->snd_burst <= 0 ||
> +		    !sk_stream_memory_free(ssk) ||
> +		    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
> +			goto out;
> +		}
> +		mptcp_set_timeout(sk);
> 	}
>
> 	/* at this point we held the socket lock for the last subflow we used */
> @@ -1637,6 +1633,13 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk,
> 			mptcp_update_post_push(msk, dfrag, ret);
> 		}
> 		WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
> +
> +		if (msk->snd_burst <= 0 ||
> +		    !sk_stream_memory_free(ssk) ||
> +		    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
> +			goto out;
> +		}
> +		mptcp_set_timeout(sk);
> 	}
>
> out:
> -- 
> 2.35.3
>
>
>

--
Mat Martineau
Intel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH mptcp-next v4 04/11] mptcp: refactor push_pending logic
  2022-10-02 14:25 ` [PATCH mptcp-next v4 04/11] mptcp: refactor push_pending logic Geliang Tang
@ 2022-10-05  0:23   ` Mat Martineau
  0 siblings, 0 replies; 18+ messages in thread
From: Mat Martineau @ 2022-10-05  0:23 UTC (permalink / raw)
  To: Geliang Tang; +Cc: mptcp

On Sun, 2 Oct 2022, Geliang Tang wrote:

> To support redundant package schedulers more easily, this patch refactors
> __mptcp_push_pending() logic from:
>
> For each dfrag:
> 	While sends succeed:
> 		Call the scheduler (selects subflow and msk->snd_burst)
> 		Update subflow locks (push/release/acquire as needed)
> 		Send the dfrag data with mptcp_sendmsg_frag()
> 		Update already_sent, snd_nxt, snd_burst
> 	Update msk->first_pending
> Push/release on final subflow
>
> to:
>
> While the scheduler selects one subflow:
> 	Lock the subflow
> 	For each pending dfrag:
> 		While sends succeed:
> 			Send the dfrag data with mptcp_sendmsg_frag()
> 			Update already_sent, snd_nxt, snd_burst
> 		Update msk->first_pending
> 		Break if required by msk->snd_burst / etc
> 	Push and release the subflow
>
> Signed-off-by: Geliang Tang <geliang.tang@suse.com>
> ---
> net/mptcp/protocol.c | 76 +++++++++++++++++---------------------------
> 1 file changed, 30 insertions(+), 46 deletions(-)
>
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index 785c52b738cf..296b7135e9cf 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -1519,67 +1519,51 @@ void mptcp_check_and_set_pending(struct sock *sk)
>
> void __mptcp_push_pending(struct sock *sk, unsigned int flags)
> {
> -	struct sock *prev_ssk = NULL, *ssk = NULL;
> 	struct mptcp_sock *msk = mptcp_sk(sk);
> 	struct mptcp_sendmsg_info info = {
> 				.flags = flags,
> 	};
> 	bool do_check_data_fin = false;
> 	struct mptcp_data_frag *dfrag;
> +	struct sock *ssk;
> 	int len;
>
> -	while ((dfrag = mptcp_send_head(sk))) {
> -		info.sent = dfrag->already_sent;
> -		info.limit = dfrag->data_len;
> -		len = dfrag->data_len - dfrag->already_sent;
> -		while (len > 0) {
> -			int ret = 0;
> -
> -			prev_ssk = ssk;
> -			ssk = mptcp_subflow_get_send(msk);
> -
> -			/* First check. If the ssk has changed since
> -			 * the last round, release prev_ssk
> -			 */
> -			if (ssk != prev_ssk && prev_ssk)
> -				mptcp_push_release(prev_ssk, &info);
> -			if (!ssk)
> -				goto out;
> +	while (mptcp_send_head(sk) && (ssk = mptcp_subflow_get_send(msk))) {
> +		lock_sock(ssk);
>
> -			/* Need to lock the new subflow only if different
> -			 * from the previous one, otherwise we are still
> -			 * helding the relevant lock
> -			 */
> -			if (ssk != prev_ssk)
> -				lock_sock(ssk);
> +		while ((dfrag = mptcp_send_head(sk))) {
> +			info.sent = dfrag->already_sent;
> +			info.limit = dfrag->data_len;
> +			len = dfrag->data_len - dfrag->already_sent;
> +			while (len > 0) {
> +				int ret = 0;
> +
> +				ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
> +				if (ret <= 0) {
> +					if (ret == -EAGAIN)
> +						continue;
> +					mptcp_push_release(ssk, &info);
> +					goto out;
> +				}
> +
> +				do_check_data_fin = true;
> +				info.sent += ret;
> +				len -= ret;
> +
> +				mptcp_update_post_push(msk, dfrag, ret);
> +			}
> +			WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
>
> -			ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
> -			if (ret <= 0) {
> -				if (ret == -EAGAIN)
> -					continue;
> -				mptcp_push_release(ssk, &info);
> +			if (msk->snd_burst <= 0 ||
> +			    !sk_stream_memory_free(ssk) ||
> +			    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
> 				goto out;

When a burst is over, the scheduler needs to be called again. So rather 
than jumping out of both loops, this should repeat the outer while loop.

It also looks like there are code paths where mptcp_push_release() is not 
called, so the ssk is never unlocked. That should be fixed so this patch 
does not break git bisection.

- Mat

> 			}
> -
> -			do_check_data_fin = true;
> -			info.sent += ret;
> -			len -= ret;
> -
> -			mptcp_update_post_push(msk, dfrag, ret);
> -		}
> -		WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
> -
> -		if (msk->snd_burst <= 0 ||
> -		    !sk_stream_memory_free(ssk) ||
> -		    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
> -			goto out;
> +			mptcp_set_timeout(sk);
> 		}
> -		mptcp_set_timeout(sk);
> -	}
>
> -	/* at this point we held the socket lock for the last subflow we used */
> -	if (ssk)
> 		mptcp_push_release(ssk, &info);
> +	}
>
> out:
> 	/* ensure the rtx timer is running */
> -- 
> 2.35.3
>
>
>

--
Mat Martineau
Intel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH mptcp-next v4 03/11] mptcp: move burst check out of subflow_get_send
  2022-10-05  0:20   ` Mat Martineau
@ 2022-10-05  0:24     ` Mat Martineau
  0 siblings, 0 replies; 18+ messages in thread
From: Mat Martineau @ 2022-10-05  0:24 UTC (permalink / raw)
  To: Geliang Tang; +Cc: mptcp

On Tue, 4 Oct 2022, Mat Martineau wrote:

> On Sun, 2 Oct 2022, Geliang Tang wrote:
>
>> This patch moves the burst check conditions out of the function
>> mptcp_subflow_get_send(), check them in __mptcp_push_pending() and
>> __mptcp_subflow_push_pending() in the inner "for each pending dfrag" loop.
>> 
>> Signed-off-by: Geliang Tang <geliang.tang@suse.com>
>
> This patch changes behavior in a way that would break MPTCP sends if someone 
> was bisecting git commits. I recommend squashing this with the next patch and 
> making sure the code tests ok.
>
>> ---
>> net/mptcp/protocol.c | 27 +++++++++++++++------------
>> 1 file changed, 15 insertions(+), 12 deletions(-)
>> 
>> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
>> index bbc43212a20f..785c52b738cf 100644
>> --- a/net/mptcp/protocol.c
>> +++ b/net/mptcp/protocol.c
>> @@ -1417,14 +1417,6 @@ struct sock *mptcp_subflow_get_send(struct 
>> mptcp_sock *msk)
>> 	u64 linger_time;
>> 	long tout = 0;
>> 
>> -	/* re-use last subflow, if the burst allow that */
>> -	if (msk->last_snd && msk->snd_burst > 0 &&
>> -	    sk_stream_memory_free(msk->last_snd) &&
>> -	    mptcp_subflow_active(mptcp_subflow_ctx(msk->last_snd))) {
>> -		mptcp_set_timeout(sk);
>> -		return msk->last_snd;
>
> Once msk->last_snd is removed here, that member of msk is no longer used and 
> it can be removed from struct mptcp_sock. I think I mentioned this in a 
> previous review - if I'm mistaken please correct me here. Otherwise I will 
> keep making the same suggestion :)
>
>

Also, if msk->last_snd is removed, MPTCP_RESET_SCHEDULER can be removed 
too.

- Mat
>
>
>> -	}
>> -
>> 	/* pick the subflow with the lower wmem/wspace ratio */
>> 	for (i = 0; i < SSK_MODE_MAX; ++i) {
>> 		send_info[i].ssk = NULL;
>> @@ -1477,16 +1469,13 @@ struct sock *mptcp_subflow_get_send(struct 
>> mptcp_sock *msk)
>>
>> 	burst = min_t(int, MPTCP_SEND_BURST_SIZE, mptcp_wnd_end(msk) - 
>> msk->snd_nxt);
>> 	wmem = READ_ONCE(ssk->sk_wmem_queued);
>> -	if (!burst) {
>> -		msk->last_snd = NULL;
>> +	if (!burst)
>> 		return ssk;
>> -	}
>>
>> 	subflow = mptcp_subflow_ctx(ssk);
>> 	subflow->avg_pacing_rate = div_u64((u64)subflow->avg_pacing_rate * 
>> wmem +
>> 					   READ_ONCE(ssk->sk_pacing_rate) * 
>> burst,
>> 					   burst + wmem);
>> -	msk->last_snd = ssk;
>> 	msk->snd_burst = burst;
>> 	return ssk;
>> }
>> @@ -1579,6 +1568,13 @@ void __mptcp_push_pending(struct sock *sk, unsigned 
>> int flags)
>> 			mptcp_update_post_push(msk, dfrag, ret);
>> 		}
>> 		WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
>> +
>> +		if (msk->snd_burst <= 0 ||
>> +		    !sk_stream_memory_free(ssk) ||
>> +		    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
>> +			goto out;
>> +		}
>> +		mptcp_set_timeout(sk);
>> 	}
>>
>> 	/* at this point we held the socket lock for the last subflow we used 
>> */
>> @@ -1637,6 +1633,13 @@ static void __mptcp_subflow_push_pending(struct sock 
>> *sk, struct sock *ssk,
>> 			mptcp_update_post_push(msk, dfrag, ret);
>> 		}
>> 		WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
>> +
>> +		if (msk->snd_burst <= 0 ||
>> +		    !sk_stream_memory_free(ssk) ||
>> +		    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
>> +			goto out;
>> +		}
>> +		mptcp_set_timeout(sk);
>> 	}
>> 
>> out:
>> -- 
>> 2.35.3
>> 
>> 
>> 
>
> --
> Mat Martineau
> Intel
>
>

--
Mat Martineau
Intel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH mptcp-next v4 05/11] mptcp: simplify push_pending
  2022-10-02 14:25 ` [PATCH mptcp-next v4 05/11] mptcp: simplify push_pending Geliang Tang
@ 2022-10-05  0:33   ` Mat Martineau
  0 siblings, 0 replies; 18+ messages in thread
From: Mat Martineau @ 2022-10-05  0:33 UTC (permalink / raw)
  To: Geliang Tang; +Cc: mptcp

On Sun, 2 Oct 2022, Geliang Tang wrote:

> This patch moves the duplicate code from __mptcp_push_pending() and
> __mptcp_subflow_push_pending() into a new helper function, named
> __subflow_push_pending(). And simplify __mptcp_push_pending() by
> invoking this helper.
>
> Signed-off-by: Geliang Tang <geliang.tang@suse.com>
> ---
> net/mptcp/protocol.c | 90 +++++++++++++++++++++++---------------------
> 1 file changed, 48 insertions(+), 42 deletions(-)
>
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index 296b7135e9cf..66c97ac06a4e 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -1480,12 +1480,6 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk)
> 	return ssk;
> }
>
> -static void mptcp_push_release(struct sock *ssk, struct mptcp_sendmsg_info *info)
> -{
> -	tcp_push(ssk, 0, info->mss_now, tcp_sk(ssk)->nonagle, info->size_goal);
> -	release_sock(ssk);
> -}
> -
> static void mptcp_update_post_push(struct mptcp_sock *msk,
> 				   struct mptcp_data_frag *dfrag,
> 				   u32 sent)
> @@ -1517,6 +1511,52 @@ void mptcp_check_and_set_pending(struct sock *sk)
> 		mptcp_sk(sk)->push_pending |= BIT(MPTCP_PUSH_PENDING);
> }
>
> +static int __subflow_push_pending(struct sock *sk, struct sock *ssk,
> +				  struct mptcp_sendmsg_info *info)
> +{
> +	struct mptcp_sock *msk = mptcp_sk(sk);
> +	struct mptcp_data_frag *dfrag;
> +	int len, copied = 0;
> +
> +	while ((dfrag = mptcp_send_head(sk))) {
> +		info->sent = dfrag->already_sent;
> +		info->limit = dfrag->data_len;
> +		len = dfrag->data_len - dfrag->already_sent;
> +		while (len > 0) {
> +			int ret = 0;
> +
> +			ret = mptcp_sendmsg_frag(sk, ssk, dfrag, info);
> +			if (ret <= 0) {
> +				if (ret == -EAGAIN)
> +					continue;

In the older code, the scheduler got called again in the -EAGAIN case. 
With this refactored code, this could get in a very tight loop if 
mptcp_sendmsg_frag() returns. I think it's necessary to cleanly finish 
this loop iteration and let the scheduler run again in this -EAGAIN case.

> +				goto out;
> +			}
> +
> +			info->sent += ret;
> +			copied += ret;
> +			len -= ret;
> +
> +			mptcp_update_post_push(msk, dfrag, ret);
> +		}
> +		WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
> +
> +		if (msk->snd_burst <= 0 ||
> +		    !sk_stream_memory_free(ssk) ||
> +		    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
> +			goto out;
> +		}
> +		mptcp_set_timeout(sk);
> +	}
> +
> +out:
> +	if (copied) {
> +		tcp_push(ssk, 0, info->mss_now, tcp_sk(ssk)->nonagle,
> +			 info->size_goal);
> +	}
> +
> +	return copied;
> +}
> +
> void __mptcp_push_pending(struct sock *sk, unsigned int flags)
> {
> 	struct mptcp_sock *msk = mptcp_sk(sk);
> @@ -1524,48 +1564,14 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
> 				.flags = flags,
> 	};
> 	bool do_check_data_fin = false;
> -	struct mptcp_data_frag *dfrag;
> 	struct sock *ssk;
> -	int len;
>
> 	while (mptcp_send_head(sk) && (ssk = mptcp_subflow_get_send(msk))) {
> 		lock_sock(ssk);
> -
> -		while ((dfrag = mptcp_send_head(sk))) {
> -			info.sent = dfrag->already_sent;
> -			info.limit = dfrag->data_len;
> -			len = dfrag->data_len - dfrag->already_sent;
> -			while (len > 0) {
> -				int ret = 0;
> -
> -				ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
> -				if (ret <= 0) {
> -					if (ret == -EAGAIN)
> -						continue;
> -					mptcp_push_release(ssk, &info);
> -					goto out;
> -				}
> -
> -				do_check_data_fin = true;
> -				info.sent += ret;
> -				len -= ret;
> -
> -				mptcp_update_post_push(msk, dfrag, ret);
> -			}
> -			WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
> -
> -			if (msk->snd_burst <= 0 ||
> -			    !sk_stream_memory_free(ssk) ||
> -			    !mptcp_subflow_active(mptcp_subflow_ctx(ssk))) {
> -				goto out;
> -			}
> -			mptcp_set_timeout(sk);
> -		}
> -
> -		mptcp_push_release(ssk, &info);
> +		do_check_data_fin = __subflow_push_pending(sk, ssk, &info);

do_check_data_fin is a bool, but __subflow_push_pending() returns an 
int (the number of bytes copied). Looking at the other patches, the int 
value is needed. I suggest assigning the int return value to an int 
variable:

 		copied = __subflow_push_pending(sk, ssk, &info);

and updating the 'if' statement below...

> +		release_sock(ssk);
> 	}
>
> -out:
> 	/* ensure the rtx timer is running */
> 	if (!mptcp_timer_pending(sk))
> 		mptcp_reset_timer(sk);
>	if (do_check_data_fin)
> 		__mptcp_check_send_data_fin(sk);

...like this:

 	if (copied > 0)
  		__mptcp_check_send_data_fin(sk);


Thanks,

--
Mat Martineau
Intel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: mptcp: multi subflows retrans support: Tests Results
  2022-10-02 14:25 ` [PATCH mptcp-next v4 11/11] mptcp: multi subflows retrans support Geliang Tang
@ 2022-10-06 15:43   ` MPTCP CI
  0 siblings, 0 replies; 18+ messages in thread
From: MPTCP CI @ 2022-10-06 15:43 UTC (permalink / raw)
  To: Geliang Tang; +Cc: mptcp

Hi Geliang,

Thank you for your modifications, that's great!

Our CI did some validations and here is its report:

- KVM Validation: normal:
  - Success! ✅:
  - Task: https://cirrus-ci.com/task/6082444804751360
  - Summary: https://api.cirrus-ci.com/v1/artifact/task/6082444804751360/summary/summary.txt

- {"code":404,"message":
  - "Can't find artifacts containing file conclusion.txt"}:
  - Task: https://cirrus-ci.com/task/5519494851330048
  - Summary: https://api.cirrus-ci.com/v1/artifact/task/5519494851330048/summary/summary.txt

Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/bc515f11df5d


If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:

    $ cd [kernel source code]
    $ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
        --pull always mptcp/mptcp-upstream-virtme-docker:latest \
        auto-debug

For more details:

    https://github.com/multipath-tcp/mptcp-upstream-virtme-docker


Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)

Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (Tessares)

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2022-10-06 15:43 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-02 14:25 [PATCH mptcp-next v4 00/11] refactor push pending Geliang Tang
2022-10-02 14:25 ` [PATCH mptcp-next v4 01/11] Squash to "mptcp: add get_subflow wrappers" Geliang Tang
2022-10-02 14:25 ` [PATCH mptcp-next v4 02/11] mptcp: add new argument ssk_first Geliang Tang
2022-10-05  0:16   ` Mat Martineau
2022-10-02 14:25 ` [PATCH mptcp-next v4 03/11] mptcp: move burst check out of subflow_get_send Geliang Tang
2022-10-05  0:20   ` Mat Martineau
2022-10-05  0:24     ` Mat Martineau
2022-10-02 14:25 ` [PATCH mptcp-next v4 04/11] mptcp: refactor push_pending logic Geliang Tang
2022-10-05  0:23   ` Mat Martineau
2022-10-02 14:25 ` [PATCH mptcp-next v4 05/11] mptcp: simplify push_pending Geliang Tang
2022-10-05  0:33   ` Mat Martineau
2022-10-02 14:25 ` [PATCH mptcp-next v4 06/11] mptcp: multi subflows push_pending Geliang Tang
2022-10-02 14:25 ` [PATCH mptcp-next v4 07/11] mptcp: use msk instead of mptcp_sk Geliang Tang
2022-10-02 14:25 ` [PATCH mptcp-next v4 08/11] mptcp: refactor subflow_push_pending logic Geliang Tang
2022-10-02 14:25 ` [PATCH mptcp-next v4 09/11] mptcp: simplify subflow_push_pending Geliang Tang
2022-10-02 14:25 ` [PATCH mptcp-next v4 10/11] mptcp: multi subflows subflow_push_pending Geliang Tang
2022-10-02 14:25 ` [PATCH mptcp-next v4 11/11] mptcp: multi subflows retrans support Geliang Tang
2022-10-06 15:43   ` mptcp: multi subflows retrans support: Tests Results MPTCP CI

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.