From: sashiko-bot@kernel.org
To: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>,
"MPTCP Linux" <mptcp@lists.linux.dev>
Subject: Re: [PATCH mptcp-net 26/34] mptcp: don't send a FIN before the pending data on fallback
Date: Sat, 14 Nov 2026 00:27:50 +0000 [thread overview]
Message-ID: <sashiko-outbox-213924@kernel.org> (raw)
In-Reply-To: <20261113-mptcp-cmason-fixes-v1-26-9205b77e9a2f@kernel.org>
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] mptcp: missing TCP FIN in mptcp_try_fallback() after data
reinjection
- [Medium] mptcp: stalled pending data and FIN after fallback in
mptcp_try_fallback()
--
commit a99710492ed63fdd9aa5e8bcc3f5436e41a0c574
Author: Matthieu Baerts (NGI0) <matttbe@kernel.org>
mptcp: don't send a FIN before the pending data on fallback
This commit updates mptcp_try_fallback() to skip shutting down the subflow
at fallback time when mptcp_send_head(sk) is non-NULL, deferring the TCP
FIN until the pending data has been pushed.
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index e61b6a3a955de..d76eaed4f01eb 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -1339,7 +1339,10 @@ static inline bool mptcp_try_fallback(struct sock *ssk, int fb_mib)
>
> if (!__mptcp_try_fallback(msk, fb_mib))
> return false;
> - if (READ_ONCE(msk->snd_data_fin_enable) && !(ssk->sk_shutdown & SEND_SHUTDOWN)) {
> +
> + /* no FIN before pending data: see mptcp_check_send_data_fin() */
> + if (READ_ONCE(msk->snd_data_fin_enable) && !mptcp_send_head(sk) &&
> + !(ssk->sk_shutdown & SEND_SHUTDOWN)) {
> gfp_t saved_allocation = ssk->sk_allocation;
>
> /* we are in a atomic (BH) scope, override ssk default for data
[Severity: Medium]
Can this regression skip sending a TCP FIN altogether if
__mptcp_retransmit_pending_data() has reset msk->first_pending after
mptcp_check_send_data_fin() already ran?
Once all data is pushed to the initial subflow and the socket is shut
down, mptcp_check_send_data_fin() sets msk->snd_nxt = msk->write_seq.
If an unestablished MP_JOIN subflow then closes via __mptcp_close_ssk(),
__mptcp_retransmit_pending_data() resets msk->first_pending to rtx_head
without changing msk->snd_nxt. If the initial subflow falls back to TCP
before that reinjected data is processed, !mptcp_send_head(sk) is false
and mptcp_try_fallback() skips tcp_shutdown(ssk, SEND_SHUTDOWN) even
though ssk already has all data below msk->snd_nxt in its write queue.
Later, mptcp_sendmsg_frag() skips all bytes below msk->snd_nxt and
clears msk->first_pending back to NULL, but mptcp_check_send_data_fin()
will never run again because msk->snd_nxt == msk->write_seq:
net/mptcp/protocol.c:mptcp_check_send_data_fin() {
if (!msk->snd_data_fin_enable || msk->snd_nxt + 1 != msk->write_seq ||
mptcp_send_head(sk))
return;
WRITE_ONCE(msk->snd_nxt, msk->write_seq);
...
}
As a result, the subflow never sends a TCP FIN and stays in
TCP_ESTABLISHED while the MPTCP socket remains stuck in TCP_FIN_WAIT2.
Allowing the shutdown when mptcp_data_fin_enabled(msk) is true (i.e.
!mptcp_send_head(sk) || mptcp_data_fin_enabled(msk)) would avoid this.
[Severity: Medium]
Can this regression also leave both the pending data and the TCP FIN
unsent when a non-TFO subflow falls back while both sent unacknowledged
data and unsent queued data exist?
Suppose mptcp_rtx_head(sk) has dfrag->already_sent > 0, unsent data
remains queued at mptcp_send_head(sk), and the application calls
shutdown(SHUT_WR). When the peer sends a TCP ACK without MPTCP options
that acks the in-flight TCP data on ssk, check_fully_established() (when
!tcp_sk(ssk)->syn_fastopen_child) or subflow_check_data_avail() calls
mptcp_try_fallback() without updating msk->snd_una or calling
__mptcp_check_push(sk, ssk):
net/mptcp/options.c:check_fully_established() {
...
if (!mptcp_try_fallback(ssk, MPTCP_MIB_MPCAPABLEACTFALLBACK))
goto Inevitable;
if (tcp_sk(ssk)->syn_fastopen_child) {
mptcp_data_lock(sk);
__mptcp_check_push(sk, ssk);
mptcp_data_unlock(sk);
}
return false;
...
}
mptcp_try_fallback() clears MPTCP_RTX_ENABLED and skips
tcp_shutdown(ssk, SEND_SHUTDOWN) because mptcp_send_head(sk) is
non-NULL. When the MPTCP retransmit timer later fires, msk->snd_una is
still below msk->snd_nxt, so __mptcp_retrans() sees
dfrag->already_sent > 0 after fallback, gets -1 from
__mptcp_push_retrans(), and jumps to clear_scheduled without calling
mptcp_check_and_set_pending(sk). With ssk's TCP write queue empty and
the peer waiting for the remaining data and FIN, nothing ever pushes
mptcp_send_head(sk) or sends the FIN, stalling the connection.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261113-mptcp-cmason-fixes-v1-0-9205b77e9a2f@kernel.org?part=26
next prev parent reply other threads:[~2026-11-14 0:27 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 19:53 [PATCH mptcp-net 00/34] mptcp: misc fixes Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 01/34] tcp: drain the queues of a listen() that fails Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 02/34] mptcp: " Matthieu Baerts (NGI0)
2026-11-13 20:13 ` sashiko-bot
2026-11-13 19:53 ` [PATCH mptcp-net 03/34] mptcp: clear inet_opt in the child of an IPv6 listener Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 04/34] mptcp: pm: work on a copy of the received RM_ADDR list Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 05/34] mptcp: pm: don't drop an RM_ADDR behind a pending one Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 06/34] mptcp: pm: don't drop an RM_ADDR because of an ADD_ADDR Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 07/34] mptcp: arm the rtx timer if a push leaves data behind Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 08/34] mptcp: force the charge for the first skb of a subflow Matthieu Baerts (NGI0)
2026-11-13 20:09 ` sashiko-bot
2026-11-13 19:53 ` [PATCH mptcp-net 09/34] mptcp: leave an orphan's DATA_FIN to the worker Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 10/34] mptcp: don't leak an orphan when the PM closes its last subflow Matthieu Baerts (NGI0)
2026-11-13 21:10 ` sashiko-bot
2026-11-13 19:53 ` [PATCH mptcp-net 11/34] mptcp: do not use a raised snd_wnd for the send window Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 12/34] mptcp: drop non-MP_JOIN cookie ACKs on PM listeners Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 13/34] net: add __sk_net_refcnt_upgrade() with a GFP mask Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 14/34] mptcp: pm: don't let listeners pin their netns Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 15/34] mptcp: close a subflow reset for a bad mapping Matthieu Baerts (NGI0)
2026-11-13 21:40 ` sashiko-bot
2026-11-13 19:53 ` [PATCH mptcp-net 16/34] mptcp: initialize drop_req in subflow_init_req() Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 17/34] mptcp: pm: kernel: count endpoint listeners as sockets in use Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 18/34] mptcp: count a listener once when listen() is called again Matthieu Baerts (NGI0)
2026-11-13 19:53 ` [PATCH mptcp-net 19/34] mptcp: do not fallback while old data is in flight Matthieu Baerts (NGI0)
2026-11-13 22:29 ` sashiko-bot
2026-11-13 19:53 ` [PATCH mptcp-net 20/34] mptcp: stop resending data to a peer that fell back Matthieu Baerts (NGI0)
2026-11-13 22:53 ` sashiko-bot
2026-11-13 19:53 ` [PATCH mptcp-net 21/34] mptcp: pm: kernel: don't count signal+subflow ID 0 endp Matthieu Baerts (NGI0)
2026-11-13 19:54 ` [PATCH mptcp-net 22/34] selftests: mptcp: join: check re-adding " Matthieu Baerts (NGI0)
2026-11-13 19:54 ` [PATCH mptcp-net 23/34] mptcp: use sk instead of casting msk in check_fully_established() Matthieu Baerts (NGI0)
2026-11-13 19:54 ` [PATCH mptcp-net 24/34] mptcp: push queued data on passive TFO subflows becoming established Matthieu Baerts (NGI0)
2026-11-13 19:54 ` [PATCH mptcp-net 25/34] mptcp: push queued data on passive TFO subflows falling back to TCP Matthieu Baerts (NGI0)
2026-11-13 23:54 ` sashiko-bot
2026-11-13 19:54 ` [PATCH mptcp-net 26/34] mptcp: don't send a FIN before the pending data on fallback Matthieu Baerts (NGI0)
2026-11-14 0:27 ` sashiko-bot [this message]
2026-11-13 19:54 ` [PATCH mptcp-net 27/34] tcp: do not pass a BPF reqsk to an MPTCP listener Matthieu Baerts (NGI0)
2026-11-14 0:43 ` sashiko-bot
2026-11-13 19:54 ` [PATCH mptcp-net 28/34] mptcp: reclaim forward memory after coalescing skbs Matthieu Baerts (NGI0)
2026-11-13 19:54 ` [PATCH mptcp-net 29/34] mptcp: don't charge a shared page twice at accept() Matthieu Baerts (NGI0)
2026-11-13 19:54 ` [PATCH mptcp-net 30/34] mptcp: don't charge the backlog " Matthieu Baerts (NGI0)
2026-11-13 19:54 ` [PATCH mptcp-net 31/34] mptcp: don't charge a subflow twice when it joins during accept() Matthieu Baerts (NGI0)
2026-11-13 19:54 ` [PATCH mptcp-net 32/34] mptcp: fix dummy mapping of overlapping segments Matthieu Baerts (NGI0)
2026-11-13 19:54 ` [PATCH mptcp-net 33/34] mptcp: continue the last mapping after a fallback Matthieu Baerts (NGI0)
2026-11-13 19:54 ` [PATCH RFC mptcp-next mptcp-net 34/34] mptcp: reset when the DSS disappears after a DATA_ACK Matthieu Baerts (NGI0)
2026-11-13 21:58 ` [PATCH mptcp-net 00/34] mptcp: misc fixes MPTCP CI
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-213924@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=matttbe@kernel.org \
--cc=mptcp@lists.linux.dev \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.