* [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter
@ 2025-02-07 10:35 Geliang Tang
2025-02-07 10:35 ` [PATCH mptcp-next v5 1/5] selftests/bpf: Add mptcp pm_nl_ctl link Geliang Tang
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Geliang Tang @ 2025-02-07 10:35 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
v5:
- use "struct sock *sk" instead of "struct mptcp-sock *msk" as the
argument of bpf_iter_mptcp_userspace_pm_addr_new() in patch 3.
- update patch 5.
v4:
- patch 3, use spin_is_locked() instead of lockdep_assert_held().
- patch 5, use ipv4_is_private_10() for the selftests instead of using
ipv6_addr_v4mapped().
v3:
- rename mptcp_address to mptcp_userspace_pm_addr as I mentioned in [1].
- rebased.
[1]
https://patchwork.kernel.org/project/mptcp/patch/b6b53fd730a0edd0024963468d078488ad5e67aa.1729588019.git.tanggeliang@kylinos.cn/
v2:
- squash patches 5,6 of v1 into one.
- patch 3, use lockdep_assert_held instead of spin_is_locked.
- update patch 5 to make it run normally in btf-debug mode.
Another bpf_iter for BPF path manager to traverse all address entries
on userspace_pm_local_addr_list of an MPTCP socket is added in this set.
Userspace pm tool is needed by the self test, so add pm_nl_ctl link in
patch 1.
Geliang Tang (5):
selftests/bpf: Add mptcp pm_nl_ctl link
selftests/bpf: Use pm_nl_ctl if ip mptcp not supported
bpf: Add mptcp_userspace_pm_addr bpf_iter
bpf: Export more helpers for mptcp_userspace_pm_addr test
selftests/bpf: Add mptcp_userspace_pm_addr bpf_iter subtest
MAINTAINERS | 1 +
net/mptcp/bpf.c | 72 ++++++
tools/testing/selftests/bpf/Makefile | 4 +-
.../testing/selftests/bpf/bpf_experimental.h | 8 +
tools/testing/selftests/bpf/mptcp_pm_nl_ctl.c | 1 +
.../testing/selftests/bpf/prog_tests/mptcp.c | 235 +++++++++++++++++-
tools/testing/selftests/bpf/progs/mptcp_bpf.h | 5 +
.../selftests/bpf/progs/mptcp_bpf_iters.c | 34 +++
8 files changed, 351 insertions(+), 9 deletions(-)
create mode 120000 tools/testing/selftests/bpf/mptcp_pm_nl_ctl.c
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH mptcp-next v5 1/5] selftests/bpf: Add mptcp pm_nl_ctl link
2025-02-07 10:35 [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter Geliang Tang
@ 2025-02-07 10:35 ` Geliang Tang
2025-02-07 10:35 ` [PATCH mptcp-next v5 2/5] selftests/bpf: Use pm_nl_ctl if ip mptcp not supported Geliang Tang
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Geliang Tang @ 2025-02-07 10:35 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Matthieu Baerts
From: Geliang Tang <tanggeliang@kylinos.cn>
This patch adds a symlink to MPTCP's pm_nl_ctl tool into bpf selftests,
and updates Makefile to compile it.
This is useful to run MPTCP BPF selftests on systems with an old version
of IPRoute2. This tool can be used as an alternative to 'ip mptcp'.
In addition, this tool is used as userspace path manager. "csf" and "dsf"
commands of pm_nl_ctl for creating and destroying subflows, and "ann" and
"rem" commands for signaling ADD_ADDR and RM_ADDR. These commands are not
currently supported in 'ip mptcp' yet.
MAINTAINERS needs to be updated since a new file is added in a non
covered place.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
MAINTAINERS | 1 +
tools/testing/selftests/bpf/Makefile | 4 +++-
tools/testing/selftests/bpf/mptcp_pm_nl_ctl.c | 1 +
3 files changed, 5 insertions(+), 1 deletion(-)
create mode 120000 tools/testing/selftests/bpf/mptcp_pm_nl_ctl.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 873aa2cce4d7..8543bb0e6bc8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16632,6 +16632,7 @@ F: include/trace/events/mptcp.h
F: include/uapi/linux/mptcp*.h
F: net/mptcp/
F: tools/testing/selftests/bpf/*/*mptcp*.[ch]
+F: tools/testing/selftests/bpf/*mptcp*.[ch]
F: tools/testing/selftests/net/mptcp/
NETWORKING [TCP]
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 87551628e112..98a521db072a 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -138,7 +138,8 @@ TEST_GEN_PROGS_EXTENDED = \
xdp_redirect_multi \
xdp_synproxy \
xdping \
- xskxceiver
+ xskxceiver \
+ mptcp_pm_nl_ctl
TEST_GEN_FILES += liburandom_read.so urandom_read sign-file uprobe_multi
@@ -719,6 +720,7 @@ TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read \
$(OUTPUT)/xdp_synproxy \
$(OUTPUT)/sign-file \
$(OUTPUT)/uprobe_multi \
+ $(OUTPUT)/mptcp_pm_nl_ctl \
$(TEST_KMOD_TARGETS) \
ima_setup.sh \
verify_sig_setup.sh \
diff --git a/tools/testing/selftests/bpf/mptcp_pm_nl_ctl.c b/tools/testing/selftests/bpf/mptcp_pm_nl_ctl.c
new file mode 120000
index 000000000000..5a08c255b278
--- /dev/null
+++ b/tools/testing/selftests/bpf/mptcp_pm_nl_ctl.c
@@ -0,0 +1 @@
+../net/mptcp/pm_nl_ctl.c
\ No newline at end of file
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH mptcp-next v5 2/5] selftests/bpf: Use pm_nl_ctl if ip mptcp not supported
2025-02-07 10:35 [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter Geliang Tang
2025-02-07 10:35 ` [PATCH mptcp-next v5 1/5] selftests/bpf: Add mptcp pm_nl_ctl link Geliang Tang
@ 2025-02-07 10:35 ` Geliang Tang
2025-02-07 10:36 ` [PATCH mptcp-next v5 3/5] bpf: Add mptcp_userspace_pm_addr bpf_iter Geliang Tang
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Geliang Tang @ 2025-02-07 10:35 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
If running MPTCP BPF selftests on systems with an old version of IPRoute2,
'ip mptcp' command is not supported. In this case, instead of skipping the
test, falling back to using 'pm_nl_ctl' tool is a better option. This patch
adds an 'ip_mptcp' argument for endpoint_add() to control whether to use
'ip mptcp' or 'pm_nl_ctl' to add an endpoint.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
.../testing/selftests/bpf/prog_tests/mptcp.c | 21 ++++++++++++-------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing/selftests/bpf/prog_tests/mptcp.c
index ac6f6a6f7700..0a0dee34095d 100644
--- a/tools/testing/selftests/bpf/prog_tests/mptcp.c
+++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c
@@ -28,6 +28,7 @@
#define ADDR6_3 "dead:beef:3::1"
#define ADDR6_4 "dead:beef:4::1"
#define PORT_1 10001
+#define PM_CTL "./mptcp_pm_nl_ctl"
#define WITH_DATA true
#define WITHOUT_DATA false
@@ -366,13 +367,18 @@ static int address_init(void)
return -1;
}
-static int endpoint_add(char *addr, char *flags)
+static int endpoint_add(char *addr, char *flags, bool ip_mptcp)
{
- return SYS_NOFAIL("ip -net %s mptcp endpoint add %s %s", NS_TEST, addr, flags);
+ if (ip_mptcp)
+ return SYS_NOFAIL("ip -net %s mptcp endpoint add %s %s",
+ NS_TEST, addr, flags);
+ return SYS_NOFAIL("ip netns exec %s %s add %s flags %s",
+ NS_TEST, PM_CTL, addr, flags);
}
static int endpoint_init(char *flags, u8 endpoints)
{
+ bool ip_mptcp = true;
int ret = -1;
if (!endpoints || endpoints > 4)
@@ -383,17 +389,16 @@ static int endpoint_init(char *flags, u8 endpoints)
if (SYS_NOFAIL("ip -net %s mptcp limits set add_addr_accepted 4 subflows 4",
NS_TEST)) {
- printf("'ip mptcp' not supported, skip this test.\n");
- test__skip();
- goto fail;
+ SYS(fail, "ip netns exec %s %s limits 4 4", NS_TEST, PM_CTL);
+ ip_mptcp = false;
}
if (endpoints > 1)
- ret = endpoint_add(ADDR_2, flags);
+ ret = endpoint_add(ADDR_2, flags, ip_mptcp);
if (endpoints > 2)
- ret = ret ?: endpoint_add(ADDR_3, flags);
+ ret = ret ?: endpoint_add(ADDR_3, flags, ip_mptcp);
if (endpoints > 3)
- ret = ret ?: endpoint_add(ADDR_4, flags);
+ ret = ret ?: endpoint_add(ADDR_4, flags, ip_mptcp);
fail:
return ret;
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH mptcp-next v5 3/5] bpf: Add mptcp_userspace_pm_addr bpf_iter
2025-02-07 10:35 [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter Geliang Tang
2025-02-07 10:35 ` [PATCH mptcp-next v5 1/5] selftests/bpf: Add mptcp pm_nl_ctl link Geliang Tang
2025-02-07 10:35 ` [PATCH mptcp-next v5 2/5] selftests/bpf: Use pm_nl_ctl if ip mptcp not supported Geliang Tang
@ 2025-02-07 10:36 ` Geliang Tang
2025-02-07 10:36 ` [PATCH mptcp-next v5 4/5] bpf: Export more helpers for mptcp_userspace_pm_addr test Geliang Tang
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Geliang Tang @ 2025-02-07 10:36 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
Just like the mptcp_subflow bpf_iter used to implement the MPTCP
BPF packet scheduler, another bpf_iter is also needed, named
mptcp_userspace_pm_addr, to traverse all address entries on
userspace_pm_local_addr_list of an MPTCP socket for implementing
the MPTCP BPF path manager.
In kernel space, we walk this list like this:
mptcp_for_each_userspace_pm_addr(msk, entry)
kfunc(entry);
With the mptcp_userspace_pm_addr bpf_iter, bpf_for_each() can be
used to do the same thing in BPF program:
bpf_for_each(mptcp_userspace_pm_addr, entry, sk)
kfunc(entry);
This bpf_iter should be invoked under holding the msk pm lock, so
use spin_is_locked() to check whether the lock is holding.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
net/mptcp/bpf.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c
index be222fa5f308..21f736f2ff30 100644
--- a/net/mptcp/bpf.c
+++ b/net/mptcp/bpf.c
@@ -227,6 +227,15 @@ struct bpf_iter_mptcp_subflow_kern {
struct list_head *pos;
} __aligned(8);
+struct bpf_iter_mptcp_userspace_pm_addr {
+ __u64 __opaque[2];
+} __aligned(8);
+
+struct bpf_iter_mptcp_userspace_pm_addr_kern {
+ struct mptcp_sock *msk;
+ struct list_head *pos;
+} __aligned(8);
+
__bpf_kfunc_start_defs();
__bpf_kfunc static struct mptcp_subflow_context *
@@ -305,6 +314,48 @@ bpf_mptcp_subflow_ctx_by_pos(const struct mptcp_sched_data *data, unsigned int p
return data->contexts[pos];
}
+__bpf_kfunc static int
+bpf_iter_mptcp_userspace_pm_addr_new(struct bpf_iter_mptcp_userspace_pm_addr *it,
+ struct sock *sk)
+{
+ struct bpf_iter_mptcp_userspace_pm_addr_kern *kit = (void *)it;
+ struct mptcp_sock *msk;
+
+ BUILD_BUG_ON(sizeof(struct bpf_iter_mptcp_userspace_pm_addr_kern) >
+ sizeof(struct bpf_iter_mptcp_userspace_pm_addr));
+ BUILD_BUG_ON(__alignof__(struct bpf_iter_mptcp_userspace_pm_addr_kern) !=
+ __alignof__(struct bpf_iter_mptcp_userspace_pm_addr));
+
+ msk = bpf_mptcp_sock_from_sock(sk);
+ if (!msk)
+ return -EINVAL;
+
+ if (!spin_is_locked(&msk->pm.lock))
+ return -EINVAL;
+
+ kit->msk = msk;
+ kit->pos = &msk->pm.userspace_pm_local_addr_list;
+ return 0;
+}
+
+__bpf_kfunc static struct mptcp_pm_addr_entry *
+bpf_iter_mptcp_userspace_pm_addr_next(struct bpf_iter_mptcp_userspace_pm_addr *it)
+{
+ struct bpf_iter_mptcp_userspace_pm_addr_kern *kit = (void *)it;
+
+ if (!kit->msk || list_is_last(kit->pos,
+ &kit->msk->pm.userspace_pm_local_addr_list))
+ return NULL;
+
+ kit->pos = kit->pos->next;
+ return list_entry(kit->pos, struct mptcp_pm_addr_entry, list);
+}
+
+__bpf_kfunc static void
+bpf_iter_mptcp_userspace_pm_addr_destroy(struct bpf_iter_mptcp_userspace_pm_addr *it)
+{
+}
+
__bpf_kfunc static bool bpf_mptcp_subflow_queues_empty(struct sock *sk)
{
return tcp_rtx_queue_empty(sk);
@@ -317,6 +368,9 @@ BTF_ID_FLAGS(func, bpf_mptcp_subflow_ctx, KF_RET_NULL)
BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_new, KF_ITER_NEW | KF_TRUSTED_ARGS)
BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_next, KF_ITER_NEXT | KF_RET_NULL)
BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_destroy, KF_ITER_DESTROY)
+BTF_ID_FLAGS(func, bpf_iter_mptcp_userspace_pm_addr_new, KF_ITER_NEW | KF_TRUSTED_ARGS)
+BTF_ID_FLAGS(func, bpf_iter_mptcp_userspace_pm_addr_next, KF_ITER_NEXT | KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_iter_mptcp_userspace_pm_addr_destroy, KF_ITER_DESTROY)
BTF_ID_FLAGS(func, bpf_mptcp_sock_acquire, KF_ACQUIRE | KF_RET_NULL)
BTF_ID_FLAGS(func, bpf_mptcp_sock_release, KF_RELEASE)
BTF_KFUNCS_END(bpf_mptcp_common_kfunc_ids)
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH mptcp-next v5 4/5] bpf: Export more helpers for mptcp_userspace_pm_addr test
2025-02-07 10:35 [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter Geliang Tang
` (2 preceding siblings ...)
2025-02-07 10:36 ` [PATCH mptcp-next v5 3/5] bpf: Add mptcp_userspace_pm_addr bpf_iter Geliang Tang
@ 2025-02-07 10:36 ` Geliang Tang
2025-02-07 10:36 ` [PATCH mptcp-next v5 5/5] selftests/bpf: Add mptcp_userspace_pm_addr bpf_iter subtest Geliang Tang
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Geliang Tang @ 2025-02-07 10:36 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
The mptcp_userspace_pm_addr bpf_iter should be invoked under holding the
msk pm lock, so spin_lock_bh() and spin_unlock_bh() are needed in BPF
program to hold or release the msk pm lock. And bpf_ipv4_is_private_10()
helper is also needed by the mptcp_userspace_pm_addr bpf_iter selftest
program.
This patch adds the corresponding BPF wrappers for these helpers and adds
them to the mptcp common kfunc_set.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
net/mptcp/bpf.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c
index 21f736f2ff30..4854160c25df 100644
--- a/net/mptcp/bpf.c
+++ b/net/mptcp/bpf.c
@@ -356,6 +356,21 @@ bpf_iter_mptcp_userspace_pm_addr_destroy(struct bpf_iter_mptcp_userspace_pm_addr
{
}
+__bpf_kfunc static void bpf_spin_lock_bh(spinlock_t *lock)
+{
+ spin_lock_bh(lock);
+}
+
+__bpf_kfunc static void bpf_spin_unlock_bh(spinlock_t *lock)
+{
+ spin_unlock_bh(lock);
+}
+
+__bpf_kfunc static bool bpf_ipv4_is_private_10(__be32 addr)
+{
+ return ipv4_is_private_10(addr);
+}
+
__bpf_kfunc static bool bpf_mptcp_subflow_queues_empty(struct sock *sk)
{
return tcp_rtx_queue_empty(sk);
@@ -371,6 +386,9 @@ BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_destroy, KF_ITER_DESTROY)
BTF_ID_FLAGS(func, bpf_iter_mptcp_userspace_pm_addr_new, KF_ITER_NEW | KF_TRUSTED_ARGS)
BTF_ID_FLAGS(func, bpf_iter_mptcp_userspace_pm_addr_next, KF_ITER_NEXT | KF_RET_NULL)
BTF_ID_FLAGS(func, bpf_iter_mptcp_userspace_pm_addr_destroy, KF_ITER_DESTROY)
+BTF_ID_FLAGS(func, bpf_spin_lock_bh)
+BTF_ID_FLAGS(func, bpf_spin_unlock_bh)
+BTF_ID_FLAGS(func, bpf_ipv4_is_private_10)
BTF_ID_FLAGS(func, bpf_mptcp_sock_acquire, KF_ACQUIRE | KF_RET_NULL)
BTF_ID_FLAGS(func, bpf_mptcp_sock_release, KF_RELEASE)
BTF_KFUNCS_END(bpf_mptcp_common_kfunc_ids)
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH mptcp-next v5 5/5] selftests/bpf: Add mptcp_userspace_pm_addr bpf_iter subtest
2025-02-07 10:35 [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter Geliang Tang
` (3 preceding siblings ...)
2025-02-07 10:36 ` [PATCH mptcp-next v5 4/5] bpf: Export more helpers for mptcp_userspace_pm_addr test Geliang Tang
@ 2025-02-07 10:36 ` Geliang Tang
2025-02-07 10:57 ` [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter MPTCP CI
2025-02-07 11:44 ` MPTCP CI
6 siblings, 0 replies; 8+ messages in thread
From: Geliang Tang @ 2025-02-07 10:36 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
This patch adds a test program for the newly added mptcp_userspace_pm_addr
bpf_iter in SEC "cgroup/getsockopt". This test iterates over all address
entries on the local address list of userspace PM and check whether each
one is an IPv4mapped address.
Export mptcp_userspace_pm_addr helpers _new/_next/_destroy into
bpf_experimental.h. Use bpf_mptcp_sock_acquire() to acquire the msk, then
lock the msk pm lock and use bpf_for_each(mptcp_userspace_pm_addr) to walk
the local address list of this msk. Invoke bpf_ipv4_is_private_10() in the
loop to check whether the address is a "10.*" one. Then Add the address ID
of each entry to local veriable local_ids.
Out of the loop, unlock the msk pm lock and use bpf_mptcp_sock_release() to
release the msk. Finally, assign local_ids to global variable ids so that
the application can obtain this value.
Add a subtest named test_iters_address to load and verify the newly added
mptcp_userspace_pm_addr type bpf_iter example in test_mptcp.
Since mptcp_userspace_pm_addr bpf_iter iterates over all address entries
on the local address list of userspace PM. A set of userspace PM helpers
are added.
Set pm_type and start "pm_nl_ctl events" command to save pm events into
the log file /tmp/bpf_userspace_pm_events in userspace_pm_init(). Kill
"pm_nl_ctl" command and remove the log file in userspace_pm_cleanup().
Parse the log file in userspace_pm_add_subflow() to get the token, sport
and dport values, then use "pm_nl_ctl csf" command to create a subflow.
Use the helper userspace_pm_add_subflow() to add 3 new subflow endpoints.
Send a byte of message to start the mptcp connection, and receive the
message.
getsockopt() is invoked to trigger the "cgroup/getsockopt" test program.
Check if skel->bss->ids equals 60 to verify whether the program loops
three times as expected.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
.../testing/selftests/bpf/bpf_experimental.h | 8 +
.../testing/selftests/bpf/prog_tests/mptcp.c | 214 ++++++++++++++++++
tools/testing/selftests/bpf/progs/mptcp_bpf.h | 5 +
.../selftests/bpf/progs/mptcp_bpf_iters.c | 34 +++
4 files changed, 261 insertions(+)
diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
index 2ab3f0063c0f..52ff0d0407e7 100644
--- a/tools/testing/selftests/bpf/bpf_experimental.h
+++ b/tools/testing/selftests/bpf/bpf_experimental.h
@@ -583,6 +583,14 @@ bpf_iter_mptcp_subflow_next(struct bpf_iter_mptcp_subflow *it) __weak __ksym;
extern void
bpf_iter_mptcp_subflow_destroy(struct bpf_iter_mptcp_subflow *it) __weak __ksym;
+struct bpf_iter_mptcp_userspace_pm_addr;
+extern int bpf_iter_mptcp_userspace_pm_addr_new(struct bpf_iter_mptcp_userspace_pm_addr *it,
+ struct sock *sk) __weak __ksym;
+extern struct mptcp_pm_addr_entry *
+bpf_iter_mptcp_userspace_pm_addr_next(struct bpf_iter_mptcp_userspace_pm_addr *it) __weak __ksym;
+extern void
+bpf_iter_mptcp_userspace_pm_addr_destroy(struct bpf_iter_mptcp_userspace_pm_addr *it) __weak __ksym;
+
extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing/selftests/bpf/prog_tests/mptcp.c
index 0a0dee34095d..3fff78781bac 100644
--- a/tools/testing/selftests/bpf/prog_tests/mptcp.c
+++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c
@@ -29,6 +29,7 @@
#define ADDR6_4 "dead:beef:4::1"
#define PORT_1 10001
#define PM_CTL "./mptcp_pm_nl_ctl"
+#define PM_EVENTS "/tmp/bpf_userspace_pm_events"
#define WITH_DATA true
#define WITHOUT_DATA false
@@ -57,6 +58,14 @@
#endif
#define MPTCP_SCHED_NAME_MAX 16
+enum mptcp_pm_type {
+ MPTCP_PM_TYPE_KERNEL = 0,
+ MPTCP_PM_TYPE_USERSPACE,
+
+ __MPTCP_PM_TYPE_NR,
+ __MPTCP_PM_TYPE_MAX = __MPTCP_PM_TYPE_NR - 1,
+};
+
static const unsigned int total_bytes = 10 * 1024 * 1024;
static int duration;
@@ -252,6 +261,19 @@ static void send_byte(int fd)
ASSERT_EQ(write(fd, &b, sizeof(b)), 1, "send single byte");
}
+static int recv_byte(int fd)
+{
+ char buf[1];
+ ssize_t n;
+
+ n = recv(fd, buf, sizeof(buf), 0);
+ if (CHECK(n <= 0, "recv_byte", "recv")) {
+ log_err("failed/partial recv");
+ return -1;
+ }
+ return 0;
+}
+
static int verify_mptcpify(int server_fd, int client_fd)
{
struct __mptcp_info info;
@@ -567,6 +589,196 @@ static void test_iters_subflow(void)
close(cgroup_fd);
}
+static int userspace_pm_init(enum mptcp_pm_type pm_type)
+{
+ if (address_init())
+ goto fail;
+
+ SYS(fail, "ip netns exec %s sysctl -qw net.mptcp.pm_type=%u",
+ NS_TEST, pm_type);
+ SYS(fail, "ip netns exec %s %s limits 4 4",
+ NS_TEST, PM_CTL);
+ SYS(fail, "ip netns exec %s %s events >> %s 2>&1 &",
+ NS_TEST, PM_CTL, PM_EVENTS);
+
+ return 0;
+fail:
+ return -1;
+}
+
+static void userspace_pm_cleanup(void)
+{
+ SYS_NOFAIL("ip netns exec %s killall %s > /dev/null 2>&1",
+ NS_TEST, PM_CTL);
+ SYS_NOFAIL("ip netns exec %s rm -rf %s", NS_TEST, PM_EVENTS);
+}
+
+static int userspace_pm_get_events_line(char *type, char *line)
+{
+ char buf[BUFSIZ], *str;
+ size_t len;
+ int fd;
+
+ fd = open(PM_EVENTS, O_RDONLY);
+ if (fd < 0) {
+ log_err("failed to open pm events\n");
+ return -1;
+ }
+
+ len = read(fd, buf, sizeof(buf));
+ close(fd);
+ if (len <= 0) {
+ log_err("failed to read pm events\n");
+ return -1;
+ }
+
+ str = strstr(buf, type);
+ if (!str) {
+ log_err("failed to get type %s pm event\n", type);
+ return -1;
+ }
+
+ strcpy(line, str);
+ return 0;
+}
+
+static int userspace_pm_get_token(int fd)
+{
+ char line[1024], *str;
+ __u32 token;
+ int i;
+
+ /* Wait max 2 sec for the connection to be established */
+ for (i = 0; i < 10; i++) {
+ usleep(200000); /* 0.2s */
+ send_byte(fd);
+
+ sync();
+ if (userspace_pm_get_events_line("type:2", line))
+ continue;
+ str = strstr(line, "token");
+ if (!str)
+ continue;
+ if (sscanf(str, "token:%u,", &token) != 1)
+ continue;
+ return token;
+ }
+
+ return 0;
+}
+
+static int userspace_pm_add_subflow(__u32 token, char *addr, __u8 id)
+{
+ bool ipv6 = strstr(addr, ":");
+ char line[1024], *str;
+ __u32 sport, dport;
+
+ if (userspace_pm_get_events_line("type:2", line))
+ return -1;
+
+ str = strstr(line, "sport");
+ if (!str || sscanf(str, "sport:%u,dport:%u,", &sport, &dport) != 2) {
+ log_err("add_subflow error, str=%s\n", str);
+ return -1;
+ }
+
+ str = ipv6 ? (strstr(addr, ".") ? "::ffff:"ADDR_1 : ADDR6_1) : ADDR_1;
+ SYS_NOFAIL("ip netns exec %s %s csf lip %s lid %u rip %s rport %u token %u",
+ NS_TEST, PM_CTL, addr, id, str, dport, token);
+
+ return 0;
+}
+
+static void run_iters_address(void)
+{
+ int server_fd, client_fd, accept_fd;
+ int is_mptcp, err;
+ socklen_t len;
+ __u32 token;
+
+ server_fd = start_mptcp_server(AF_INET, ADDR_1, PORT_1, 0);
+ if (!ASSERT_OK_FD(server_fd, "start_mptcp_server"))
+ return;
+
+ client_fd = connect_to_fd(server_fd, 0);
+ if (!ASSERT_OK_FD(client_fd, "connect_to_fd"))
+ goto close_server;
+
+ accept_fd = accept(server_fd, NULL, NULL);
+ if (!ASSERT_OK_FD(accept_fd, "accept"))
+ goto close_client;
+
+ token = userspace_pm_get_token(client_fd);
+ if (!token)
+ goto close_client;
+ recv_byte(accept_fd);
+ usleep(200000); /* 0.2s */
+
+ err = userspace_pm_add_subflow(token, ADDR_2, 10);
+ err = err ?: userspace_pm_add_subflow(token, ADDR_3, 20);
+ err = err ?: userspace_pm_add_subflow(token, ADDR_4, 30);
+ if (!ASSERT_OK(err, "userspace_pm_add_subflow"))
+ goto close_accept;
+
+ send_byte(accept_fd);
+ recv_byte(client_fd);
+
+ len = sizeof(is_mptcp);
+ /* mainly to trigger the BPF program */
+ err = getsockopt(client_fd, SOL_TCP, TCP_IS_MPTCP, &is_mptcp, &len);
+ if (ASSERT_OK(err, "getsockopt(client_fd, TCP_IS_MPTCP)"))
+ ASSERT_EQ(is_mptcp, 1, "is_mptcp");
+
+close_accept:
+ close(accept_fd);
+close_client:
+ close(client_fd);
+close_server:
+ close(server_fd);
+}
+
+static void test_iters_address(void)
+{
+ struct mptcp_bpf_iters *skel;
+ struct netns_obj *netns;
+ int cgroup_fd;
+ int err;
+
+ cgroup_fd = test__join_cgroup("/iters_address");
+ if (!ASSERT_OK_FD(cgroup_fd, "join_cgroup: iters_address"))
+ return;
+
+ skel = mptcp_bpf_iters__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "skel_open_load: iters_address"))
+ goto close_cgroup;
+
+ skel->links.iters_address = bpf_program__attach_cgroup(skel->progs.iters_address,
+ cgroup_fd);
+ if (!ASSERT_OK_PTR(skel->links.iters_address, "attach getsockopt"))
+ goto skel_destroy;
+
+ netns = netns_new(NS_TEST, true);
+ if (!ASSERT_OK_PTR(netns, "netns_new"))
+ goto skel_destroy;
+
+ err = userspace_pm_init(MPTCP_PM_TYPE_USERSPACE);
+ if (!ASSERT_OK(err, "userspace_pm_init: iters_address"))
+ goto close_netns;
+
+ run_iters_address();
+
+ /* 10 + 20 + 30 = 60 */
+ ASSERT_EQ(skel->bss->ids, 60, "address ids");
+
+ userspace_pm_cleanup();
+close_netns:
+ netns_free(netns);
+skel_destroy:
+ mptcp_bpf_iters__destroy(skel);
+close_cgroup:
+ close(cgroup_fd);
+}
+
static struct netns_obj *sched_init(char *flags, char *sched)
{
struct netns_obj *netns;
@@ -760,6 +972,8 @@ void test_mptcp(void)
test_subflow();
if (test__start_subtest("iters_subflow"))
test_iters_subflow();
+ if (test__start_subtest("iters_address"))
+ test_iters_address();
if (test__start_subtest("default"))
test_default();
if (test__start_subtest("first"))
diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf.h b/tools/testing/selftests/bpf/progs/mptcp_bpf.h
index b1f6e1fb467e..5e29ac93d823 100644
--- a/tools/testing/selftests/bpf/progs/mptcp_bpf.h
+++ b/tools/testing/selftests/bpf/progs/mptcp_bpf.h
@@ -51,6 +51,11 @@ bpf_mptcp_subflow_ctx(const struct sock *sk) __ksym;
extern struct sock *
bpf_mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow) __ksym;
+extern void bpf_spin_lock_bh(spinlock_t *lock) __ksym;
+extern void bpf_spin_unlock_bh(spinlock_t *lock) __ksym;
+
+extern bool bpf_ipv4_is_private_10(__be32 addr) __ksym;
+
extern void mptcp_subflow_set_scheduled(struct mptcp_subflow_context *subflow,
bool scheduled) __ksym;
diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf_iters.c b/tools/testing/selftests/bpf/progs/mptcp_bpf_iters.c
index fd5691a4073b..4c6e2fa4fbc2 100644
--- a/tools/testing/selftests/bpf/progs/mptcp_bpf_iters.c
+++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_iters.c
@@ -61,3 +61,37 @@ int iters_subflow(struct bpf_sockopt *ctx)
bpf_mptcp_sock_release(msk);
return 1;
}
+
+SEC("cgroup/getsockopt")
+int iters_address(struct bpf_sockopt *ctx)
+{
+ struct mptcp_pm_addr_entry *entry;
+ struct bpf_sock *sk = ctx->sk;
+ struct mptcp_sock *msk;
+ int local_ids = 0;
+
+ if (ctx->level != SOL_TCP || ctx->optname != TCP_IS_MPTCP)
+ return 1;
+
+ msk = bpf_skc_to_mptcp_sock(sk);
+ if (!msk || msk->pm.server_side)
+ return 1;
+
+ bpf_spin_lock_bh(&msk->pm.lock);
+ bpf_for_each(mptcp_userspace_pm_addr, entry, (struct sock *)sk) {
+ /* Here MPTCP-specific path manager kfunc can be called:
+ * this test is not doing anything really useful, only to
+ * verify the iteration works.
+ */
+
+ if (!bpf_ipv4_is_private_10(entry->addr.addr.s_addr))
+ break;
+
+ local_ids += entry->addr.id;
+ }
+ bpf_spin_unlock_bh(&msk->pm.lock);
+
+ ids = local_ids;
+
+ return 1;
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter
2025-02-07 10:35 [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter Geliang Tang
` (4 preceding siblings ...)
2025-02-07 10:36 ` [PATCH mptcp-next v5 5/5] selftests/bpf: Add mptcp_userspace_pm_addr bpf_iter subtest Geliang Tang
@ 2025-02-07 10:57 ` MPTCP CI
2025-02-07 11:44 ` MPTCP CI
6 siblings, 0 replies; 8+ messages in thread
From: MPTCP CI @ 2025-02-07 10:57 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
Hi Geliang,
Thank you for your modifications, that's great!
But sadly, our CI spotted some issues with it when trying to build it.
You can find more details there:
https://github.com/multipath-tcp/mptcp_net-next/actions/runs/13198351456
Status: failure
Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/bf5c2a4b6df9
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=931534
Feel free to reply to this email if you cannot access logs, if you need
some support to fix the error, if this doesn't seem to be caused by your
modifications or if the error is a false positive one.
Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter
2025-02-07 10:35 [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter Geliang Tang
` (5 preceding siblings ...)
2025-02-07 10:57 ` [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter MPTCP CI
@ 2025-02-07 11:44 ` MPTCP CI
6 siblings, 0 replies; 8+ messages in thread
From: MPTCP CI @ 2025-02-07 11:44 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: Success! ✅
- KVM Validation: debug: 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/13198351458
Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/bf5c2a4b6df9
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=931534
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] 8+ messages in thread
end of thread, other threads:[~2025-02-07 11:44 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-07 10:35 [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter Geliang Tang
2025-02-07 10:35 ` [PATCH mptcp-next v5 1/5] selftests/bpf: Add mptcp pm_nl_ctl link Geliang Tang
2025-02-07 10:35 ` [PATCH mptcp-next v5 2/5] selftests/bpf: Use pm_nl_ctl if ip mptcp not supported Geliang Tang
2025-02-07 10:36 ` [PATCH mptcp-next v5 3/5] bpf: Add mptcp_userspace_pm_addr bpf_iter Geliang Tang
2025-02-07 10:36 ` [PATCH mptcp-next v5 4/5] bpf: Export more helpers for mptcp_userspace_pm_addr test Geliang Tang
2025-02-07 10:36 ` [PATCH mptcp-next v5 5/5] selftests/bpf: Add mptcp_userspace_pm_addr bpf_iter subtest Geliang Tang
2025-02-07 10:57 ` [PATCH mptcp-next v5 0/5] add mptcp_address bpf_iter MPTCP CI
2025-02-07 11:44 ` MPTCP CI
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.