:p
atchew
Login
From: Geliang Tang <tanggeliang@kylinos.cn> This patch set adds a mptcp_subflow type bpf_iter, and self tests. Geliang Tang (4): bpf: Add mptcp_subflow bpf_iter bpf: Register mptcp tracing kfunc set selftests/bpf: Add mptcp_subflow bpf_iter test prog selftests/bpf: Add mptcp_subflow bpf_iter subtest kernel/bpf/helpers.c | 3 + net/mptcp/bpf.c | 59 +++++++++++++++++++ .../testing/selftests/bpf/bpf_experimental.h | 7 +++ .../testing/selftests/bpf/prog_tests/mptcp.c | 55 +++++++++++++++++ tools/testing/selftests/bpf/progs/mptcp_bpf.h | 3 + .../selftests/bpf/progs/mptcp_bpf_iter.c | 38 ++++++++++++ 6 files changed, 165 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/mptcp_bpf_iter.c -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> It's necessary to traverse all subflows on the conn_list of an MPTCP socket and then call kfunc to modify the fields of each subflow. In kernel space, mptcp_for_each_subflow() helper is used for this: mptcp_for_each_subflow(msk, subflow) kfunc(subflow); But in the MPTCP BPF program, this has not yet been implemented. As Martin suggested recently, this conn_list walking + modify-by-kfunc usage fits the bpf_iter use case. This patch adds a new bpf_iter type named "mptcp_subflow" to do this. Suggested-by: Martin KaFai Lau <martin.lau@kernel.org> Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- kernel/bpf/helpers.c | 3 +++ net/mptcp/bpf.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index XXXXXXX..XXXXXXX 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -XXX,XX +XXX,XX @@ BTF_ID_FLAGS(func, bpf_preempt_enable) BTF_ID_FLAGS(func, bpf_iter_bits_new, KF_ITER_NEW) BTF_ID_FLAGS(func, bpf_iter_bits_next, KF_ITER_NEXT | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_iter_bits_destroy, KF_ITER_DESTROY) +BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_new) +BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_next) +BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_destroy) BTF_KFUNCS_END(common_btf_ids) static const struct btf_kfunc_id_set common_kfunc_set = { diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c index XXXXXXX..XXXXXXX 100644 --- a/net/mptcp/bpf.c +++ b/net/mptcp/bpf.c @@ -XXX,XX +XXX,XX @@ static const struct btf_kfunc_id_set bpf_mptcp_fmodret_set = { .set = &bpf_mptcp_fmodret_ids, }; +struct bpf_iter__mptcp_subflow { + __bpf_md_ptr(struct bpf_iter_meta *, meta); + __bpf_md_ptr(struct mptcp_sock *, msk); + __bpf_md_ptr(struct list_head *, pos); +}; + +DEFINE_BPF_ITER_FUNC(mptcp_subflow, struct bpf_iter_meta *meta, + struct mptcp_sock *msk, struct list_head *pos) + +struct bpf_iter_mptcp_subflow { + __u64 __opaque[3]; +} __attribute__((aligned(8))); + +struct bpf_iter_mptcp_subflow_kern { + struct mptcp_sock *msk; + struct list_head *pos; +} __attribute__((aligned(8))); + +__bpf_kfunc_start_defs(); + +__bpf_kfunc int bpf_iter_mptcp_subflow_new(struct bpf_iter_mptcp_subflow *it, + struct mptcp_sock *msk) +{ + struct bpf_iter_mptcp_subflow_kern *kit = (void *)it; + + kit->msk = msk; + kit->pos = &msk->conn_list; + spin_lock_bh(&msk->pm.lock); + + return 0; +} + +__bpf_kfunc struct mptcp_subflow_context * +bpf_iter_mptcp_subflow_next(struct bpf_iter_mptcp_subflow *it) +{ + struct bpf_iter_mptcp_subflow_kern *kit = (void *)it; + struct mptcp_subflow_context *subflow; + struct mptcp_sock *msk = kit->msk; + + subflow = list_entry((kit->pos)->next, struct mptcp_subflow_context, node); + if (list_entry_is_head(subflow, &msk->conn_list, node)) + return NULL; + + kit->pos = &subflow->node; + return subflow; +} + +__bpf_kfunc void bpf_iter_mptcp_subflow_destroy(struct bpf_iter_mptcp_subflow *it) +{ + struct bpf_iter_mptcp_subflow_kern *kit = (void *)it; + struct mptcp_sock *msk = kit->msk; + + spin_unlock_bh(&msk->pm.lock); +} + +__bpf_kfunc_end_defs(); + __diag_push(); __diag_ignore_all("-Wmissing-prototypes", "kfuncs which will be used in BPF programs"); -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> Since the kfuncs mptcp_subflow_active() and mptcp_subflow_set_scheduled() are invoked in the mptcp_subflow bpf_iter test in a trace for mptcp_subflow_get_send(), it's necessary to register them into a BPF_PROG_TYPE_TRACING type kfunc set. Note: BTF_KFUNCS_START(bpf_mptcp_sched_kfunc_ids) BTF_ID_FLAGS(func, mptcp_subflow_set_scheduled) BTF_ID_FLAGS(func, mptcp_subflow_active) BTF_KFUNCS_END(bpf_mptcp_sched_kfunc_ids) Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- net/mptcp/bpf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c index XXXXXXX..XXXXXXX 100644 --- a/net/mptcp/bpf.c +++ b/net/mptcp/bpf.c @@ -XXX,XX +XXX,XX @@ static int __init bpf_mptcp_kfunc_init(void) int ret; ret = register_btf_fmodret_id_set(&bpf_mptcp_fmodret_set); + ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, + &bpf_mptcp_sched_kfunc_set); ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &bpf_mptcp_sched_kfunc_set); #ifdef CONFIG_BPF_JIT -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> This patch adds a new mptcp bpf selftest program for the newly added mptcp_subflow bpf_iter. Export bpf_iter_mptcp_subflow_new/_next/_destroy into bpf_experimental.h then use bpf_for_each(mptcp_subflow, subflow, msk) to walk the mptcp subflow list. Add a trace for mptcp_subflow_get_send() to do this test and invoke kfuncs mptcp_subflow_active() and mptcp_subflow_set_scheduled() in the loop. Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- .../testing/selftests/bpf/bpf_experimental.h | 7 ++++ tools/testing/selftests/bpf/progs/mptcp_bpf.h | 3 ++ .../selftests/bpf/progs/mptcp_bpf_iter.c | 38 +++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/mptcp_bpf_iter.c diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h index XXXXXXX..XXXXXXX 100644 --- a/tools/testing/selftests/bpf/bpf_experimental.h +++ b/tools/testing/selftests/bpf/bpf_experimental.h @@ -XXX,XX +XXX,XX @@ extern int bpf_iter_css_new(struct bpf_iter_css *it, extern struct cgroup_subsys_state *bpf_iter_css_next(struct bpf_iter_css *it) __weak __ksym; extern void bpf_iter_css_destroy(struct bpf_iter_css *it) __weak __ksym; +struct bpf_iter_mptcp_subflow; +extern int bpf_iter_mptcp_subflow_new(struct bpf_iter_mptcp_subflow *it, + struct mptcp_sock *msk) __weak __ksym; +extern struct mptcp_subflow_context * +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; + 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/progs/mptcp_bpf.h b/tools/testing/selftests/bpf/progs/mptcp_bpf.h index XXXXXXX..XXXXXXX 100644 --- a/tools/testing/selftests/bpf/progs/mptcp_bpf.h +++ b/tools/testing/selftests/bpf/progs/mptcp_bpf.h @@ -XXX,XX +XXX,XX @@ mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow) extern void mptcp_subflow_set_scheduled(struct mptcp_subflow_context *subflow, bool scheduled) __ksym; +extern void bpf_rcu_read_lock(void) __ksym; +extern void bpf_rcu_read_unlock(void) __ksym; + extern struct mptcp_subflow_context * bpf_mptcp_subflow_ctx_by_pos(const struct mptcp_sched_data *data, unsigned int pos) __ksym; diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf_iter.c b/tools/testing/selftests/bpf/progs/mptcp_bpf_iter.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_iter.c @@ -XXX,XX +XXX,XX @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024, Kylin Software */ + +/* vmlinux.h, bpf_helpers.h and other 'define' */ +#include "bpf_tracing_net.h" +#include "mptcp_bpf.h" + +char _license[] SEC("license") = "GPL"; +int pid; + +extern bool mptcp_subflow_active(struct mptcp_subflow_context *subflow) __ksym; + +SEC("fentry/mptcp_subflow_get_send") +struct sock *BPF_PROG(trace_mptcp_subflow_get_send, struct mptcp_sock *msk) +{ + struct mptcp_subflow_context *subflow; + int i = 0; + + if (bpf_get_current_pid_tgid() >> 32 != pid) + return NULL; + + bpf_rcu_read_lock(); + bpf_for_each(mptcp_subflow, subflow, msk) { + if (i++ > MPTCP_SUBFLOWS_MAX) + break; + + if (subflow->token != msk->token) + break; + + if (!mptcp_subflow_active(subflow)) + continue; + + mptcp_subflow_set_scheduled(subflow, false); + } + bpf_rcu_read_unlock(); + + return NULL; +} -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> This patch adds a subtest named test_bpf_iter to load and verify the newly added mptcp_subflow type bpf_iter example in test_mptcp. Use endpoint_init() to add a new subflow endpoint. Use send_byte() to trigger the tracing program for mptcp_subflow_get_send. Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- .../testing/selftests/bpf/prog_tests/mptcp.c | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing/selftests/bpf/prog_tests/mptcp.c index XXXXXXX..XXXXXXX 100644 --- a/tools/testing/selftests/bpf/prog_tests/mptcp.c +++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c @@ -XXX,XX +XXX,XX @@ #include "mptcp_sock.skel.h" #include "mptcpify.skel.h" #include "mptcp_subflow.skel.h" +#include "mptcp_bpf_iter.skel.h" #include "mptcp_bpf_first.skel.h" #include "mptcp_bpf_bkup.skel.h" #include "mptcp_bpf_rr.skel.h" @@ -XXX,XX +XXX,XX @@ static void test_subflow(void) close(cgroup_fd); } +static void run_bpf_iter(void) +{ + int server_fd, client_fd; + + server_fd = start_mptcp_server(AF_INET, ADDR_1, PORT_1, 0); + if (!ASSERT_GE(server_fd, 0, "start_mptcp_server")) + return; + + client_fd = connect_to_fd(server_fd, 0); + if (!ASSERT_GE(client_fd, 0, "connect to fd")) + goto close_server; + + send_byte(client_fd); + wait_for_new_subflows(client_fd); + send_byte(client_fd); + + close(client_fd); +close_server: + close(server_fd); +} + +static void test_bpf_iter(void) +{ + struct mptcp_bpf_iter *skel; + struct nstoken *nstoken; + int err; + + skel = mptcp_bpf_iter__open_and_load(); + if (!ASSERT_OK_PTR(skel, "skel_open_load: mptcp_iter")) + return; + + skel->bss->pid = getpid(); + + err = mptcp_bpf_iter__attach(skel); + if (!ASSERT_OK(err, "skel_attach: mptcp_iter")) + goto skel_destroy; + + nstoken = create_netns(); + if (!ASSERT_OK_PTR(nstoken, "create_netns: mptcp_iter")) + goto skel_destroy; + + if (endpoint_init("subflow") < 0) + goto close_netns; + + run_bpf_iter(); + +close_netns: + cleanup_netns(nstoken); +skel_destroy: + mptcp_bpf_iter__destroy(skel); +} + static struct nstoken *sched_init(char *flags, char *sched) { struct nstoken *nstoken; @@ -XXX,XX +XXX,XX @@ void test_mptcp(void) test_mptcpify(); if (test__start_subtest("subflow")) test_subflow(); + if (test__start_subtest("bpf_iter")) + test_bpf_iter(); if (test__start_subtest("default")) test_default(); if (test__start_subtest("first")) -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> v12: - squash patch 4 and patch 6 into one. - use TCP_IS_MPTCP instead of TCP_CONGESTION. v11: - fix building errors in v10. - update patch 5, change bpf test IP addresses more like that of mptcp join selftests from: #define ADDR_1 "10.0.1.1" #define ADDR_2 "10.0.1.2" #define ADDR_3 "10.0.1.3" #define ADDR_4 "10.0.1.4" to #define ADDR_1 "10.0.1.1" #define ADDR_2 "10.0.2.1" #define ADDR_3 "10.0.3.1" #define ADDR_4 "10.0.4.1" This ensures that it can be expanded to two namespaces in the future. v10: - rename bpf prog to "mptcp_bpf_iters.c" and change it as "cgroup/getsockopt" type. Since another bpf_iter "mptcp_address", to traverse all address entries on userspace_pm_local_addr_list of an MPTCP socket for implementing the MPTCP BPF path manager, will be added in the next set. The test program for "mptcp_address" bpf_iter will be added into this "mptcp_bpf_iters.c" file too and also defined as "cgroup/getsockopt" type. - change all bpf kfunc static as Matt suggested. - drop mptcp_subflow_active and mptcp_subflow_set_scheduled from the test program as Matt suggested. v9: - rename bpf prog to "mptcp_bpf_iters_subflow.c" - drop the helper bpf_mptcp_sk(), it's not used in this test. v8: - Make the test prog in patch 4 more like a bpf packet scheduler. - Export more mptcp helpers into BPF in patch 1. v7: - As Martin recently replied, mptcp_stubflow bpf_iter can still be used in tracing. So go back to the tracing selftest. v6: - add KF_TRUSTED_ARGS flag in patch 2 (Andrii, Martin), then acquire and release helpers (patch 3) are needed to be implemented. - test mptcp_subflow bpf_iter in "cgroup/getsockopt" (patch 5), instead of testing them in "tracing" (Martin). v5: - update patch 1 as Andrii suggested: if msk is NULL, initialize kit->msk to NULL in _new() and check it in _next(). v4: - squash patch 1/5 and 3/5 in v3 together as Matt suggested. - a new squash-to patch to drop mptcp_subflow_active declaration in bpf_burst. v3: - drop bpf_iter__mptcp_subflow, __diag_push, __diag_pop and __diag_ignore_all - drop declarations for bpf kfuncs v2: - update patch 1 as Martin and Andrii suggested. - fix warnings and errors reported by MPTCP CI. This patch set adds a mptcp_subflow type bpf_iter, and self tests. Geliang Tang (8): bpf: Register mptcp common kfunc set bpf: Add mptcp_subflow bpf_iter bpf: Acquire and release mptcp socket selftests/bpf: More endpoints for endpoint_init selftests/bpf: Add mptcp_subflow bpf_iter subtest Squash to "selftests/bpf: Add bpf scheduler test" Revert "bpf: Export more bpf_burst related functions" Squash to "bpf: Add bpf_mptcp_sched_kfunc_set" net/mptcp/bpf.c | 99 ++++++++++++- net/mptcp/protocol.h | 1 - .../testing/selftests/bpf/bpf_experimental.h | 7 + .../testing/selftests/bpf/prog_tests/mptcp.c | 131 +++++++++++++++++- tools/testing/selftests/bpf/progs/mptcp_bpf.h | 9 ++ .../selftests/bpf/progs/mptcp_bpf_iters.c | 64 +++++++++ 6 files changed, 298 insertions(+), 13 deletions(-) create mode 100644 tools/testing/selftests/bpf/progs/mptcp_bpf_iters.c -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> MPTCP helper mptcp_sk() is used to convert struct sock to mptcp_sock. Helpers mptcp_subflow_ctx() and mptcp_subflow_tcp_sock() are used to convert between struct mptcp_subflow_context and sock. They all will be used in MPTCP BPF programs too. This patch defines corresponding wrappers of them, and put the wrappers into mptcp common kfunc set and register the set with the flag BPF_PROG_TYPE_UNSPEC to let them accessible to all types of BPF programs. Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- net/mptcp/bpf.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c index XXXXXXX..XXXXXXX 100644 --- a/net/mptcp/bpf.c +++ b/net/mptcp/bpf.c @@ -XXX,XX +XXX,XX @@ __diag_push(); __diag_ignore_all("-Wmissing-prototypes", "kfuncs which will be used in BPF programs"); +__bpf_kfunc static struct mptcp_sock *bpf_mptcp_sk(struct sock *sk) +{ + return mptcp_sk(sk); +} + +__bpf_kfunc static struct mptcp_subflow_context * +bpf_mptcp_subflow_ctx(const struct sock *sk) +{ + return mptcp_subflow_ctx(sk); +} + +__bpf_kfunc static struct sock * +bpf_mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow) +{ + return mptcp_subflow_tcp_sock(subflow); +} + __bpf_kfunc struct mptcp_subflow_context * bpf_mptcp_subflow_ctx_by_pos(const struct mptcp_sched_data *data, unsigned int pos) { @@ -XXX,XX +XXX,XX @@ __bpf_kfunc bool bpf_mptcp_subflow_queues_empty(struct sock *sk) __diag_pop(); +BTF_KFUNCS_START(bpf_mptcp_common_kfunc_ids) +BTF_ID_FLAGS(func, bpf_mptcp_sk) +BTF_ID_FLAGS(func, bpf_mptcp_subflow_ctx) +BTF_ID_FLAGS(func, bpf_mptcp_subflow_tcp_sock) +BTF_KFUNCS_END(bpf_mptcp_common_kfunc_ids) + +static const struct btf_kfunc_id_set bpf_mptcp_common_kfunc_set = { + .owner = THIS_MODULE, + .set = &bpf_mptcp_common_kfunc_ids, +}; + BTF_KFUNCS_START(bpf_mptcp_sched_kfunc_ids) BTF_ID_FLAGS(func, mptcp_subflow_set_scheduled) BTF_ID_FLAGS(func, bpf_mptcp_subflow_ctx_by_pos) @@ -XXX,XX +XXX,XX @@ static int __init bpf_mptcp_kfunc_init(void) int ret; ret = register_btf_fmodret_id_set(&bpf_mptcp_fmodret_set); + ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC, + &bpf_mptcp_common_kfunc_set); ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &bpf_mptcp_sched_kfunc_set); #ifdef CONFIG_BPF_JIT -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> It's necessary to traverse all subflows on the conn_list of an MPTCP socket and then call kfunc to modify the fields of each subflow. In kernel space, mptcp_for_each_subflow() helper is used for this: mptcp_for_each_subflow(msk, subflow) kfunc(subflow); But in the MPTCP BPF program, this has not yet been implemented. As Martin suggested recently, this conn_list walking + modify-by-kfunc usage fits the bpf_iter use case. So this patch adds a new bpf_iter type named "mptcp_subflow" to do this and implements its helpers bpf_iter_mptcp_subflow_new()/_next()/ _destroy(). And register these bpf_iter mptcp_subflow into mptcp common kfunc set. Then bpf_for_each() for mptcp_subflow can be used in BPF program like this: bpf_for_each(mptcp_subflow, subflow, msk) kfunc(subflow); v2: remove msk->pm.lock in _new() and _destroy() (Martin) drop DEFINE_BPF_ITER_FUNC, change opaque[3] to opaque[2] (Andrii) v3: drop bpf_iter__mptcp_subflow v4: if msk is NULL, initialize kit->msk to NULL in _new() and check it in _next() (Andrii) v5: use list_is_last() instead of list_entry_is_head() add KF_ITER_NEW/NEXT/DESTROY flags add msk_owned_by_me in _new() v6: add KF_TRUSTED_ARGS flag (Andrii, Martin) "Suggested-by: Martin KaFai Lau <martin.lau@kernel.org>" Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- net/mptcp/bpf.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c index XXXXXXX..XXXXXXX 100644 --- a/net/mptcp/bpf.c +++ b/net/mptcp/bpf.c @@ -XXX,XX +XXX,XX @@ static const struct btf_kfunc_id_set bpf_mptcp_fmodret_set = { .set = &bpf_mptcp_fmodret_ids, }; -__diag_push(); -__diag_ignore_all("-Wmissing-prototypes", - "kfuncs which will be used in BPF programs"); +struct bpf_iter_mptcp_subflow { + __u64 __opaque[2]; +} __attribute__((aligned(8))); + +struct bpf_iter_mptcp_subflow_kern { + struct mptcp_sock *msk; + struct list_head *pos; +} __attribute__((aligned(8))); + +__bpf_kfunc_start_defs(); __bpf_kfunc static struct mptcp_sock *bpf_mptcp_sk(struct sock *sk) { @@ -XXX,XX +XXX,XX @@ bpf_mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow) return mptcp_subflow_tcp_sock(subflow); } +__bpf_kfunc static int bpf_iter_mptcp_subflow_new(struct bpf_iter_mptcp_subflow *it, + struct mptcp_sock *msk) +{ + struct bpf_iter_mptcp_subflow_kern *kit = (void *)it; + + kit->msk = msk; + if (!msk) + return -EINVAL; + + msk_owned_by_me(msk); + + kit->pos = &msk->conn_list; + return 0; +} + +__bpf_kfunc static struct mptcp_subflow_context * +bpf_iter_mptcp_subflow_next(struct bpf_iter_mptcp_subflow *it) +{ + struct bpf_iter_mptcp_subflow_kern *kit = (void *)it; + + if (!kit->msk || list_is_last(kit->pos, &kit->msk->conn_list)) + return NULL; + + kit->pos = kit->pos->next; + return list_entry(kit->pos, struct mptcp_subflow_context, node); +} + +__bpf_kfunc static void bpf_iter_mptcp_subflow_destroy(struct bpf_iter_mptcp_subflow *it) +{ +} + __bpf_kfunc struct mptcp_subflow_context * bpf_mptcp_subflow_ctx_by_pos(const struct mptcp_sched_data *data, unsigned int pos) { @@ -XXX,XX +XXX,XX @@ __bpf_kfunc bool bpf_mptcp_subflow_queues_empty(struct sock *sk) return tcp_rtx_queue_empty(sk); } -__diag_pop(); +__bpf_kfunc_end_defs(); BTF_KFUNCS_START(bpf_mptcp_common_kfunc_ids) BTF_ID_FLAGS(func, bpf_mptcp_sk) BTF_ID_FLAGS(func, bpf_mptcp_subflow_ctx) BTF_ID_FLAGS(func, bpf_mptcp_subflow_tcp_sock) +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_KFUNCS_END(bpf_mptcp_common_kfunc_ids) static const struct btf_kfunc_id_set bpf_mptcp_common_kfunc_set = { -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> The KF_TRUSTED_ARGS flag is used for bpf_iter_mptcp_subflow_new, it indicates that the all pointer arguments are valid. It's necessary to add a KF_ACQUIRE helper to get valid "msk". This patch adds bpf_mptcp_sock_acquire() and bpf_mptcp_sock_release() helpers for this. Increase sk->sk_refcnt in _acquire() and decrease it in _release(). Register them with KF_ACQUIRE flag and KF_RELEASE flag. 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 XXXXXXX..XXXXXXX 100644 --- a/net/mptcp/bpf.c +++ b/net/mptcp/bpf.c @@ -XXX,XX +XXX,XX @@ __bpf_kfunc static void bpf_iter_mptcp_subflow_destroy(struct bpf_iter_mptcp_sub { } +__bpf_kfunc static struct mptcp_sock *bpf_mptcp_sock_acquire(struct mptcp_sock *msk) +{ + struct sock *sk = (struct sock *)msk; + + if (sk && refcount_inc_not_zero(&sk->sk_refcnt)) + return msk; + return NULL; +} + +__bpf_kfunc static void bpf_mptcp_sock_release(struct mptcp_sock *msk) +{ + struct sock *sk = (struct sock *)msk; + + WARN_ON_ONCE(!sk || !refcount_dec_not_one(&sk->sk_refcnt)); +} + __bpf_kfunc struct mptcp_subflow_context * bpf_mptcp_subflow_ctx_by_pos(const struct mptcp_sched_data *data, unsigned int pos) { @@ -XXX,XX +XXX,XX @@ BTF_ID_FLAGS(func, bpf_mptcp_subflow_tcp_sock) 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_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) static const struct btf_kfunc_id_set bpf_mptcp_common_kfunc_set = { -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> This patch changes ADDR_2 from "10.0.1.2" to "10.0.2.1", and adds two more IPv4 test addresses ADDR_3 - ADDR_4, four IPv6 addresses ADDR6_1 - ADDR6_4. Add a new helper address_init() to initialize all these addresses. Add a new parameter "endpoints" for endpoint_init() to control how many endpoints are used for the tests. This makes it more flexible. Update the parameters of endpoint_init() in test_subflow(). Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- .../testing/selftests/bpf/prog_tests/mptcp.c | 56 +++++++++++++++++-- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing/selftests/bpf/prog_tests/mptcp.c index XXXXXXX..XXXXXXX 100644 --- a/tools/testing/selftests/bpf/prog_tests/mptcp.c +++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c @@ -XXX,XX +XXX,XX @@ #define NS_TEST "mptcp_ns" #define ADDR_1 "10.0.1.1" -#define ADDR_2 "10.0.1.2" +#define ADDR_2 "10.0.2.1" +#define ADDR_3 "10.0.3.1" +#define ADDR_4 "10.0.4.1" +#define ADDR6_1 "dead:beef:1::1" +#define ADDR6_2 "dead:beef:2::1" +#define ADDR6_3 "dead:beef:3::1" +#define ADDR6_4 "dead:beef:4::1" #define PORT_1 10001 #define WITH_DATA true #define WITHOUT_DATA false @@ -XXX,XX +XXX,XX @@ static void test_mptcpify(void) close(cgroup_fd); } -static int endpoint_init(char *flags) +static int address_init(void) { SYS(fail, "ip -net %s link add veth1 type veth peer name veth2", NS_TEST); SYS(fail, "ip -net %s addr add %s/24 dev veth1", NS_TEST, ADDR_1); + SYS(fail, "ip -net %s addr add %s/64 dev veth1 nodad", NS_TEST, ADDR6_1); SYS(fail, "ip -net %s link set dev veth1 up", NS_TEST); SYS(fail, "ip -net %s addr add %s/24 dev veth2", NS_TEST, ADDR_2); + SYS(fail, "ip -net %s addr add %s/64 dev veth2 nodad", NS_TEST, ADDR6_2); SYS(fail, "ip -net %s link set dev veth2 up", NS_TEST); - if (SYS_NOFAIL("ip -net %s mptcp endpoint add %s %s", NS_TEST, ADDR_2, flags)) { + + SYS(fail, "ip -net %s link add veth3 type veth peer name veth4", NS_TEST); + SYS(fail, "ip -net %s addr add %s/24 dev veth3", NS_TEST, ADDR_3); + SYS(fail, "ip -net %s addr add %s/64 dev veth3 nodad", NS_TEST, ADDR6_3); + SYS(fail, "ip -net %s link set dev veth3 up", NS_TEST); + SYS(fail, "ip -net %s addr add %s/24 dev veth4", NS_TEST, ADDR_4); + SYS(fail, "ip -net %s addr add %s/64 dev veth4 nodad", NS_TEST, ADDR6_4); + SYS(fail, "ip -net %s link set dev veth4 up", NS_TEST); + + return 0; +fail: + return -1; +} + +static int endpoint_add(char *addr, char *flags) +{ + return SYS_NOFAIL("ip -net %s mptcp endpoint add %s %s", NS_TEST, addr, flags); +} + +static int endpoint_init(char *flags, u8 endpoints) +{ + int ret = -1; + + if (!endpoints || endpoints > 4) + goto fail; + + if (address_init()) + goto fail; + + 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; } - return 0; + if (endpoints > 1) + ret = endpoint_add(ADDR_2, flags); + if (endpoints > 2) + ret = ret ?: endpoint_add(ADDR_3, flags); + if (endpoints > 3) + ret = ret ?: endpoint_add(ADDR_4, flags); + fail: - return -1; + return ret; } static void wait_for_new_subflows(int fd) @@ -XXX,XX +XXX,XX @@ static void test_subflow(void) if (!ASSERT_OK_PTR(nstoken, "create_netns: mptcp_subflow")) goto skel_destroy; - if (endpoint_init("subflow") < 0) + if (endpoint_init("subflow", 2) < 0) goto close_netns; run_subflow(); -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> This patch adds a "cgroup/getsockopt" program "iters_subflow" to test the newly added mptcp_subflow bpf_iter. Export mptcp_subflow helpers bpf_iter_mptcp_subflow_new/_next/_destroy, bpf_mptcp_sock_acquire/_release and other helpers into bpf_experimental.h. Use bpf_mptcp_sock_acquire() to acquire the msk, then use bpf_for_each() to walk the subflow list of this msk. MPTCP-specific packet scheduler kfunc can be called in the loop. In this test, just add all subflow ids to local veriable local_ids, then invoke the kfunc bpf_mptcp_subflow_tcp_sock() in the loop to pick a subsocket. Out of the loop, use bpf_mptcp_subflow_ctx() to get the subflow context of the picked subsocket and do some verification. Finally, assign local_ids to global variable ids so that the application can obtain this value, and release the msk. Add a subtest named test_iters_subflow to load and verify the newly added mptcp_subflow type bpf_iter example in test_mptcp. Use the helper endpoint_init() to add 3 new subflow endpoints. Send a byte of message to start the mptcp connection, and wait for new subflows to be added. getsockopt() is invoked to trigger the "cgroup/getsockopt" test program "iters_subflow". Check if skel->bss->ids equals 10 to verify whether this mptcp_subflow bpf_iter loops correctly as expected. Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- .../testing/selftests/bpf/bpf_experimental.h | 7 ++ .../testing/selftests/bpf/prog_tests/mptcp.c | 73 +++++++++++++++++++ tools/testing/selftests/bpf/progs/mptcp_bpf.h | 9 +++ .../selftests/bpf/progs/mptcp_bpf_iters.c | 64 ++++++++++++++++ 4 files changed, 153 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/mptcp_bpf_iters.c diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h index XXXXXXX..XXXXXXX 100644 --- a/tools/testing/selftests/bpf/bpf_experimental.h +++ b/tools/testing/selftests/bpf/bpf_experimental.h @@ -XXX,XX +XXX,XX @@ extern int bpf_iter_css_new(struct bpf_iter_css *it, extern struct cgroup_subsys_state *bpf_iter_css_next(struct bpf_iter_css *it) __weak __ksym; extern void bpf_iter_css_destroy(struct bpf_iter_css *it) __weak __ksym; +struct bpf_iter_mptcp_subflow; +extern int bpf_iter_mptcp_subflow_new(struct bpf_iter_mptcp_subflow *it, + struct mptcp_sock *msk) __weak __ksym; +extern struct mptcp_subflow_context * +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; + 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 XXXXXXX..XXXXXXX 100644 --- a/tools/testing/selftests/bpf/prog_tests/mptcp.c +++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c @@ -XXX,XX +XXX,XX @@ #include "mptcp_sock.skel.h" #include "mptcpify.skel.h" #include "mptcp_subflow.skel.h" +#include "mptcp_bpf_iters.skel.h" #include "mptcp_bpf_first.skel.h" #include "mptcp_bpf_bkup.skel.h" #include "mptcp_bpf_rr.skel.h" @@ -XXX,XX +XXX,XX @@ #ifndef MPTCP_INFO #define MPTCP_INFO 1 #endif +#ifndef TCP_IS_MPTCP +#define TCP_IS_MPTCP 43 /* Is MPTCP being used? */ +#endif #ifndef MPTCP_INFO_FLAG_FALLBACK #define MPTCP_INFO_FLAG_FALLBACK _BITUL(0) #endif @@ -XXX,XX +XXX,XX @@ static void test_subflow(void) close(cgroup_fd); } +static void run_iters_subflow(void) +{ + int server_fd, client_fd; + int is_mptcp, err; + socklen_t len; + + 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; + + send_byte(client_fd); + wait_for_new_subflows(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(client_fd); +close_server: + close(server_fd); +} + +static void test_iters_subflow(void) +{ + struct mptcp_bpf_iters *skel; + struct nstoken *nstoken; + int cgroup_fd; + + cgroup_fd = test__join_cgroup("/iters_subflow"); + if (!ASSERT_OK_FD(cgroup_fd, "join_cgroup: iters_subflow")) + return; + + skel = mptcp_bpf_iters__open_and_load(); + if (!ASSERT_OK_PTR(skel, "skel_open_load: iters_subflow")) + goto close_cgroup; + + skel->links.iters_subflow = bpf_program__attach_cgroup(skel->progs.iters_subflow, + cgroup_fd); + if (!ASSERT_OK_PTR(skel->links.iters_subflow, "attach getsockopt")) + goto skel_destroy; + + nstoken = create_netns(); + if (!ASSERT_OK_PTR(nstoken, "create_netns: iters_subflow")) + goto skel_destroy; + + if (endpoint_init("subflow", 4) < 0) + goto close_netns; + + run_iters_subflow(); + + /* 1 + 2 + 3 + 4 = 10 */ + ASSERT_EQ(skel->bss->ids, 10, "subflow ids"); + +close_netns: + cleanup_netns(nstoken); +skel_destroy: + mptcp_bpf_iters__destroy(skel); +close_cgroup: + close(cgroup_fd); +} + static struct nstoken *sched_init(char *flags, char *sched) { struct nstoken *nstoken; @@ -XXX,XX +XXX,XX @@ void test_mptcp(void) test_mptcpify(); if (test__start_subtest("subflow")) test_subflow(); + if (test__start_subtest("iters_subflow")) + test_iters_subflow(); 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 XXXXXXX..XXXXXXX 100644 --- a/tools/testing/selftests/bpf/progs/mptcp_bpf.h +++ b/tools/testing/selftests/bpf/progs/mptcp_bpf.h @@ -XXX,XX +XXX,XX @@ mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow) } /* ksym */ +extern struct mptcp_sock *bpf_mptcp_sock_acquire(struct mptcp_sock *msk) __ksym; +extern void bpf_mptcp_sock_release(struct mptcp_sock *msk) __ksym; + +extern struct mptcp_sock *bpf_mptcp_sk(struct sock *sk) __ksym; +extern struct mptcp_subflow_context * +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 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 new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_iters.c @@ -XXX,XX +XXX,XX @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024, Kylin Software */ + +/* vmlinux.h, bpf_helpers.h and other 'define' */ +#include "bpf_tracing_net.h" +#include "mptcp_bpf.h" + +char _license[] SEC("license") = "GPL"; +int ids; + +#ifndef TCP_IS_MPTCP +#define TCP_IS_MPTCP 43 /* Is MPTCP being used? */ +#endif + +SEC("cgroup/getsockopt") +int iters_subflow(struct bpf_sockopt *ctx) +{ + struct mptcp_subflow_context *subflow; + struct bpf_sock *sk = ctx->sk; + struct sock *ssk = NULL; + struct mptcp_sock *msk; + int local_ids = 0; + + if (!sk || sk->protocol != IPPROTO_MPTCP || + ctx->level != SOL_TCP || ctx->optname != TCP_IS_MPTCP) + return 1; + + msk = bpf_mptcp_sk((struct sock *)sk); + if (msk->pm.server_side || !msk->pm.subflows) + return 1; + + msk = bpf_mptcp_sock_acquire(msk); + if (!msk) + return 1; + bpf_for_each(mptcp_subflow, subflow, msk) { + /* Here MPTCP-specific packet scheduler kfunc can be called: + * this test is not doing anything really useful, only to + * verify the iteration works. + */ + + local_ids += subflow->subflow_id; + + /* only to check the following kfunc works */ + ssk = bpf_mptcp_subflow_tcp_sock(subflow); + } + + if (!ssk) + goto out; + + /* assert: if not OK, something wrong on the kernel side */ + if (ssk->sk_dport != ((struct sock *)msk)->sk_dport) + goto out; + + /* only to check the following kfunc works */ + subflow = bpf_mptcp_subflow_ctx(ssk); + if (subflow->token != msk->token) + goto out; + + ids = local_ids; + +out: + bpf_mptcp_sock_release(msk); + return 1; +} -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> Update endpoint_init() in sched_init(). Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- tools/testing/selftests/bpf/prog_tests/mptcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing/selftests/bpf/prog_tests/mptcp.c index XXXXXXX..XXXXXXX 100644 --- a/tools/testing/selftests/bpf/prog_tests/mptcp.c +++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c @@ -XXX,XX +XXX,XX @@ static struct nstoken *sched_init(char *flags, char *sched) if (!ASSERT_OK_PTR(nstoken, "create_netns")) return NULL; - if (endpoint_init("subflow") < 0) + if (endpoint_init("subflow", 2) < 0) goto fail; SYS(fail, "ip netns exec %s sysctl -qw net.mptcp.scheduler=%s", NS_TEST, sched); -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> This reverts commit 371136b55b559e2ef4d117a901b9f96ee036a175. Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- net/mptcp/bpf.c | 11 ----------- net/mptcp/protocol.c | 4 ++-- net/mptcp/protocol.h | 3 --- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c index XXXXXXX..XXXXXXX 100644 --- a/net/mptcp/bpf.c +++ b/net/mptcp/bpf.c @@ -XXX,XX +XXX,XX @@ bpf_mptcp_subflow_ctx_by_pos(const struct mptcp_sched_data *data, unsigned int p return data->contexts[pos]; } -__bpf_kfunc bool bpf_mptcp_subflow_queues_empty(struct sock *sk) -{ - return tcp_rtx_queue_empty(sk); -} - __bpf_kfunc_end_defs(); BTF_KFUNCS_START(bpf_mptcp_common_kfunc_ids) @@ -XXX,XX +XXX,XX @@ static const struct btf_kfunc_id_set bpf_mptcp_common_kfunc_set = { BTF_KFUNCS_START(bpf_mptcp_sched_kfunc_ids) BTF_ID_FLAGS(func, mptcp_subflow_set_scheduled) BTF_ID_FLAGS(func, bpf_mptcp_subflow_ctx_by_pos) -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, tcp_stream_memory_free) -BTF_ID_FLAGS(func, bpf_mptcp_subflow_queues_empty) -BTF_ID_FLAGS(func, mptcp_pm_subflow_chk_stale) BTF_KFUNCS_END(bpf_mptcp_sched_kfunc_ids) static const struct btf_kfunc_id_set bpf_mptcp_sched_kfunc_set = { diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index XXXXXXX..XXXXXXX 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -XXX,XX +XXX,XX @@ DEFINE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions); static struct net_device mptcp_napi_dev; /* Returns end sequence number of the receiver's advertised window */ -u64 mptcp_wnd_end(const struct mptcp_sock *msk) +static u64 mptcp_wnd_end(const struct mptcp_sock *msk) { return READ_ONCE(msk->wnd_end); } @@ -XXX,XX +XXX,XX @@ static long mptcp_timeout_from_subflow(const struct mptcp_subflow_context *subfl inet_csk(ssk)->icsk_timeout - jiffies : 0; } -void mptcp_set_timeout(struct sock *sk) +static void mptcp_set_timeout(struct sock *sk) { struct mptcp_subflow_context *subflow; long tout = 0; diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index XXXXXXX..XXXXXXX 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -XXX,XX +XXX,XX @@ void __mptcp_subflow_send_ack(struct sock *ssk); void mptcp_subflow_reset(struct sock *ssk); void mptcp_subflow_queue_clean(struct sock *sk, struct sock *ssk); void mptcp_sock_graft(struct sock *sk, struct socket *parent); -u64 mptcp_wnd_end(const struct mptcp_sock *msk); -void mptcp_set_timeout(struct sock *sk); -bool bpf_mptcp_subflow_queues_empty(struct sock *sk); struct mptcp_subflow_context * bpf_mptcp_subflow_ctx_by_pos(const struct mptcp_sched_data *data, unsigned int pos); struct sock *__mptcp_nmpc_sk(struct mptcp_sock *msk); -- 2.43.0
From: Geliang Tang <tanggeliang@kylinos.cn> Please update the subject to "bpf: Export mptcp packet scheduler helpers" Make bpf_mptcp_subflow_queues_empty static. Merge "bpf: Export more bpf_burst related functions" into this patch. Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> --- net/mptcp/bpf.c | 11 +++++++++++ net/mptcp/protocol.c | 4 ++-- net/mptcp/protocol.h | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c index XXXXXXX..XXXXXXX 100644 --- a/net/mptcp/bpf.c +++ b/net/mptcp/bpf.c @@ -XXX,XX +XXX,XX @@ bpf_mptcp_subflow_ctx_by_pos(const struct mptcp_sched_data *data, unsigned int p return data->contexts[pos]; } +__bpf_kfunc static bool bpf_mptcp_subflow_queues_empty(struct sock *sk) +{ + return tcp_rtx_queue_empty(sk); +} + __bpf_kfunc_end_defs(); BTF_KFUNCS_START(bpf_mptcp_common_kfunc_ids) @@ -XXX,XX +XXX,XX @@ static const struct btf_kfunc_id_set bpf_mptcp_common_kfunc_set = { BTF_KFUNCS_START(bpf_mptcp_sched_kfunc_ids) BTF_ID_FLAGS(func, mptcp_subflow_set_scheduled) BTF_ID_FLAGS(func, bpf_mptcp_subflow_ctx_by_pos) +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, tcp_stream_memory_free) +BTF_ID_FLAGS(func, bpf_mptcp_subflow_queues_empty) +BTF_ID_FLAGS(func, mptcp_pm_subflow_chk_stale) BTF_KFUNCS_END(bpf_mptcp_sched_kfunc_ids) static const struct btf_kfunc_id_set bpf_mptcp_sched_kfunc_set = { diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index XXXXXXX..XXXXXXX 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -XXX,XX +XXX,XX @@ DEFINE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions); static struct net_device mptcp_napi_dev; /* Returns end sequence number of the receiver's advertised window */ -static u64 mptcp_wnd_end(const struct mptcp_sock *msk) +u64 mptcp_wnd_end(const struct mptcp_sock *msk) { return READ_ONCE(msk->wnd_end); } @@ -XXX,XX +XXX,XX @@ static long mptcp_timeout_from_subflow(const struct mptcp_subflow_context *subfl inet_csk(ssk)->icsk_timeout - jiffies : 0; } -static void mptcp_set_timeout(struct sock *sk) +void mptcp_set_timeout(struct sock *sk) { struct mptcp_subflow_context *subflow; long tout = 0; diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index XXXXXXX..XXXXXXX 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -XXX,XX +XXX,XX @@ void __mptcp_subflow_send_ack(struct sock *ssk); void mptcp_subflow_reset(struct sock *ssk); void mptcp_subflow_queue_clean(struct sock *sk, struct sock *ssk); void mptcp_sock_graft(struct sock *sk, struct socket *parent); +u64 mptcp_wnd_end(const struct mptcp_sock *msk); +void mptcp_set_timeout(struct sock *sk); struct mptcp_subflow_context * bpf_mptcp_subflow_ctx_by_pos(const struct mptcp_sched_data *data, unsigned int pos); struct sock *__mptcp_nmpc_sk(struct mptcp_sock *msk); -- 2.43.0