Skip to content

Commit

Permalink
mptcp: don't orphan ssk in mptcp_close()
Browse files Browse the repository at this point in the history
All of the subflows of a msk will be orphaned in mptcp_close(), which
means the subflows are in DEAD state. After then, DATA_FIN will be sent,
and the other side will response with a DATA_ACK for this DATA_FIN.

However, if the other side still has pending data, the data that received
on these subflows will not be passed to the msk, as they are DEAD and
subflow_data_ready() will not be called in tcp_data_ready(). Therefore,
these data can't be acked, and they will be retransmitted again and again,
until timeout.

Fix this by setting ssk->sk_socket and ssk->sk_wq to 'NULL', instead of
orphaning the subflows in __mptcp_close(), as Paolo suggested.

Fixes: e16163b ("mptcp: refactor shutdown and close")
Reviewed-by: Biao Jiang <[email protected]>
Reviewed-by: Mengen Sun <[email protected]>
Signed-off-by: Menglong Dong <[email protected]>
Reviewed-by: Paolo Abeni <[email protected]>
Signed-off-by: Matthieu Baerts <[email protected]>
Signed-off-by: Jakub Kicinski <[email protected]>
  • Loading branch information
menglongdong authored and kuba-moo committed Nov 29, 2022
1 parent 39f59bc commit fe94800
Showing 1 changed file with 6 additions and 7 deletions.
13 changes: 6 additions & 7 deletions net/mptcp/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -2354,12 +2354,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
goto out;
}

/* if we are invoked by the msk cleanup code, the subflow is
* already orphaned
*/
if (ssk->sk_socket)
sock_orphan(ssk);

sock_orphan(ssk);
subflow->disposable = 1;

/* if ssk hit tcp_done(), tcp_cleanup_ulp() cleared the related ops
Expand Down Expand Up @@ -2940,7 +2935,11 @@ bool __mptcp_close(struct sock *sk, long timeout)
if (ssk == msk->first)
subflow->fail_tout = 0;

sock_orphan(ssk);
/* detach from the parent socket, but allow data_ready to
* push incoming data into the mptcp stack, to properly ack it
*/
ssk->sk_socket = NULL;
ssk->sk_wq = NULL;
unlock_sock_fast(ssk, slow);
}
sock_orphan(sk);
Expand Down

0 comments on commit fe94800

Please sign in to comment.