diff options
author | Geliang Tang <tanggeliang@kylinos.cn> | 2024-04-20 09:25:15 +0000 |
---|---|---|
committer | Matthieu Baerts (NGI0) <matttbe@kernel.org> | 2024-04-20 09:25:15 +0000 |
commit | 88c98e672248ac9210f7d8e5619ac5978dbee074 (patch) | |
tree | 6df3b3889bea76170fc900217a5ef58619dd5a48 | |
parent | e6ac58e01630d64992e56cac58d3d2efbfc4023a (diff) | |
download | mptcp_net-next-88c98e672248ac9210f7d8e5619ac5978dbee074.tar.gz |
selftests/bpf: Add bpf_rr scheduler & test
This patch implements the round-robin BPF MPTCP scheduler, named bpf_rr,
which always picks the next available subflow to send data. If no such
next subflow available, picks the first one.
Using MPTCP_SCHED_TEST macro to add a new test for this bpf_rr
scheduler, the arguments "1 1" means data has been sent on both net
devices. Run this test by RUN_MPTCP_TEST macro.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
-rw-r--r-- | tools/testing/selftests/bpf/bpf_tcp_helpers.h | 5 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/prog_tests/mptcp.c | 3 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/progs/mptcp_bpf_rr.c | 77 |
3 files changed, 85 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/bpf_tcp_helpers.h b/tools/testing/selftests/bpf/bpf_tcp_helpers.h index f698f249686aea..cd4b6e6f14f9da 100644 --- a/tools/testing/selftests/bpf/bpf_tcp_helpers.h +++ b/tools/testing/selftests/bpf/bpf_tcp_helpers.h @@ -266,5 +266,10 @@ extern void mptcp_subflow_set_scheduled(struct mptcp_subflow_context *subflow, bool scheduled) __ksym; extern struct mptcp_subflow_context * bpf_mptcp_subflow_ctx_by_pos(const struct mptcp_sched_data *data, unsigned int pos) __ksym; +static __always_inline struct sock * +mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow) +{ + return subflow->tcp_sock; +} #endif diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing/selftests/bpf/prog_tests/mptcp.c index c274be0298c4f5..bb2b1fa59dc797 100644 --- a/tools/testing/selftests/bpf/prog_tests/mptcp.c +++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c @@ -11,6 +11,7 @@ #include "mptcpify.skel.h" #include "mptcp_bpf_first.skel.h" #include "mptcp_bpf_bkup.skel.h" +#include "mptcp_bpf_rr.skel.h" #define NS_TEST "mptcp_ns" #define WITH_DATA true @@ -541,6 +542,7 @@ static void test_##sched(void) \ MPTCP_SCHED_TEST(first, WITH_DATA, WITHOUT_DATA); MPTCP_SCHED_TEST(bkup, WITH_DATA, WITHOUT_DATA); +MPTCP_SCHED_TEST(rr, WITH_DATA, WITH_DATA); #define RUN_MPTCP_TEST(suffix) \ do { \ @@ -555,4 +557,5 @@ void test_mptcp(void) RUN_MPTCP_TEST(default); RUN_MPTCP_TEST(first); RUN_MPTCP_TEST(bkup); + RUN_MPTCP_TEST(rr); } diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf_rr.c b/tools/testing/selftests/bpf/progs/mptcp_bpf_rr.c new file mode 100644 index 00000000000000..39b7e1cfbbd555 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_rr.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2022, SUSE. */ + +#include <linux/bpf.h> +#include "bpf_tcp_helpers.h" + +char _license[] SEC("license") = "GPL"; + +struct mptcp_rr_storage { + struct sock *last_snd; +}; + +struct { + __uint(type, BPF_MAP_TYPE_SK_STORAGE); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, int); + __type(value, struct mptcp_rr_storage); +} mptcp_rr_map SEC(".maps"); + +SEC("struct_ops/mptcp_sched_rr_init") +void BPF_PROG(mptcp_sched_rr_init, struct mptcp_sock *msk) +{ + bpf_sk_storage_get(&mptcp_rr_map, msk, 0, + BPF_LOCAL_STORAGE_GET_F_CREATE); +} + +SEC("struct_ops/mptcp_sched_rr_release") +void BPF_PROG(mptcp_sched_rr_release, struct mptcp_sock *msk) +{ + bpf_sk_storage_delete(&mptcp_rr_map, msk); +} + +int BPF_STRUCT_OPS(bpf_rr_get_subflow, struct mptcp_sock *msk, + struct mptcp_sched_data *data) +{ + struct mptcp_subflow_context *subflow; + struct mptcp_rr_storage *ptr; + struct sock *last_snd = NULL; + int nr = 0; + + ptr = bpf_sk_storage_get(&mptcp_rr_map, msk, 0, + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (!ptr) + return -1; + + last_snd = ptr->last_snd; + + for (int i = 0; i < data->subflows && i < MPTCP_SUBFLOWS_MAX; i++) { + subflow = bpf_mptcp_subflow_ctx_by_pos(data, i); + if (!last_snd || !subflow) + break; + + if (mptcp_subflow_tcp_sock(subflow) == last_snd) { + if (i + 1 == MPTCP_SUBFLOWS_MAX || + !bpf_mptcp_subflow_ctx_by_pos(data, i + 1)) + break; + + nr = i + 1; + break; + } + } + + subflow = bpf_mptcp_subflow_ctx_by_pos(data, nr); + if (!subflow) + return -1; + mptcp_subflow_set_scheduled(subflow, true); + ptr->last_snd = mptcp_subflow_tcp_sock(subflow); + return 0; +} + +SEC(".struct_ops") +struct mptcp_sched_ops rr = { + .init = (void *)mptcp_sched_rr_init, + .release = (void *)mptcp_sched_rr_release, + .get_subflow = (void *)bpf_rr_get_subflow, + .name = "bpf_rr", +}; |