aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeliang Tang <tanggeliang@kylinos.cn>2024-04-20 09:25:15 +0000
committerMatthieu Baerts (NGI0) <matttbe@kernel.org>2024-04-20 09:25:15 +0000
commit88c98e672248ac9210f7d8e5619ac5978dbee074 (patch)
tree6df3b3889bea76170fc900217a5ef58619dd5a48
parente6ac58e01630d64992e56cac58d3d2efbfc4023a (diff)
downloadmptcp_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.h5
-rw-r--r--tools/testing/selftests/bpf/prog_tests/mptcp.c3
-rw-r--r--tools/testing/selftests/bpf/progs/mptcp_bpf_rr.c77
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",
+};