net/mptcp/pm_kernel.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
syzkaller hit the WARN_ON_ONCE() in mptcp_pm_alloc_anno_list() with
the in-kernel path manager.
When a signal endpoint is removed, the pending ADD_ADDR has to be
cancelled: its retransmit timer stopped and the anno_list entry
unlinked and freed. For a non-zero id endpoint this is done via
mptcp_nl_remove_subflow_and_signal_addr() ->
mptcp_pm_remove_anno_addr() -> mptcp_remove_anno_list_by_saddr().
The id 0 removal path, mptcp_nl_remove_id_zero_address(), does not do
this: it only queues a RM_ADDR and marks the id available again, but
leaves any pending anno_list entry and its armed retransmit timer
alive.
So when the id 0 endpoint is removed and re-added while its previously
sent ADD_ADDR is still awaiting the echo, the stale entry survives.
The kernel PM reselects id 0, reaches mptcp_pm_alloc_anno_list() a
second time, finds the stale entry and hits the WARN.
Make the id 0 removal path symmetric with the non-zero one: drop the
pending ADD_ADDR before queuing the RM_ADDR, and decrement
add_addr_signaled if the address had been announced. This closes the
race at its source, so the WARN_ON_ONCE() stays a valid assertion.
Fixes: 740d798e8767 ("mptcp: remove id 0 address")
Reported-by: syzbot+55c2a5c871441261ed14@syzkaller.appspotmail.com
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/620
Signed-off-by: Kalpan Jani <kalpan.jani@mpiricsoftware.com>
---
v1 -> v2:
- Do not drop the WARN_ON_ONCE(); it is a valid assertion.
(Matthieu Baerts)
- Fix mptcp_nl_remove_id_zero_address() to tear down the pending
ADD_ADDR entry: call mptcp_remove_anno_list_by_saddr() and
decrement add_addr_signaled, mirroring the non-zero id path.
(Matthieu Baerts)
net/mptcp/pm_kernel.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/net/mptcp/pm_kernel.c b/net/mptcp/pm_kernel.c
index fc818b63752e..ed0ad1c1b140 100644
--- a/net/mptcp/pm_kernel.c
+++ b/net/mptcp/pm_kernel.c
@@ -1126,6 +1126,7 @@ static int mptcp_nl_remove_id_zero_address(struct net *net,
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
struct sock *sk = (struct sock *)msk;
struct mptcp_addr_info msk_local;
+ bool announced;
if (list_empty(&msk->conn_list) || mptcp_pm_is_userspace(msk))
goto next;
@@ -1135,7 +1136,16 @@ static int mptcp_nl_remove_id_zero_address(struct net *net,
goto next;
lock_sock(sk);
+ /* Drop a possibly pending ADD_ADDR for this address: stop its
+ * retransmit timer and unlink the anno_list entry, so a later
+ * re-add cannot find a stale entry and hit the WARN_ON_ONCE()
+ * in mptcp_pm_alloc_anno_list(). Mirrors the non-zero id path
+ * in mptcp_pm_remove_anno_addr().
+ */
+ announced = mptcp_remove_anno_list_by_saddr(msk, &msk_local);
spin_lock_bh(&msk->pm.lock);
+ if (announced)
+ msk->pm.add_addr_signaled--;
mptcp_pm_remove_addr(msk, &list);
mptcp_pm_rm_subflow(msk, &list);
__mark_subflow_endp_available(msk, 0);
--
2.43.0
Hi Kalpan,
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! ✅
- Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/26623410540
Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/ed6268d8c29c
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1102655
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)
Hi Kalpan,
Thank you for the v2.
29 May 2026 16:44:12 Kalpan Jani <kalpan.jani@mpiricsoftware.com>:
> syzkaller hit the WARN_ON_ONCE() in mptcp_pm_alloc_anno_list() with
> the in-kernel path manager.
>
> When a signal endpoint is removed, the pending ADD_ADDR has to be
> cancelled: its retransmit timer stopped and the anno_list entry
> unlinked and freed. For a non-zero id endpoint this is done via
> mptcp_nl_remove_subflow_and_signal_addr() ->
> mptcp_pm_remove_anno_addr() -> mptcp_remove_anno_list_by_saddr().
>
> The id 0 removal path, mptcp_nl_remove_id_zero_address(), does not do
> this: it only queues a RM_ADDR and marks the id available again, but
> leaves any pending anno_list entry and its armed retransmit timer
> alive.
>
> So when the id 0 endpoint is removed and re-added while its previously
> sent ADD_ADDR is still awaiting the echo, the stale entry survives.
> The kernel PM reselects id 0, reaches mptcp_pm_alloc_anno_list() a
> second time, finds the stale entry and hits the WARN.
>
> Make the id 0 removal path symmetric with the non-zero one: drop the
> pending ADD_ADDR before queuing the RM_ADDR, and decrement
> add_addr_signaled if the address had been announced. This closes the
> race at its source, so the WARN_ON_ONCE() stays a valid assertion.
>
> Fixes: 740d798e8767 ("mptcp: remove id 0 address")
> Reported-by: syzbot+55c2a5c871441261ed14@syzkaller.appspotmail.com
> Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/620
> Signed-off-by: Kalpan Jani <kalpan.jani@mpiricsoftware.com>
> ---
>
> v1 -> v2:
> - Do not drop the WARN_ON_ONCE(); it is a valid assertion.
> (Matthieu Baerts)
> - Fix mptcp_nl_remove_id_zero_address() to tear down the pending
> ADD_ADDR entry: call mptcp_remove_anno_list_by_saddr() and
> decrement add_addr_signaled, mirroring the non-zero id path.
> (Matthieu Baerts)
>
> net/mptcp/pm_kernel.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/net/mptcp/pm_kernel.c b/net/mptcp/pm_kernel.c
> index fc818b63752e..ed0ad1c1b140 100644
> --- a/net/mptcp/pm_kernel.c
> +++ b/net/mptcp/pm_kernel.c
> @@ -1126,6 +1126,7 @@ static int mptcp_nl_remove_id_zero_address(struct net *net,
> while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
> struct sock *sk = (struct sock *)msk;
> struct mptcp_addr_info msk_local;
> + bool announced;
>
> if (list_empty(&msk->conn_list) || mptcp_pm_is_userspace(msk))
> goto next;
> @@ -1135,7 +1136,16 @@ static int mptcp_nl_remove_id_zero_address(struct net *net,
> goto next;
>
> lock_sock(sk);
> + /* Drop a possibly pending ADD_ADDR for this address: stop its
> + * retransmit timer and unlink the anno_list entry, so a later
> + * re-add cannot find a stale entry and hit the WARN_ON_ONCE()
> + * in mptcp_pm_alloc_anno_list(). Mirrors the non-zero id path
> + * in mptcp_pm_remove_anno_addr().
> + */
I'm not sure such a long comment in the code is that useful, and it
might: it can quickly become outdated when other parts are modified.
Limit it to the first line, the rest can be seen in the commit message.
> + announced = mptcp_remove_anno_list_by_saddr(msk, &msk_local);
> spin_lock_bh(&msk->pm.lock);
> + if (announced)
> + msk->pm.add_addr_signaled--;
It would be good to check this counter on the test/reproducer you will
provide. Did it work with packetdrill?
Cheers,
Matt
> mptcp_pm_remove_addr(msk, &list);
> mptcp_pm_rm_subflow(msk, &list);
> __mark_subflow_endp_available(msk, 0);
> --
> 2.43.0
Hi Matt,
> Did it work with packetdrill?
I worked on a packetdrill test based on add_addr4_server.pkt with the
MP_JOIN extra subflow and the delete/re-add sequence. The environment
is working (add_addr4_server.pkt passes cleanly), but I was not able
to reliably trigger the WARN through packetdrill within the test
timeframe.
The difficulty is that the id 0 ADD_ADDR is only sent when the
endpoint is re-added after the connection is established AND after
mptcp_nl_remove_id_zero_address() has run to restore the
id_avail_bitmap bit via __mark_subflow_endp_available(). Getting
packetdrill to control this timing precisely — while also keeping
conn_list non-empty so mptcp_nl_remove_id_zero_address() actually
processes the msk — proved tricky.
syzbot is reproducing the bug reliably on current upstream (3 crashes
between 2026/05/19 and 2026/05/22 on kernels including cca95436be15).
The syzbot reproducer is the most reliable pre-fix evidence available.
I will continue working on the packetdrill test and send it as a
follow-up once I have a clean before/after result. For v3 I have
addressed your comment shortening request.
Thanks,
Kalpan Jani
From: Matthieu Baerts <matttbe@kernel.org>
To: "Kalpan Jani"<kalpan.jani@mpiricsoftware.com>
Cc: <mptcp@lists.linux.dev>, <martineau@kernel.org>, <pabeni@redhat.com>, <shardul.b@mpiricsoftware.com>, <janak@mpiric.us>, <kalpanjani009@gmail.com>, <shardulsb08@gmail.com>, <syzbot+55c2a5c871441261ed14@syzkaller.appspotmail.com>
Date: Fri, 29 May 2026 12:25:09 +0530
Subject: Re: [PATCH net v2] mptcp: pm: drop pending ADD_ADDR when removing id 0 endpoint
> Hi Kalpan,
>
> Thank you for the v2.
>
> 29 May 2026 16:44:12 Kalpan Jani <kalpan.jani@mpiricsoftware.com>:
>
> > syzkaller hit the WARN_ON_ONCE() in mptcp_pm_alloc_anno_list() with
> > the in-kernel path manager.
> >
> > When a signal endpoint is removed, the pending ADD_ADDR has to be
> > cancelled: its retransmit timer stopped and the anno_list entry
> > unlinked and freed. For a non-zero id endpoint this is done via
> > mptcp_nl_remove_subflow_and_signal_addr() ->
> > mptcp_pm_remove_anno_addr() -> mptcp_remove_anno_list_by_saddr().
> >
> > The id 0 removal path, mptcp_nl_remove_id_zero_address(), does not do
> > this: it only queues a RM_ADDR and marks the id available again, but
> > leaves any pending anno_list entry and its armed retransmit timer
> > alive.
> >
> > So when the id 0 endpoint is removed and re-added while its previously
> > sent ADD_ADDR is still awaiting the echo, the stale entry survives.
> > The kernel PM reselects id 0, reaches mptcp_pm_alloc_anno_list() a
> > second time, finds the stale entry and hits the WARN.
> >
> > Make the id 0 removal path symmetric with the non-zero one: drop the
> > pending ADD_ADDR before queuing the RM_ADDR, and decrement
> > add_addr_signaled if the address had been announced. This closes the
> > race at its source, so the WARN_ON_ONCE() stays a valid assertion.
> >
> > Fixes: 740d798e8767 ("mptcp: remove id 0 address")
> > Reported-by: syzbot+55c2a5c871441261ed14@syzkaller.appspotmail.com
> > Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/620
> > Signed-off-by: Kalpan Jani <kalpan.jani@mpiricsoftware.com>
> > ---
> >
> > v1 -> v2:
> > - Do not drop the WARN_ON_ONCE(); it is a valid assertion.
> > (Matthieu Baerts)
> > - Fix mptcp_nl_remove_id_zero_address() to tear down the pending
> > ADD_ADDR entry: call mptcp_remove_anno_list_by_saddr() and
> > decrement add_addr_signaled, mirroring the non-zero id path.
> > (Matthieu Baerts)
> >
> > net/mptcp/pm_kernel.c | 10 ++++++++++
> > 1 file changed, 10 insertions(+)
> >
> > diff --git a/net/mptcp/pm_kernel.c b/net/mptcp/pm_kernel.c
> > index fc818b63752e..ed0ad1c1b140 100644
> > --- a/net/mptcp/pm_kernel.c
> > +++ b/net/mptcp/pm_kernel.c
> > @@ -1126,6 +1126,7 @@ static int mptcp_nl_remove_id_zero_address(struct net *net,
> > while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
> > struct sock *sk = (struct sock *)msk;
> > struct mptcp_addr_info msk_local;
> > + bool announced;
> >
> > if (list_empty(&msk->conn_list) || mptcp_pm_is_userspace(msk))
> > goto next;
> > @@ -1135,7 +1136,16 @@ static int mptcp_nl_remove_id_zero_address(struct net *net,
> > goto next;
> >
> > lock_sock(sk);
> > + /* Drop a possibly pending ADD_ADDR for this address: stop its
> > + * retransmit timer and unlink the anno_list entry, so a later
> > + * re-add cannot find a stale entry and hit the WARN_ON_ONCE()
> > + * in mptcp_pm_alloc_anno_list(). Mirrors the non-zero id path
> > + * in mptcp_pm_remove_anno_addr().
> > + */
>
> I'm not sure such a long comment in the code is that useful, and it
> might: it can quickly become outdated when other parts are modified.
> Limit it to the first line, the rest can be seen in the commit message.
>
> > + announced = mptcp_remove_anno_list_by_saddr(msk, &msk_local);
> > spin_lock_bh(&msk->pm.lock);
> > + if (announced)
> > + msk->pm.add_addr_signaled--;
>
> It would be good to check this counter on the test/reproducer you will
> provide. Did it work with packetdrill?
>
> Cheers,
> Matt
>
> > mptcp_pm_remove_addr(msk, &list);
> > mptcp_pm_rm_subflow(msk, &list);
> > __mark_subflow_endp_available(msk, 0);
> > --
> > 2.43.0
>
>
Hi Kalpan, On 29/05/2026 17:18, Kalpan Jani wrote: > Hi Matt, > >> Did it work with packetdrill? > > I worked on a packetdrill test based on add_addr4_server.pkt with the > MP_JOIN extra subflow and the delete/re-add sequence. The environment > is working (add_addr4_server.pkt passes cleanly), but I was not able > to reliably trigger the WARN through packetdrill within the test > timeframe. > > The difficulty is that the id 0 ADD_ADDR is only sent when the > endpoint is re-added after the connection is established AND after > mptcp_nl_remove_id_zero_address() has run to restore the > id_avail_bitmap bit via __mark_subflow_endp_available(). Getting > packetdrill to control this timing precisely — while also keeping > conn_list non-empty so mptcp_nl_remove_id_zero_address() actually > processes the msk — proved tricky. I understand it might be tricky, but do you mind sharing what you have so far. Maybe someone else can help you to reproduce the issue. Also, it might be enough to have a test that can reproduce the WARN not 100% of the time, as long as it is not 0. I will wait for this test before applying the v3. At least having something exercising new paths: here, having the new call to mptcp_remove_anno_list_by_saddr() returning true. > syzbot is reproducing the bug reliably on current upstream (3 crashes > between 2026/05/19 and 2026/05/22 on kernels including cca95436be15). > The syzbot reproducer is the most reliable pre-fix evidence available. Because syzbot didn't manage to generate a reproducer, we cannot really rely on syzbot to say that the bug is fixed. 3 crashes out of how many thousands/millions attempts? :) > I will continue working on the packetdrill test and send it as a > follow-up once I have a clean before/after result. For v3 I have > addressed your comment shortening request. Thanks! Do not forget to wait ~1 day between submissions, otherwise it is even harder for reviewers and various tools to follow the modifications and discussions. Cheers, Matt -- Sponsored by the NGI0 Core fund.
Hi Matt, > do you mind sharing what you have so far. Maybe someone else can help > you to reproduce the issue. Attached is the WIP packetdrill test (server side, based on the existing add_addr/mp_join server tests, with an extra MP_JOIN subflow). I have not been able to reproduce the WARN with it yet, so please treat it as a work-in-progress rather than a finished test -- the status and the open question are written at the top of the file. The trigger is "ip mptcp endpoint delete id 0 <saddr>", which is the only op that reaches mptcp_nl_remove_id_zero_address(). (flush is not usable: it goes through mptcp_pm_flush_addrs_and_subflows(), which already calls mptcp_pm_announced_remove(), so that path was never buggy.) Where I am stuck is getting ADD_ADDR(id 0) announced in the first place. The signal endpoint on the MPC address has its id bit cleared by mptcp_mpc_endpoint_setup(), so it is not announced on connect. "delete id 0" frees the bit again, but I could not confirm that the PM worker re-runs and announces id 0 on an otherwise idle connection. Without that announcement no pending anno_list entry is created, so the second "delete id 0" has nothing stale to leave behind and the WARN does not trigger. So my question: what is the minimal way to get the id-0 address actually announced via packetdrill? Does this need the MP_JOIN subflow and/or a data exchange to wake the PM worker between the operations, or is there a simpler approach I am missing? > I will wait for this test before applying the v3. Understood, I will keep working on it. One thing I wanted to ask directly: is a deterministic packetdrill test a hard requirement for applying v3, or could the fix go in on the reasoning + the syzbot report alone? The change only makes the id-0 removal path symmetric with the non-zero id path (tear down the pending ADD_ADDR and decrement add_addr_signaled), so it is fairly contained and independent of whether I can script a reliable trigger. (Note: the anno-list helpers were renamed in current export, so v3 no longer applies as-is; I can send a trivially rebased v4 that swaps mptcp_remove_anno_list_by_saddr() for mptcp_pm_announced_remove() if useful.) Cheers, Kalpan Jani From: Matthieu Baerts <matttbe@kernel.org> To: "Kalpan Jani"<kalpan.jani@mpiricsoftware.com> Cc: "mptcp"<mptcp@lists.linux.dev>, "martineau"<martineau@kernel.org>, "pabeni"<pabeni@redhat.com>, "shardul.b"<shardul.b@mpiricsoftware.com>, "janak"<janak@mpiric.us>, "kalpanjani009"<kalpanjani009@gmail.com>, "shardulsb08"<shardulsb08@gmail.com>, "syzbot+55c2a5c871441261ed14"<syzbot+55c2a5c871441261ed14@syzkaller.appspotmail.com> Date: Sun, 31 May 2026 12:09:53 +0530 Subject: Re: [PATCH net v2] mptcp: pm: drop pending ADD_ADDR when removing id 0 endpoint > Hi Kalpan, > > On 29/05/2026 17:18, Kalpan Jani wrote: > > Hi Matt, > > > >> Did it work with packetdrill? > > > > I worked on a packetdrill test based on add_addr4_server.pkt with the > > MP_JOIN extra subflow and the delete/re-add sequence. The environment > > is working (add_addr4_server.pkt passes cleanly), but I was not able > > to reliably trigger the WARN through packetdrill within the test > > timeframe. > > > > The difficulty is that the id 0 ADD_ADDR is only sent when the > > endpoint is re-added after the connection is established AND after > > mptcp_nl_remove_id_zero_address() has run to restore the > > id_avail_bitmap bit via __mark_subflow_endp_available(). Getting > > packetdrill to control this timing precisely — while also keeping > > conn_list non-empty so mptcp_nl_remove_id_zero_address() actually > > processes the msk — proved tricky. > > I understand it might be tricky, but do you mind sharing what you have > so far. Maybe someone else can help you to reproduce the issue. Also, it > might be enough to have a test that can reproduce the WARN not 100% of > the time, as long as it is not 0. I will wait for this test before > applying the v3. > > At least having something exercising new paths: here, having the new > call to mptcp_remove_anno_list_by_saddr() returning true. > > > syzbot is reproducing the bug reliably on current upstream (3 crashes > > between 2026/05/19 and 2026/05/22 on kernels including cca95436be15). > > The syzbot reproducer is the most reliable pre-fix evidence available. > > Because syzbot didn't manage to generate a reproducer, we cannot really > rely on syzbot to say that the bug is fixed. 3 crashes out of how many > thousands/millions attempts? :) > > > I will continue working on the packetdrill test and send it as a > > follow-up once I have a clean before/after result. For v3 I have > > addressed your comment shortening request. > > Thanks! > > Do not forget to wait ~1 day between submissions, otherwise it is even > harder for reviewers and various tools to follow the modifications and > discussions. > > Cheers, > Matt > -- > Sponsored by the NGI0 Core fund. > > // SPDX-License-Identifier: GPL-2.0 // // ============================ STATUS: WIP ============================ // Work-in-progress reproducer for issue #620. It does NOT reproduce the // WARN yet; sharing it per the suggestion to post what I have so far so // others can help close the gap. Please do not treat it as a passing test. // // What it is meant to do: drive the in-kernel PM into reselecting address // ID 0 while a previously announced ADD_ADDR(id 0) is still pending (echo // withheld), which on an unfixed kernel leaves a stale anno_list entry and // trips WARN_ON_ONCE() in mptcp_pm_announced_alloc(). // // Where I am stuck: I have not been able to confirm that ADD_ADDR(id 0) is // actually announced in this setup. The signal endpoint on the MPC address // has its id bit cleared by mptcp_mpc_endpoint_setup(), so it is not // announced on connect; "delete id 0" frees the bit again, but I am not sure // the PM worker re-runs to announce id 0 on an otherwise idle connection. // Without that announcement no pending entry is created and the WARN cannot // trigger. The "> ..." kernel-reply lines below are therefore my best guess // and are NOT calibrated against captured output (in particular the DSS // data-ack values are placeholders). // // Open question: what is the minimal way to get the id-0 address announced // via packetdrill -- is the MP_JOIN subflow and/or an interleaved data // segment required to wake the PM worker between the operations? // // Reminder for anyone trying it: the trigger must be "endpoint delete id 0", // NOT "flush". Only the delete-id-0 op reaches mptcp_nl_remove_id_zero_address(); // flush goes through mptcp_pm_flush_addrs_and_subflows(), which already calls // mptcp_pm_announced_remove() and so was never buggy. // ===================================================================== // // Roles: packetdrill is the peer (caddr*); the kernel under test is local // (saddr0 == $OPT_LOCAL_IP) and runs the in-kernel PM as the server. --tolerance_usecs=750000 `../common/defaults.sh` +0 `../common/multi-ep.sh -e 0` +0 `sysctl -q net.mptcp.add_addr_timeout=0` +0.0 socket(..., SOCK_STREAM, IPPROTO_MPTCP) = 3 +0.0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 +0.0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) +0.0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 +0 bind(3, ..., ...) = 0 +0 listen(3, 1) = 0 // ---- MPC connection on saddr0 ---- +0.1 < addr[caddr0] > addr[saddr0] S 0:0(0) win 65535 <mss 1460, sackOK, TS val 4074410674 ecr 0, nop, wscale 8, mpcapable v1 flags[flag_h] nokey> +0 > S. 0:0(0) ack 1 <mss 1460, sackOK, TS val 4074410674 ecr 4074410674, nop, wscale 8, mpcapable v1 flags[flag_h] key[skey]> +0.2 < . 1:1(0) ack 1 win 256 <nop, nop, TS val 4074410674 ecr 4074410674, mpcapable v1 flags[flag_h] key[ckey=2, skey]> +0 accept(3, ..., ...) = 4 +0.0 < addr[caddr0] > addr[saddr0] P. 1:3(2) ack 1 win 256 <nop, nop, TS val 4074418292 ecr 4074410674, mpcapable v1 flags[flag_h] key[skey, ckey] mpcdatalen 2, nop, nop> +0.0 > . 1:1(0) ack 3 <nop, nop, TS val 4074418293 ecr 4074418292, dss dack8=3 dll=0 nocs> // ---- Extra subflow via MP_JOIN (likely needed to wake the PM worker) ---- +0.1 < addr[caddr1] > addr[saddr0] S 0:0(0) win 65535 <mss 1460, sackOK, TS val 448955294 ecr 0, nop, wscale 8, mp_join_syn address_id=1 token=sha256_32(skey)> +0 > S. 0:0(0) ack 1 <mss 1460, sackOK, TS val 448955294 ecr 448955294, nop, wscale 8, mp_join_syn_ack address_id=0 sender_hmac=auto> +0.1 < . 1:1(0) ack 1 win 256 <nop, nop, TS val 448955294 ecr 448955294, mp_join_ack sender_hmac=auto> +0 > . 1:1(0) ack 1 <nop, nop, TS val 448955294 ecr 448955294, dss dack8=3 nocs> // ---- Signal endpoint on the local (MPC / ID 0) address ---- // mpc_endpoint_id is set and its id bit cleared, so NO ADD_ADDR is sent yet. +0.1 `ip mptcp endpoint add $OPT_LOCAL_IP id 1 signal` // ---- First "delete id 0": intended to free id 0 so the PM announces it ---- +0.3 `ip mptcp endpoint delete id 0 $OPT_LOCAL_IP` // UNCALIBRATED expected RM_ADDR(id 0) ride-along (DSS dack value is a guess): +0 > . 1:1(0) ack 1 <nop, nop, TS val 448955294 ecr 448955294, dss dack8=3 nocs, remove_address address_id=[0]> // UNCALIBRATED: ADD_ADDR(id 0) -- this is the step I could not confirm fires: +0.1 > . 1:1(0) ack 1 <nop, nop, TS val 448955294 ecr 448955294, add_address address_id=0 addr[saddr0] hmac=auto> // Withhold the echo so the ADD_ADDR(id 0) entry would stay pending. // ---- Second "delete id 0": THIS is the path the patch fixes ---- // * unfixed: leaves the stale entry -> later re-announce hits the WARN; // * fixed: mptcp_pm_announced_remove() returns true, entry freed, // add_addr_signaled decremented. +0.2 `ip mptcp endpoint delete id 0 $OPT_LOCAL_IP` // UNCALIBRATED expected RM_ADDR(id 0): +0 > . 1:1(0) ack 1 <nop, nop, TS val 448955294 ecr 448955294, dss dack8=3 nocs, remove_address address_id=[0]> // A 2nd signal endpoint lifts the signal cap so the PM can reselect id 0; // on an unfixed kernel the reselect should hit the stale entry -> WARN. +0.2 `ip mptcp endpoint add 192.168.0.2 id 2 signal`
© 2016 - 2026 Red Hat, Inc.