net/mptcp/fastopen.c | 4 ++-- net/mptcp/options.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-)
With TCP Fast Open on an MPTCP listener, if the server application
writes data while the passive subflow is still in SYN_RECV (after
consuming the client's SYN data but before the MP_CAPABLE third ACK
arrives), __mptcp_subflow_active() refuses transmission and the data
is queued into the msk write queue.
When the MPC third ACK arrives, the subflow transitions to
TCP_ESTABLISHED and is marked fully established in
check_fully_established(), but because the third ACK carries no
DSS data, the queued bytes remain stranded until the peer sends
more data.
Fix this in check_fully_established() by checking if the subflow
was doing passive TFO (subflow->is_mptfo). Under mptcp_data_lock(),
flush queued bytes via __mptcp_check_push().
Additionally, ensure subflow->is_mptfo is set in
mptcp_fastopen_subflow_synack_set_params() even if the cookie-bearing
SYN carries no data, so that server-first replies on zero-data TFO
connections are also pushed upon 3WHS completion.
Suggested-by: Petar Sakic <petar.sakic@ink.fish>
Reported-by: Petar Sakic <petar.sakic@ink.fish>
Closes: https://lore.kernel.org/netdev/CAFPPu1gU2Y-D+d4i3F0MoNkYK+e1U+=X3qf6QycjfKBw+8snPg@mail.gmail.com/
Fixes: fb7084501a61 ("mptcp: add support for TCP_FASTOPEN sockopt")
Tested-by: Petar Sakic <petar.sakic@ink.fish>
Signed-off-by: T S Rameshkumar <rameshkumar.t@phytecembedded.in>
---
v3:
- In mptcp_fastopen_subflow_synack_set_params(), set subflow->is_mptfo
unconditionally before checking for SYN data in the receive queue,
ensuring server-first replies on zero-data TFO connections are also
pushed upon 3WHS completion (Petar Sakic).
- Added Tested-by tag for Petar Sakic.
v2:
- Reverted moving/clearing is_mptfo since check_fully_established() is
only called once and is_mptfo is read-only at this stage (Matthieu Baerts).
- Added Suggested-by tag for Petar Sakic.
- Rebased cleanly on top of mptcp_net-next export branch.
---
net/mptcp/fastopen.c | 4 ++--
net/mptcp/options.c | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c
index f71775090..c4c525019 100644
--- a/net/mptcp/fastopen.c
+++ b/net/mptcp/fastopen.c
@@ -24,13 +24,13 @@ void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subf
sk = subflow->conn;
tp = tcp_sk(ssk);
+ subflow->is_mptfo = 1;
+
/* A valid TFO cookie does not guarantee SYN data. */
skb = skb_peek(&ssk->sk_receive_queue);
if (!skb)
return;
- subflow->is_mptfo = 1;
-
/* dequeue the skb from sk receive queue */
__skb_unlink(skb, &ssk->sk_receive_queue);
skb_ext_reset(skb);
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index adbf8e077..0e1dd57bf 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -1046,6 +1046,8 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
mptcp_data_lock((struct sock *)msk);
__mptcp_subflow_fully_established(msk, subflow, mp_opt);
+ if (subflow->is_mptfo)
+ __mptcp_check_push((struct sock *)msk, ssk);
mptcp_data_unlock((struct sock *)msk);
check_notify:
--
2.34.1
Hi T S, On 13/10/2026 10:02, T S Rameshkumar wrote: > With TCP Fast Open on an MPTCP listener, if the server application > writes data while the passive subflow is still in SYN_RECV (after > consuming the client's SYN data but before the MP_CAPABLE third ACK > arrives), __mptcp_subflow_active() refuses transmission and the data > is queued into the msk write queue. > > When the MPC third ACK arrives, the subflow transitions to > TCP_ESTABLISHED and is marked fully established in > check_fully_established(), but because the third ACK carries no > DSS data, the queued bytes remain stranded until the peer sends > more data. > > Fix this in check_fully_established() by checking if the subflow > was doing passive TFO (subflow->is_mptfo). Under mptcp_data_lock(), > flush queued bytes via __mptcp_check_push(). > > Additionally, ensure subflow->is_mptfo is set in > mptcp_fastopen_subflow_synack_set_params() even if the cookie-bearing > SYN carries no data, so that server-first replies on zero-data TFO > connections are also pushed upon 3WHS completion. (...) > diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c > index f71775090..c4c525019 100644 > --- a/net/mptcp/fastopen.c > +++ b/net/mptcp/fastopen.c > @@ -24,13 +24,13 @@ void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subf > sk = subflow->conn; > tp = tcp_sk(ssk); > > + subflow->is_mptfo = 1; > + > /* A valid TFO cookie does not guarantee SYN data. */ > skb = skb_peek(&ssk->sk_receive_queue); > if (!skb) > return; > > - subflow->is_mptfo = 1; No, we cannot do that: https://lore.kernel.org/3f9d7081-65f1-4618-8f34-d95e3f84824e@kernel.org Please wait for the discussions to settle before sending new versions. Cheers, Matt -- Sponsored by the NGI0 Core fund.
Hi T,
Thank you for your modifications, that's great!
Our CI did some validations and here is its report:
- KVM Validation: normal (except selftest_mptcp_join): Success! ✅
- KVM Validation: normal (only selftest_mptcp_join): Success! ✅
- KVM Validation: debug (except selftest_mptcp_join): Success! ✅
- KVM Validation: debug (only selftest_mptcp_join): Success! ✅
- KVM Validation: btf-normal (only bpftest_all): Success! ✅
- KVM Validation: btf-debug (only bpftest_all): Success! ✅
- Perf: Success! ✅
- Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/38368903325
Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/9a32a1768402
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1184480
If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:
$ cd [kernel source code]
$ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
--pull always mptcp/mptcp-upstream-virtme-docker:latest \
auto-normal
For more details:
https://github.com/multipath-tcp/mptcp-upstream-virtme-docker
Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)
Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)
© 2016 - 2026 Red Hat, Inc.