Skip to content

Commit 40947e1

Browse files
Florian Westphaldavem330
authored andcommitted
mptcp: schedule worker when subflow is closed
When remote side closes a subflow we should schedule the worker to dispose of the subflow in a timely manner. Otherwise, SF_CLOSED event won't be generated until the mptcp socket itself is closing or local side is closing another subflow. Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a141e02 commit 40947e1

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

net/mptcp/protocol.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2170,6 +2170,10 @@ static void __mptcp_close_subflow(struct mptcp_sock *msk)
21702170
if (inet_sk_state_load(ssk) != TCP_CLOSE)
21712171
continue;
21722172

2173+
/* 'subflow_data_ready' will re-sched once rx queue is empty */
2174+
if (!skb_queue_empty_lockless(&ssk->sk_receive_queue))
2175+
continue;
2176+
21732177
mptcp_close_ssk((struct sock *)msk, ssk, subflow);
21742178
}
21752179
}

net/mptcp/subflow.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,22 @@ static void mptcp_subflow_discard_data(struct sock *ssk, struct sk_buff *skb,
953953
subflow->map_valid = 0;
954954
}
955955

956+
/* sched mptcp worker to remove the subflow if no more data is pending */
957+
static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ssk)
958+
{
959+
struct sock *sk = (struct sock *)msk;
960+
961+
if (likely(ssk->sk_state != TCP_CLOSE))
962+
return;
963+
964+
if (skb_queue_empty(&ssk->sk_receive_queue) &&
965+
!test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags)) {
966+
sock_hold(sk);
967+
if (!schedule_work(&msk->work))
968+
sock_put(sk);
969+
}
970+
}
971+
956972
static bool subflow_check_data_avail(struct sock *ssk)
957973
{
958974
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
@@ -991,11 +1007,11 @@ static bool subflow_check_data_avail(struct sock *ssk)
9911007
}
9921008

9931009
if (status != MAPPING_OK)
994-
return false;
1010+
goto no_data;
9951011

9961012
skb = skb_peek(&ssk->sk_receive_queue);
9971013
if (WARN_ON_ONCE(!skb))
998-
return false;
1014+
goto no_data;
9991015

10001016
/* if msk lacks the remote key, this subflow must provide an
10011017
* MP_CAPABLE-based mapping
@@ -1029,6 +1045,9 @@ static bool subflow_check_data_avail(struct sock *ssk)
10291045
}
10301046
return true;
10311047

1048+
no_data:
1049+
subflow_sched_work_if_closed(msk, ssk);
1050+
return false;
10321051
fatal:
10331052
/* fatal protocol error, close the socket */
10341053
/* This barrier is coupled with smp_rmb() in tcp_poll() */
@@ -1413,6 +1432,8 @@ static void subflow_state_change(struct sock *sk)
14131432
if (mptcp_subflow_data_available(sk))
14141433
mptcp_data_ready(parent, sk);
14151434

1435+
subflow_sched_work_if_closed(mptcp_sk(parent), sk);
1436+
14161437
if (__mptcp_check_fallback(mptcp_sk(parent)) &&
14171438
!subflow->rx_eof && subflow_is_done(sk)) {
14181439
subflow->rx_eof = 1;

0 commit comments

Comments
 (0)