To support redundant package schedulers more easily, this patch refactors
the data sending loop in __subflow_push_pending(), to delay updating
first_pending until all data is sent.
Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
net/mptcp/protocol.c | 36 ++++++++++++++++++++++++++++++++----
net/mptcp/protocol.h | 13 ++++++++++---
2 files changed, 42 insertions(+), 7 deletions(-)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index b8265badbe29..4c249d1b9ec6 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1112,6 +1112,7 @@ struct mptcp_sendmsg_info {
u16 sent;
unsigned int flags;
bool data_lock_held;
+ struct mptcp_data_frag *last_frag;
};
static int mptcp_check_allowed_size(const struct mptcp_sock *msk, struct sock *ssk,
@@ -1502,6 +1503,19 @@ static void mptcp_update_post_push(struct mptcp_sock *msk,
msk->snd_nxt = snd_nxt_new;
}
+static void mptcp_update_first_pending(struct sock *sk, struct mptcp_sendmsg_info *info)
+{
+ struct mptcp_sock *msk = mptcp_sk(sk);
+
+ if (info->last_frag)
+ WRITE_ONCE(msk->first_pending, mptcp_next_frag(sk, info->last_frag));
+}
+
+static void mptcp_update_dfrags(struct sock *sk, struct mptcp_sendmsg_info *info)
+{
+ mptcp_update_first_pending(sk, info);
+}
+
void mptcp_check_and_set_pending(struct sock *sk)
{
if (mptcp_send_head(sk))
@@ -1515,7 +1529,13 @@ static int __subflow_push_pending(struct sock *sk, struct sock *ssk,
struct mptcp_data_frag *dfrag;
int len, copied = 0, err = 0;
- while ((dfrag = mptcp_send_head(sk))) {
+ info->last_frag = NULL;
+
+ dfrag = mptcp_send_head(sk);
+ if (!dfrag)
+ goto out;
+
+ do {
info->sent = dfrag->already_sent;
info->limit = dfrag->data_len;
len = dfrag->data_len - dfrag->already_sent;
@@ -1534,7 +1554,8 @@ static int __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));
+ info->last_frag = dfrag;
+ dfrag = mptcp_next_frag(sk, dfrag);
if (msk->snd_burst <= 0 ||
!sk_stream_memory_free(ssk) ||
@@ -1543,7 +1564,7 @@ static int __subflow_push_pending(struct sock *sk, struct sock *ssk,
goto out;
}
mptcp_set_timeout(sk);
- }
+ } while (dfrag);
err = copied;
out:
@@ -1587,6 +1608,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
ret = __subflow_push_pending(sk, ssk, &info);
if (ret <= 0) {
+ mptcp_update_first_pending(sk, &info);
if (ret != -EAGAIN ||
inet_sk_state_load(ssk) == TCP_FIN_WAIT1 ||
inet_sk_state_load(ssk) == TCP_FIN_WAIT2 ||
@@ -1599,6 +1621,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
mptcp_subflow_set_scheduled(subflow, false);
}
}
+ mptcp_update_dfrags(sk, &info);
}
out:
@@ -1632,10 +1655,13 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool
if (first) {
ret = __subflow_push_pending(sk, ssk, &info);
first = false;
- if (ret <= 0)
+ if (ret <= 0) {
+ mptcp_update_first_pending(sk, &info);
break;
+ }
copied += ret;
msk->last_snd = ssk;
+ mptcp_update_dfrags(sk, &info);
continue;
}
@@ -1656,6 +1682,7 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool
ret = __subflow_push_pending(sk, ssk, &info);
if (ret <= 0) {
+ mptcp_update_first_pending(sk, &info);
err = 1;
continue;
}
@@ -1664,6 +1691,7 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool
mptcp_subflow_set_scheduled(subflow, false);
}
}
+ mptcp_update_dfrags(sk, &info);
}
out:
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 8536035a71d0..cdce0c092c3c 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -358,16 +358,23 @@ static inline struct mptcp_data_frag *mptcp_send_head(const struct sock *sk)
return READ_ONCE(msk->first_pending);
}
-static inline struct mptcp_data_frag *mptcp_send_next(struct sock *sk)
+static inline struct mptcp_data_frag *mptcp_next_frag(const struct sock *sk,
+ struct mptcp_data_frag *cur)
{
struct mptcp_sock *msk = mptcp_sk(sk);
- struct mptcp_data_frag *cur;
- cur = msk->first_pending;
+ if (!cur)
+ return NULL;
+
return list_is_last(&cur->list, &msk->rtx_queue) ? NULL :
list_next_entry(cur, list);
}
+static inline struct mptcp_data_frag *mptcp_send_next(const struct sock *sk)
+{
+ return mptcp_next_frag(sk, mptcp_send_head(sk));
+}
+
static inline struct mptcp_data_frag *mptcp_pending_tail(const struct sock *sk)
{
struct mptcp_sock *msk = mptcp_sk(sk);
--
2.35.3