Skip to content

Commit e16163b

Browse files
Paolo Abenikuba-moo
Paolo Abeni
authored andcommitted
mptcp: refactor shutdown and close
We must not close the subflows before all the MPTCP level data, comprising the DATA_FIN has been acked at the MPTCP level, otherwise we could be unable to retransmit as needed. __mptcp_wr_shutdown() shutdown is responsible to check for the correct status and close all subflows. Is called by the output path after spooling any data and at shutdown/close time. In a similar way, __mptcp_destroy_sock() is responsible to clean-up the MPTCP level status, and is called when the msk transition to TCP_CLOSE. The protocol level close() does not force anymore the TCP_CLOSE status, but orphan the msk socket and all the subflows. Orphaned msk sockets are forciby closed after a timeout or when all MPTCP-level data is acked. There is a caveat about keeping the orphaned subflows around: the TCP stack can asynchronusly call tcp_cleanup_ulp() on them via tcp_close(). To prevent accessing freed memory on later MPTCP level operations, the msk acquires a reference to each subflow socket and prevent subflow_ulp_release() from releasing the subflow context before __mptcp_destroy_sock(). The additional subflow references are released by __mptcp_done() and the async ULP release is detected checking ULP ops. If such field has been already cleared by the ULP release path, the dangling context is freed directly by __mptcp_done(). Co-developed-by: Davide Caratti <[email protected]> Signed-off-by: Davide Caratti <[email protected]> Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent eaa2ffa commit e16163b

File tree

5 files changed

+273
-110
lines changed

5 files changed

+273
-110
lines changed

net/mptcp/options.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
492492
bool ret = false;
493493

494494
mpext = skb ? mptcp_get_ext(skb) : NULL;
495-
snd_data_fin_enable = READ_ONCE(msk->snd_data_fin_enable);
495+
snd_data_fin_enable = mptcp_data_fin_enabled(msk);
496496

497497
if (!skb || (mpext && mpext->use_map) || snd_data_fin_enable) {
498498
unsigned int map_size;

net/mptcp/pm_netlink.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -416,14 +416,13 @@ void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk)
416416
list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
417417
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
418418
int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
419-
long timeout = 0;
420419

421420
if (msk->pm.rm_id != subflow->remote_id)
422421
continue;
423422

424423
spin_unlock_bh(&msk->pm.lock);
425424
mptcp_subflow_shutdown(sk, ssk, how);
426-
__mptcp_close_ssk(sk, ssk, subflow, timeout);
425+
__mptcp_close_ssk(sk, ssk, subflow);
427426
spin_lock_bh(&msk->pm.lock);
428427

429428
msk->pm.add_addr_accepted--;
@@ -452,14 +451,13 @@ void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk, u8 rm_id)
452451
list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
453452
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
454453
int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
455-
long timeout = 0;
456454

457455
if (rm_id != subflow->local_id)
458456
continue;
459457

460458
spin_unlock_bh(&msk->pm.lock);
461459
mptcp_subflow_shutdown(sk, ssk, how);
462-
__mptcp_close_ssk(sk, ssk, subflow, timeout);
460+
__mptcp_close_ssk(sk, ssk, subflow);
463461
spin_lock_bh(&msk->pm.lock);
464462

465463
msk->pm.local_addr_used--;

0 commit comments

Comments
 (0)