* [PATCH mptcp-next v3 1/6] Squash to "bpf: Add mptcp_subflow bpf_iter"
2026-06-22 9:38 [PATCH mptcp-next v3 0/6] bpf sched updates Geliang Tang
@ 2026-06-22 9:38 ` Geliang Tang
2026-06-22 9:38 ` [PATCH mptcp-next v3 2/6] Squash to "bpf: Export mptcp packet scheduler helpers" Geliang Tang
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Geliang Tang @ 2026-06-22 9:38 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
Zero iterator state on error paths and add sk_type == SOCK_STREAM check to
prevent raw sockets from bypassing validation.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
net/mptcp/bpf.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c
index 08bb037f0951..cb2dddb7c3a6 100644
--- a/net/mptcp/bpf.c
+++ b/net/mptcp/bpf.c
@@ -252,11 +252,18 @@ bpf_iter_mptcp_subflow_new(struct bpf_iter_mptcp_subflow *it,
BUILD_BUG_ON(__alignof__(struct bpf_iter_mptcp_subflow_kern) !=
__alignof__(struct bpf_iter_mptcp_subflow));
- if (unlikely(!sk || !sk_fullsock(sk)))
+ if (unlikely(!sk || !sk_fullsock(sk))) {
+ kit->msk = NULL;
+ kit->pos = NULL;
return -EINVAL;
+ }
- if (sk->sk_protocol != IPPROTO_MPTCP)
+ if (sk->sk_type != SOCK_STREAM ||
+ sk->sk_protocol != IPPROTO_MPTCP) {
+ kit->msk = NULL;
+ kit->pos = NULL;
return -EINVAL;
+ }
msk = mptcp_sk(sk);
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH mptcp-next v3 2/6] Squash to "bpf: Export mptcp packet scheduler helpers"
2026-06-22 9:38 [PATCH mptcp-next v3 0/6] bpf sched updates Geliang Tang
2026-06-22 9:38 ` [PATCH mptcp-next v3 1/6] Squash to "bpf: Add mptcp_subflow bpf_iter" Geliang Tang
@ 2026-06-22 9:38 ` Geliang Tang
2026-06-22 9:39 ` [PATCH mptcp-next v3 3/6] Squash to "selftests/bpf: Add bpf_burst scheduler & test" Geliang Tang
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Geliang Tang @ 2026-06-22 9:38 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
Change bpf_sk_stream_memory_free() to accept struct mptcp_subflow_context *
instead of struct sock *, and fix return type from NULL to false. Add
sk_type == SOCK_STREAM check for safety.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
net/mptcp/bpf.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c
index cb2dddb7c3a6..85ec7b0e00d2 100644
--- a/net/mptcp/bpf.c
+++ b/net/mptcp/bpf.c
@@ -296,15 +296,16 @@ __bpf_kfunc static bool bpf_mptcp_subflow_queues_empty(struct sock *sk)
return tcp_rtx_queue_empty(sk);
}
-__bpf_kfunc static bool bpf_sk_stream_memory_free(const struct sock *sk__ign)
+__bpf_kfunc static bool
+bpf_sk_stream_memory_free(const struct mptcp_subflow_context *subflow)
{
- const struct sock *sk = sk__ign;
+ const struct sock *sk = mptcp_subflow_tcp_sock(subflow);
- if (sk && sk_fullsock(sk) &&
+ if (sk && sk_fullsock(sk) && sk->sk_type == SOCK_STREAM &&
sk->sk_protocol == IPPROTO_TCP && sk_is_mptcp(sk))
return sk_stream_memory_free(sk);
- return NULL;
+ return false;
}
__bpf_kfunc_end_defs();
@@ -327,7 +328,7 @@ BTF_ID_FLAGS(func, mptcp_subflow_set_scheduled)
BTF_ID_FLAGS(func, mptcp_subflow_active)
BTF_ID_FLAGS(func, mptcp_set_timeout)
BTF_ID_FLAGS(func, mptcp_wnd_end)
-BTF_ID_FLAGS(func, bpf_sk_stream_memory_free, KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_sk_stream_memory_free)
BTF_ID_FLAGS(func, bpf_mptcp_subflow_queues_empty)
BTF_ID_FLAGS(func, mptcp_pm_subflow_chk_stale, KF_SLEEPABLE)
BTF_KFUNCS_END(bpf_mptcp_common_kfunc_ids)
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH mptcp-next v3 3/6] Squash to "selftests/bpf: Add bpf_burst scheduler & test"
2026-06-22 9:38 [PATCH mptcp-next v3 0/6] bpf sched updates Geliang Tang
2026-06-22 9:38 ` [PATCH mptcp-next v3 1/6] Squash to "bpf: Add mptcp_subflow bpf_iter" Geliang Tang
2026-06-22 9:38 ` [PATCH mptcp-next v3 2/6] Squash to "bpf: Export mptcp packet scheduler helpers" Geliang Tang
@ 2026-06-22 9:39 ` Geliang Tang
2026-06-22 9:39 ` [PATCH mptcp-next v3 4/6] Squash to "bpf: Export mptcp packet scheduler helpers" 2 Geliang Tang
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Geliang Tang @ 2026-06-22 9:39 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
Adapt burst scheduler to use the new bpf_sk_stream_memory_free() signature
(storing subflow pointers instead of sock pointers in send_info array).
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
.../selftests/bpf/progs/mptcp_bpf_burst.c | 25 ++++++++++---------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf_burst.c b/tools/testing/selftests/bpf/progs/mptcp_bpf_burst.c
index 693fab55f7be..48c22f5bce32 100644
--- a/tools/testing/selftests/bpf/progs/mptcp_bpf_burst.c
+++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_burst.c
@@ -9,6 +9,11 @@ char _license[] SEC("license") = "GPL";
#define MPTCP_SEND_BURST_SIZE 65428
+struct bpf_subflow_send_info {
+ struct mptcp_subflow_context *subflow;
+ u64 linger_time;
+};
+
#define SSK_MODE_ACTIVE 0
#define SSK_MODE_BACKUP 1
#define SSK_MODE_MAX 2
@@ -18,7 +23,7 @@ char _license[] SEC("license") = "GPL";
extern bool mptcp_subflow_active(struct mptcp_subflow_context *subflow) __ksym;
extern void mptcp_set_timeout(struct sock *sk) __ksym;
extern __u64 mptcp_wnd_end(const struct mptcp_sock *msk) __ksym;
-extern bool bpf_sk_stream_memory_free(const struct sock *sk) __ksym;
+extern bool bpf_sk_stream_memory_free(const struct mptcp_subflow_context *subflow) __ksym;
extern bool bpf_mptcp_subflow_queues_empty(struct sock *sk) __ksym;
extern void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk) __ksym;
@@ -52,7 +57,7 @@ void BPF_PROG(mptcp_sched_burst_release, struct mptcp_sock *msk)
SEC("struct_ops")
int BPF_PROG(bpf_burst_get_send, struct mptcp_sock *msk)
{
- struct subflow_send_info send_info[SSK_MODE_MAX];
+ struct bpf_subflow_send_info send_info[SSK_MODE_MAX];
struct mptcp_subflow_context *subflow;
struct sock *sk = (struct sock *)msk;
__u32 pace, burst, wmem;
@@ -62,7 +67,7 @@ int BPF_PROG(bpf_burst_get_send, struct mptcp_sock *msk)
/* pick the subflow with the lower wmem/wspace ratio */
for (i = 0; i < SSK_MODE_MAX; ++i) {
- send_info[i].ssk = NULL;
+ send_info[i].subflow = NULL;
send_info[i].linger_time = -1;
}
@@ -85,7 +90,7 @@ int BPF_PROG(bpf_burst_get_send, struct mptcp_sock *msk)
linger_time = div_u64((__u64)ssk->sk_wmem_queued << 32, pace);
if (linger_time < send_info[backup].linger_time) {
- send_info[backup].ssk = ssk;
+ send_info[backup].subflow = subflow;
send_info[backup].linger_time = linger_time;
}
}
@@ -93,18 +98,14 @@ int BPF_PROG(bpf_burst_get_send, struct mptcp_sock *msk)
/* pick the best backup if no other subflow is active */
if (!nr_active)
- send_info[SSK_MODE_ACTIVE].ssk = send_info[SSK_MODE_BACKUP].ssk;
+ send_info[SSK_MODE_ACTIVE].subflow = send_info[SSK_MODE_BACKUP].subflow;
- ssk = send_info[SSK_MODE_ACTIVE].ssk;
- if (!ssk || !bpf_sk_stream_memory_free(ssk))
- return -1;
-
- subflow = bpf_mptcp_subflow_ctx(ssk);
- if (!subflow)
+ subflow = send_info[SSK_MODE_ACTIVE].subflow;
+ if (!subflow || !bpf_sk_stream_memory_free(subflow))
return -1;
burst = min(MPTCP_SEND_BURST_SIZE, mptcp_wnd_end(msk) - msk->snd_nxt);
- ssk = bpf_core_cast(ssk, struct sock);
+ ssk = mptcp_subflow_tcp_sock(subflow);
wmem = ssk->sk_wmem_queued;
if (!burst)
goto out;
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH mptcp-next v3 4/6] Squash to "bpf: Export mptcp packet scheduler helpers" 2
2026-06-22 9:38 [PATCH mptcp-next v3 0/6] bpf sched updates Geliang Tang
` (2 preceding siblings ...)
2026-06-22 9:39 ` [PATCH mptcp-next v3 3/6] Squash to "selftests/bpf: Add bpf_burst scheduler & test" Geliang Tang
@ 2026-06-22 9:39 ` Geliang Tang
2026-06-22 9:39 ` [PATCH mptcp-next v3 5/6] Squash to "selftests/bpf: Add bpf_first scheduler & test" Geliang Tang
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Geliang Tang @ 2026-06-22 9:39 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
Remove __ign suffix from bpf_mptcp_subflow_ctx() and add sk_type ==
SOCK_STREAM check to prevent raw socket misuse.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
net/mptcp/bpf.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c
index 85ec7b0e00d2..577b815775a2 100644
--- a/net/mptcp/bpf.c
+++ b/net/mptcp/bpf.c
@@ -220,11 +220,9 @@ struct bpf_iter_mptcp_subflow_kern {
__bpf_kfunc_start_defs();
__bpf_kfunc static struct mptcp_subflow_context *
-bpf_mptcp_subflow_ctx(const struct sock *sk__ign)
+bpf_mptcp_subflow_ctx(const struct sock *sk)
{
- const struct sock *sk = sk__ign;
-
- if (sk && sk_fullsock(sk) &&
+ if (sk && sk_fullsock(sk) && sk->sk_type == SOCK_STREAM &&
sk->sk_protocol == IPPROTO_TCP && sk_is_mptcp(sk))
return mptcp_subflow_ctx(sk);
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH mptcp-next v3 5/6] Squash to "selftests/bpf: Add bpf_first scheduler & test"
2026-06-22 9:38 [PATCH mptcp-next v3 0/6] bpf sched updates Geliang Tang
` (3 preceding siblings ...)
2026-06-22 9:39 ` [PATCH mptcp-next v3 4/6] Squash to "bpf: Export mptcp packet scheduler helpers" 2 Geliang Tang
@ 2026-06-22 9:39 ` Geliang Tang
2026-06-22 9:39 ` [PATCH mptcp-next v3 6/6] Squash to "selftests/bpf: Add bpf_rr " Geliang Tang
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Geliang Tang @ 2026-06-22 9:39 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
Replace bpf_mptcp_subflow_ctx(msk->first) with a bpf_for_each iteration
over subflows to find the one whose tcp_sock matches msk->first. This
avoids passing an untrusted pointer (msk->first) to a kfunc that
requires trusted/referenced arguments, resolving the verifier error
"R1 must be referenced or trusted".
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
.../selftests/bpf/progs/mptcp_bpf_first.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf_first.c b/tools/testing/selftests/bpf/progs/mptcp_bpf_first.c
index 96b002808ce7..13ecee9833cf 100644
--- a/tools/testing/selftests/bpf/progs/mptcp_bpf_first.c
+++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_first.c
@@ -20,13 +20,16 @@ SEC("struct_ops")
int BPF_PROG(bpf_first_get_send, struct mptcp_sock *msk)
{
struct mptcp_subflow_context *subflow;
-
- subflow = bpf_mptcp_subflow_ctx(msk->first);
- if (!subflow)
- return -1;
-
- mptcp_subflow_set_scheduled(subflow, true);
- return 0;
+ struct sock *ssk;
+
+ bpf_for_each(mptcp_subflow, subflow, (struct sock *)msk) {
+ ssk = bpf_mptcp_subflow_tcp_sock(subflow);
+ if (ssk == msk->first) {
+ mptcp_subflow_set_scheduled(subflow, true);
+ return 0;
+ }
+ }
+ return -1;
}
SEC(".struct_ops.link")
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH mptcp-next v3 6/6] Squash to "selftests/bpf: Add bpf_rr scheduler & test"
2026-06-22 9:38 [PATCH mptcp-next v3 0/6] bpf sched updates Geliang Tang
` (4 preceding siblings ...)
2026-06-22 9:39 ` [PATCH mptcp-next v3 5/6] Squash to "selftests/bpf: Add bpf_first scheduler & test" Geliang Tang
@ 2026-06-22 9:39 ` Geliang Tang
2026-06-22 10:28 ` [PATCH mptcp-next v3 0/6] bpf sched updates MPTCP CI
2026-06-22 16:47 ` Matthieu Baerts
7 siblings, 0 replies; 9+ messages in thread
From: Geliang Tang @ 2026-06-22 9:39 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
Rewrite bpf_rr_get_send to use a single traversal over subflows instead
of calling bpf_mptcp_subflow_ctx() and bpf_iter_mptcp_subflow_next().
The new implementation:
- Records the first subflow as a fallback
- Uses a flag to find the subflow after ptr->last_snd
- Falls back to first when last_snd is NULL or not found
This eliminates unsafe pointer handling and avoids verifier trust issues.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
.../selftests/bpf/progs/mptcp_bpf_rr.c | 30 +++++++++++--------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf_rr.c b/tools/testing/selftests/bpf/progs/mptcp_bpf_rr.c
index 3c685c77f67f..10cef8abf206 100644
--- a/tools/testing/selftests/bpf/progs/mptcp_bpf_rr.c
+++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_rr.c
@@ -33,33 +33,37 @@ void BPF_PROG(mptcp_sched_rr_release, struct mptcp_sock *msk)
SEC("struct_ops")
int BPF_PROG(bpf_rr_get_send, struct mptcp_sock *msk)
{
- struct mptcp_subflow_context *subflow, *next;
+ struct mptcp_subflow_context *subflow, *first = NULL, *next = NULL;
struct mptcp_rr_storage *ptr;
+ bool found = false;
ptr = bpf_sk_storage_get(&mptcp_rr_map, msk, 0,
BPF_LOCAL_STORAGE_GET_F_CREATE);
if (!ptr)
return -1;
- next = bpf_mptcp_subflow_ctx(msk->first);
- if (!next)
- return -1;
-
- if (!ptr->last_snd)
- goto out;
-
bpf_for_each(mptcp_subflow, subflow, (struct sock *)msk) {
- if (mptcp_subflow_tcp_sock(subflow) == ptr->last_snd) {
- subflow = bpf_iter_mptcp_subflow_next(&___it);
- if (!subflow)
- break;
+ if (!first)
+ first = subflow;
+
+ if (!ptr->last_snd)
+ break;
+ if (found) {
next = subflow;
break;
}
+
+ if (mptcp_subflow_tcp_sock(subflow) == ptr->last_snd)
+ found = true;
}
-out:
+ if (!first)
+ return -1;
+
+ if (!next)
+ next = first;
+
mptcp_subflow_set_scheduled(next, true);
ptr->last_snd = mptcp_subflow_tcp_sock(next);
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH mptcp-next v3 0/6] bpf sched updates
2026-06-22 9:38 [PATCH mptcp-next v3 0/6] bpf sched updates Geliang Tang
` (5 preceding siblings ...)
2026-06-22 9:39 ` [PATCH mptcp-next v3 6/6] Squash to "selftests/bpf: Add bpf_rr " Geliang Tang
@ 2026-06-22 10:28 ` MPTCP CI
2026-06-22 16:47 ` Matthieu Baerts
7 siblings, 0 replies; 9+ messages in thread
From: MPTCP CI @ 2026-06-22 10:28 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
Hi Geliang,
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): Notice: Call Traces at boot time, rebooted and continued ⚠️
- KVM Validation: debug (only selftest_mptcp_join): Notice: Call Traces at boot time, rebooted and continued ⚠️
- KVM Validation: btf-normal (only bpftest_all): Success! ✅
- KVM Validation: btf-debug (only bpftest_all): Notice: Call Traces at boot time, rebooted and continued ⚠️
- Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/27944247890
Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/526ff6453267
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1114644
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)
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH mptcp-next v3 0/6] bpf sched updates
2026-06-22 9:38 [PATCH mptcp-next v3 0/6] bpf sched updates Geliang Tang
` (6 preceding siblings ...)
2026-06-22 10:28 ` [PATCH mptcp-next v3 0/6] bpf sched updates MPTCP CI
@ 2026-06-22 16:47 ` Matthieu Baerts
7 siblings, 0 replies; 9+ messages in thread
From: Matthieu Baerts @ 2026-06-22 16:47 UTC (permalink / raw)
To: Geliang Tang, mptcp; +Cc: Geliang Tang
Hi Geliang,
On 22/06/2026 11:38, Geliang Tang wrote:
> From: Geliang Tang <tanggeliang@kylinos.cn>
>
> v3:
> - Add sk_type == SOCK_STREAM check in bpf_iter_mptcp_subflow_new() to
> prevent raw sockets from bypassing validation (new patch 1).
> - Zero iterator state (kit->msk, kit->pos) on error paths in
> bpf_iter_mptcp_subflow_new() to avoid uninitialized dereference.
> - Change bpf_sk_stream_memory_free() signature to accept
> struct mptcp_subflow_context * instead of struct sock *, to make it
> work with burst scheduler.
(slowly trying to get back to the reviews, sorry for the delay on older
series, it might take a while...)
Thanks! Sashiko may have found existing issues with other helpers
introduced in our export branch, please see:
https://sashiko.dev/#/patchset/cover.1782120674.git.tanggeliang%40kylinos.cn?part=4
New patches for t/upstream:
- beb6482d3d18: "squashed" patch 1/6 in "bpf: Add mptcp_subflow bpf_iter"
- 21533dcb5a8a: "squashed" patch 2/6 in "bpf: Export mptcp packet
scheduler helpers"
- 0f4ed15e3a62: "squashed" patch 4/6 in "bpf: Export mptcp packet
scheduler helpers"
- 0d8c9711887c: "squashed" patch 5/6 in "selftests/bpf: Add bpf_first
scheduler & test"
- 4824dc0f98f1: "squashed" patch 6/6 in "selftests/bpf: Add bpf_rr
scheduler & test"
- b077032985ac: "squashed" patch 3/6 in "selftests/bpf: Add bpf_burst
scheduler & test"
- Results: bc8075b182f4..7fc976a6891c (export)
Tests are now in progress:
- export:
https://github.com/multipath-tcp/mptcp_net-next/commit/366d3bd40f3e2dbc4d7ffe0816c0c657d6d7c54c/checks
Cheers,
Matt
--
Sponsored by the NGI0 Core fund.
^ permalink raw reply [flat|nested] 9+ messages in thread