Skip to content

Commit 81c1d02

Browse files
Paolo Abenikuba-moo
authored andcommitted
mptcp: consolidate fallback and non fallback state machine
An orphaned msk releases the used resources via the worker, when the latter first see the msk in CLOSED status. If the msk status transitions to TCP_CLOSE in the release callback invoked by the worker's final release_sock(), such instance of the workqueue will not take any action. Additionally the MPTCP code prevents scheduling the worker once the socket reaches the CLOSE status: such msk resources will be leaked. The only code path that can trigger the above scenario is the __mptcp_check_send_data_fin() in fallback mode. Address the issue removing the special handling of fallback socket in __mptcp_check_send_data_fin(), consolidating the state machine for fallback and non fallback socket. Since non-fallback sockets do not send and do not receive data_fin, the mptcp code can update the msk internal status to match the next step in the SM every time data fin (ack) should be generated or received. As a consequence we can remove a bunch of checks for fallback from the fastpath. Fixes: 6e628cd ("mptcp: use mptcp release_cb for delayed tasks") Cc: [email protected] Signed-off-by: Paolo Abeni <[email protected]> Reviewed-by: Mat Martineau <[email protected]> Signed-off-by: Matthieu Baerts <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 56a666c commit 81c1d02

File tree

2 files changed

+25
-33
lines changed

2 files changed

+25
-33
lines changed

net/mptcp/protocol.c

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ enum {
4444
static struct percpu_counter mptcp_sockets_allocated ____cacheline_aligned_in_smp;
4545

4646
static void __mptcp_destroy_sock(struct sock *sk);
47-
static void __mptcp_check_send_data_fin(struct sock *sk);
47+
static void mptcp_check_send_data_fin(struct sock *sk);
4848

4949
DEFINE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions);
5050
static struct net_device mptcp_napi_dev;
@@ -424,8 +424,7 @@ static bool mptcp_pending_data_fin_ack(struct sock *sk)
424424
{
425425
struct mptcp_sock *msk = mptcp_sk(sk);
426426

427-
return !__mptcp_check_fallback(msk) &&
428-
((1 << sk->sk_state) &
427+
return ((1 << sk->sk_state) &
429428
(TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK)) &&
430429
msk->write_seq == READ_ONCE(msk->snd_una);
431430
}
@@ -583,9 +582,6 @@ static bool mptcp_check_data_fin(struct sock *sk)
583582
u64 rcv_data_fin_seq;
584583
bool ret = false;
585584

586-
if (__mptcp_check_fallback(msk))
587-
return ret;
588-
589585
/* Need to ack a DATA_FIN received from a peer while this side
590586
* of the connection is in ESTABLISHED, FIN_WAIT1, or FIN_WAIT2.
591587
* msk->rcv_data_fin was set when parsing the incoming options
@@ -623,7 +619,8 @@ static bool mptcp_check_data_fin(struct sock *sk)
623619
}
624620

625621
ret = true;
626-
mptcp_send_ack(msk);
622+
if (!__mptcp_check_fallback(msk))
623+
mptcp_send_ack(msk);
627624
mptcp_close_wake_up(sk);
628625
}
629626
return ret;
@@ -1609,7 +1606,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
16091606
if (!mptcp_timer_pending(sk))
16101607
mptcp_reset_timer(sk);
16111608
if (do_check_data_fin)
1612-
__mptcp_check_send_data_fin(sk);
1609+
mptcp_check_send_data_fin(sk);
16131610
}
16141611

16151612
static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool first)
@@ -2680,16 +2677,15 @@ static void mptcp_worker(struct work_struct *work)
26802677
if (unlikely((1 << state) & (TCPF_CLOSE | TCPF_LISTEN)))
26812678
goto unlock;
26822679

2683-
mptcp_check_data_fin_ack(sk);
2684-
26852680
mptcp_check_fastclose(msk);
26862681

26872682
mptcp_pm_nl_work(msk);
26882683

26892684
if (test_and_clear_bit(MPTCP_WORK_EOF, &msk->flags))
26902685
mptcp_check_for_eof(msk);
26912686

2692-
__mptcp_check_send_data_fin(sk);
2687+
mptcp_check_send_data_fin(sk);
2688+
mptcp_check_data_fin_ack(sk);
26932689
mptcp_check_data_fin(sk);
26942690

26952691
if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
@@ -2828,6 +2824,12 @@ void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)
28282824
pr_debug("Fallback");
28292825
ssk->sk_shutdown |= how;
28302826
tcp_shutdown(ssk, how);
2827+
2828+
/* simulate the data_fin ack reception to let the state
2829+
* machine move forward
2830+
*/
2831+
WRITE_ONCE(mptcp_sk(sk)->snd_una, mptcp_sk(sk)->snd_nxt);
2832+
mptcp_schedule_work(sk);
28312833
} else {
28322834
pr_debug("Sending DATA_FIN on subflow %p", ssk);
28332835
tcp_send_ack(ssk);
@@ -2867,7 +2869,7 @@ static int mptcp_close_state(struct sock *sk)
28672869
return next & TCP_ACTION_FIN;
28682870
}
28692871

