diff mbox series

[RFC,08/14] mptcp: add and use mptcp_subflow_get_retrans

Message ID 20191114173225.21199-9-fw@strlen.de
State Superseded, archived
Headers show
Series [RFC] mptcp: wmem accounting and nonblocking io support | expand

Commit Message

Florian Westphal Nov. 14, 2019, 5:32 p.m. UTC
Instead of having retransmit worker grab first subflow on the list,
make it always return NULL, unless either the first non-backup subflow
on the list is idle or all normal subflows have already been removed.

In the latter case, the first idle backup subflow is used.

Rationale is that it makes no sense to attempt to retransmit
at mptcp level if there is still unsent data in its write queue.

V2: always return NULL when first non-idle ssk is seen.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/mptcp/protocol.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 83be407e1dd6..c5cf19a4b9f0 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -667,6 +667,37 @@  static void mptcp_retransmit_timer(struct timer_list *t)
 	sock_put(sk);
 }
 
+/* Find an idle subflow.  Return NULL if there is unacked data at tcp
+ * level.
+ *
+ * A backup subflow is returned only if thats the only kind available.
+ */
+static struct sock *mptcp_subflow_get_retrans(const struct mptcp_sock *msk)
+{
+	struct mptcp_subflow_context *subflow;
+	struct sock *backup = NULL;
+
+	sock_owned_by_me((const struct sock *)msk);
+
+	mptcp_for_each_subflow(msk, subflow) {
+		struct sock *ssk = mptcp_subflow_tcp_socket(subflow)->sk;
+
+		/* still data outstanding at TCP level?  Don't retransmit. */
+		if (!tcp_write_queue_empty(ssk))
+			return NULL;
+
+		if (subflow->backup) {
+			if (!backup)
+				backup = ssk;
+			continue;
+		}
+
+		return ssk;
+	}
+
+	return backup;
+}
+
 static void mptcp_worker(struct work_struct *work)
 {
 	int orig_len, orig_offset, ret, mss_now = 0, size_goal = 0;
@@ -691,7 +722,7 @@  static void mptcp_worker(struct work_struct *work)
 	if (!dfrag)
 		goto unlock;
 
-	ssk = mptcp_subflow_get(msk);
+	ssk = mptcp_subflow_get_retrans(msk);
 	if (!ssk)
 		goto reset_unlock;