From 335e596c472ab9ac89e28ba543073ce3f854765f Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Mon, 24 Feb 2025 13:23:24 +0100 Subject: [PATCH] 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 Reviewed-by: Mat Martineau Reviewed-by: Matthieu Baerts (NGI0) --- .../testing/selftests/bpf/prog_tests/mptcp.c | 15 ++++ .../selftests/bpf/progs/mptcp_bpf_rr.c | 78 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/mptcp_bpf_rr.c diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing/selftests/bpf/prog_tests/mptcp.c index 3794dedfbb1d..31e43538f266 100644 --- a/tools/testing/selftests/bpf/prog_tests/mptcp.c +++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c @@ -14,6 +14,7 @@ #include "mptcp_bpf_iters.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 ADDR_1 "10.0.1.1" @@ -696,6 +697,18 @@ static void test_bkup(void) mptcp_bpf_bkup__destroy(skel); } +static void test_rr(void) +{ + struct mptcp_bpf_rr *skel; + + skel = mptcp_bpf_rr__open_and_load(); + if (!ASSERT_OK_PTR(skel, "open_and_load: rr")) + return; + + test_bpf_sched(skel->obj, "rr", WITH_DATA, WITH_DATA); + mptcp_bpf_rr__destroy(skel); +} + void test_mptcp(void) { if (test__start_subtest("base")) @@ -712,4 +725,6 @@ void test_mptcp(void) test_first(); if (test__start_subtest("bkup")) test_bkup(); + if (test__start_subtest("rr")) + 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 000000000000..405e96c116d5 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_rr.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2022, SUSE. */ + +#include "mptcp_bpf.h" +#include + +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") +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") +void BPF_PROG(mptcp_sched_rr_release, struct mptcp_sock *msk) +{ + bpf_sk_storage_delete(&mptcp_rr_map, msk); +} + +SEC("struct_ops") +int BPF_PROG(bpf_rr_get_send, 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_send = (void *)bpf_rr_get_send, + .name = "bpf_rr", +};