@@ -1508,7 +1508,9 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
struct mptcp_sock *msk = mptcp_sk(sk);
struct mptcp_sendmsg_info info;
struct mptcp_data_frag *dfrag;
+ struct sock *xmit_ssk;
int len, copied = 0;
+ bool first = true;
info.flags = 0;
while ((dfrag = mptcp_send_head(sk))) {
@@ -1518,6 +1520,18 @@ 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
+ * spooling the first chunk of data
+ */
+ xmit_ssk = first ? ssk : mptcp_subflow_get_send(mptcp_sk(sk));
+ if (!xmit_ssk)
+ goto out;
+ if (xmit_ssk != ssk) {
+ mptcp_subflow_defer(mptcp_subflow_ctx(xmit_ssk));
+ goto out;
+ }
+
if (unlikely(mptcp_must_reclaim_memory(sk, ssk))) {
__mptcp_update_wmem(sk);
sk_mem_reclaim_partial(sk);
@@ -1536,6 +1550,7 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
msk->tx_pending_data -= ret;
copied += ret;
len -= ret;
+ first = false;
}
WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
}
@@ -2244,7 +2259,6 @@ static void mptcp_worker(struct work_struct *work)
if (unlikely(state == TCP_CLOSE))
goto unlock;
- mptcp_push_pending(sk, 0);
mptcp_check_data_fin_ack(sk);
__mptcp_flush_join_list(msk);
@@ -2905,10 +2919,12 @@ void __mptcp_check_push(struct sock *sk, struct sock *ssk)
return;
if (!sock_owned_by_user(sk)) {
- if (mptcp_subflow_get_send(mptcp_sk(sk)) == ssk)
+ struct sock *xmit_ssk = mptcp_subflow_get_send(mptcp_sk(sk));
+
+ if (xmit_ssk == ssk)
__mptcp_subflow_push_pending(sk, ssk);
- else
- mptcp_schedule_work(sk);
+ else if (xmit_ssk)
+ mptcp_subflow_defer(mptcp_subflow_ctx(xmit_ssk));
} else {
set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags);
}
This change leverage the infrastructure introduced by the previous patch to avoid invoking the MPTCP worker to spool the pending data, when the packet scheduler picks a subflow other then the one currently processing the incoming MPTCP-level ack. Additinally we can fourther refine the subflow selection invoking the packet scheduler for each chunk of data even inside __mptcp_subflow_push_pending() Signed-off-by: Paolo Abeni <pabeni@redhat.com> --- net/mptcp/protocol.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)