2870-
static void __mptcp_check_send_data_fin(struct sock *sk)
2872+
static void mptcp_check_send_data_fin(struct sock *sk)
28712873
{
28722874
struct mptcp_subflow_context *subflow;
28732875
struct mptcp_sock *msk = mptcp_sk(sk);
@@ -2885,19 +2887,6 @@ static void __mptcp_check_send_data_fin(struct sock *sk)
28852887

28862888
WRITE_ONCE(msk->snd_nxt, msk->write_seq);
28872889

2888-
/* fallback socket will not get data_fin/ack, can move to the next
2889-
* state now
2890-
*/
2891-
if (__mptcp_check_fallback(msk)) {
2892-
WRITE_ONCE(msk->snd_una, msk->write_seq);
2893-
if ((1 << sk->sk_state) & (TCPF_CLOSING | TCPF_LAST_ACK)) {
2894-
inet_sk_state_store(sk, TCP_CLOSE);
2895-
mptcp_close_wake_up(sk);
2896-
} else if (sk->sk_state == TCP_FIN_WAIT1) {
2897-
inet_sk_state_store(sk, TCP_FIN_WAIT2);
2898-
}
2899-
}
2900-
29012890
mptcp_for_each_subflow(msk, subflow) {
29022891
struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);
29032892

@@ -2917,7 +2906,7 @@ static void __mptcp_wr_shutdown(struct sock *sk)
29172906
WRITE_ONCE(msk->write_seq, msk->write_seq + 1);
29182907
WRITE_ONCE(msk->snd_data_fin_enable, 1);
29192908

2920-
__mptcp_check_send_data_fin(sk);
2909+
mptcp_check_send_data_fin(sk);
29212910
}
29222911

29232912
static void __mptcp_destroy_sock(struct sock *sk)

net/mptcp/subflow.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1749,14 +1749,16 @@ static void subflow_state_change(struct sock *sk)
17491749
{
17501750
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
17511751
struct sock *parent = subflow->conn;
1752+
struct mptcp_sock *msk;
17521753

17531754
__subflow_state_change(sk);
17541755

1756+
msk = mptcp_sk(parent);
17551757
if (subflow_simultaneous_connect(sk)) {
17561758
mptcp_propagate_sndbuf(parent, sk);
17571759
mptcp_do_fallback(sk);
1758-
mptcp_rcv_space_init(mptcp_sk(parent), sk);
1759-
pr_fallback(mptcp_sk(parent));
1760+
mptcp_rcv_space_init(msk, sk);
1761+
pr_fallback(msk);
17601762
subflow->conn_finished = 1;
17611763
mptcp_set_connected(parent);
17621764
}
@@ -1772,11 +1774,12 @@ static void subflow_state_change(struct sock *sk)
17721774

17731775
subflow_sched_work_if_closed(mptcp_sk(parent), sk);
17741776

1775-
if (__mptcp_check_fallback(mptcp_sk(parent)) &&
1776-
!subflow->rx_eof && subflow_is_done(sk)) {
1777-
subflow->rx_eof = 1;
1778-
mptcp_subflow_eof(parent);
1779-
}
1777+
/* when the fallback subflow closes the rx side, trigger a 'dummy'
1778+
* ingress data fin, so that the msk state will follow along
1779+
*/
1780+
if (__mptcp_check_fallback(msk) && subflow_is_done(sk) && msk->first == sk &&
1781+
mptcp_update_rcv_data_fin(msk, READ_ONCE(msk->ack_seq), true))
1782+
mptcp_schedule_work(parent);
17801783
}
17811784

17821785
void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk)

0 commit comments

Comments
 (0)