Message ID | 20230214221718.503964-8-kuifeng@meta.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | Transit between BPF TCP congestion controls. | expand |
On Tue, Feb 14, 2023 at 2:17 PM Kui-Feng Lee <kuifeng@meta.com> wrote: > > Create a pair of sockets that utilize the congestion control algorithm > under a particular name. Then switch up this congestion control > algorithm to another implementation and check whether newly created > connections using the same cc name now run the new implementation. > > Signed-off-by: Kui-Feng Lee <kuifeng@meta.com> > --- > .../selftests/bpf/prog_tests/bpf_tcp_ca.c | 48 ++++++++++++ > .../selftests/bpf/progs/tcp_ca_update.c | 75 +++++++++++++++++++ > 2 files changed, 123 insertions(+) > create mode 100644 tools/testing/selftests/bpf/progs/tcp_ca_update.c > [...] > diff --git a/tools/testing/selftests/bpf/progs/tcp_ca_update.c b/tools/testing/selftests/bpf/progs/tcp_ca_update.c > new file mode 100644 > index 000000000000..cf51fe54ac01 > --- /dev/null > +++ b/tools/testing/selftests/bpf/progs/tcp_ca_update.c > @@ -0,0 +1,75 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include "vmlinux.h" > + > +#include <bpf/bpf_helpers.h> > +#include <bpf/bpf_tracing.h> > + > +char _license[] SEC("license") = "GPL"; > + > +int ca1_cnt = 0; > +int ca2_cnt = 0; > + > +#define USEC_PER_SEC 1000000UL > + > +#define min(a, b) ((a) < (b) ? (a) : (b)) > + > +static inline struct tcp_sock *tcp_sk(const struct sock *sk) > +{ > + return (struct tcp_sock *)sk; > +} > + > +SEC("struct_ops/ca_update_init") > +void BPF_PROG(ca_update_init, struct sock *sk) > +{ > +#ifdef ENABLE_ATOMICS_TESTS it's been 2 years since atomics were added to Clang, I think it's fine to just assume atomic operations are supported and not do the ENABLE_ATOMICS_TEST (and I'd clean up ENABLE_ATOMICS_TESTS now as well) > + __sync_bool_compare_and_swap(&sk->sk_pacing_status, SK_PACING_NONE, > + SK_PACING_NEEDED); > +#else > + sk->sk_pacing_status = SK_PACING_NEEDED; > +#endif > +} > + > +SEC("struct_ops/ca_update_1_cong_control") > +void BPF_PROG(ca_update_1_cong_control, struct sock *sk, > + const struct rate_sample *rs) > +{ > + ca1_cnt++; > +} > + > +SEC("struct_ops/ca_update_2_cong_control") > +void BPF_PROG(ca_update_2_cong_control, struct sock *sk, > + const struct rate_sample *rs) > +{ > + ca2_cnt++; > +} > + > +SEC("struct_ops/ca_update_ssthresh") > +__u32 BPF_PROG(ca_update_ssthresh, struct sock *sk) > +{ > + return tcp_sk(sk)->snd_ssthresh; > +} > + > +SEC("struct_ops/ca_update_undo_cwnd") > +__u32 BPF_PROG(ca_update_undo_cwnd, struct sock *sk) > +{ > + return tcp_sk(sk)->snd_cwnd; > +} > + > +SEC(".struct_ops") > +struct tcp_congestion_ops ca_update_1 = { > + .init = (void *)ca_update_init, > + .cong_control = (void *)ca_update_1_cong_control, > + .ssthresh = (void *)ca_update_ssthresh, > + .undo_cwnd = (void *)ca_update_undo_cwnd, > + .name = "tcp_ca_update", > +}; > + > +SEC(".struct_ops") > +struct tcp_congestion_ops ca_update_2 = { > + .init = (void *)ca_update_init, > + .cong_control = (void *)ca_update_2_cong_control, > + .ssthresh = (void *)ca_update_ssthresh, > + .undo_cwnd = (void *)ca_update_undo_cwnd, > + .name = "tcp_ca_update", > +}; > -- > 2.30.2 >
On 2/16/23 14:50, Andrii Nakryiko wrote: > On Tue, Feb 14, 2023 at 2:17 PM Kui-Feng Lee <kuifeng@meta.com> wrote: >> >> Create a pair of sockets that utilize the congestion control algorithm >> under a particular name. Then switch up this congestion control >> algorithm to another implementation and check whether newly created >> connections using the same cc name now run the new implementation. >> >> Signed-off-by: Kui-Feng Lee <kuifeng@meta.com> >> --- >> .../selftests/bpf/prog_tests/bpf_tcp_ca.c | 48 ++++++++++++ >> .../selftests/bpf/progs/tcp_ca_update.c | 75 +++++++++++++++++++ >> 2 files changed, 123 insertions(+) >> create mode 100644 tools/testing/selftests/bpf/progs/tcp_ca_update.c >> > > [...] > >> diff --git a/tools/testing/selftests/bpf/progs/tcp_ca_update.c b/tools/testing/selftests/bpf/progs/tcp_ca_update.c >> new file mode 100644 >> index 000000000000..cf51fe54ac01 >> --- /dev/null >> +++ b/tools/testing/selftests/bpf/progs/tcp_ca_update.c >> @@ -0,0 +1,75 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> + >> +#include "vmlinux.h" >> + >> +#include <bpf/bpf_helpers.h> >> +#include <bpf/bpf_tracing.h> >> + >> +char _license[] SEC("license") = "GPL"; >> + >> +int ca1_cnt = 0; >> +int ca2_cnt = 0; >> + >> +#define USEC_PER_SEC 1000000UL >> + >> +#define min(a, b) ((a) < (b) ? (a) : (b)) >> + >> +static inline struct tcp_sock *tcp_sk(const struct sock *sk) >> +{ >> + return (struct tcp_sock *)sk; >> +} >> + >> +SEC("struct_ops/ca_update_init") >> +void BPF_PROG(ca_update_init, struct sock *sk) >> +{ >> +#ifdef ENABLE_ATOMICS_TESTS > > it's been 2 years since atomics were added to Clang, I think it's fine > to just assume atomic operations are supported and not do the > ENABLE_ATOMICS_TEST (and I'd clean up ENABLE_ATOMICS_TESTS now as > well) Sure! > >> + __sync_bool_compare_and_swap(&sk->sk_pacing_status, SK_PACING_NONE, >> + SK_PACING_NEEDED); >> +#else >> + sk->sk_pacing_status = SK_PACING_NEEDED; >> +#endif >> +} >> + >> +SEC("struct_ops/ca_update_1_cong_control") >> +void BPF_PROG(ca_update_1_cong_control, struct sock *sk, >> + const struct rate_sample *rs) >> +{ >> + ca1_cnt++; >> +} >> + >> +SEC("struct_ops/ca_update_2_cong_control") >> +void BPF_PROG(ca_update_2_cong_control, struct sock *sk, >> + const struct rate_sample *rs) >> +{ >> + ca2_cnt++; >> +} >> + >> +SEC("struct_ops/ca_update_ssthresh") >> +__u32 BPF_PROG(ca_update_ssthresh, struct sock *sk) >> +{ >> + return tcp_sk(sk)->snd_ssthresh; >> +} >> + >> +SEC("struct_ops/ca_update_undo_cwnd") >> +__u32 BPF_PROG(ca_update_undo_cwnd, struct sock *sk) >> +{ >> + return tcp_sk(sk)->snd_cwnd; >> +} >> + >> +SEC(".struct_ops") >> +struct tcp_congestion_ops ca_update_1 = { >> + .init = (void *)ca_update_init, >> + .cong_control = (void *)ca_update_1_cong_control, >> + .ssthresh = (void *)ca_update_ssthresh, >> + .undo_cwnd = (void *)ca_update_undo_cwnd, >> + .name = "tcp_ca_update", >> +}; >> + >> +SEC(".struct_ops") >> +struct tcp_congestion_ops ca_update_2 = { >> + .init = (void *)ca_update_init, >> + .cong_control = (void *)ca_update_2_cong_control, >> + .ssthresh = (void *)ca_update_ssthresh, >> + .undo_cwnd = (void *)ca_update_undo_cwnd, >> + .name = "tcp_ca_update", >> +}; >> -- >> 2.30.2 >>
diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c index e980188d4124..89477e4c9a24 100644 --- a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c +++ b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c @@ -8,6 +8,7 @@ #include "bpf_dctcp.skel.h" #include "bpf_cubic.skel.h" #include "bpf_tcp_nogpl.skel.h" +#include "tcp_ca_update.skel.h" #include "bpf_dctcp_release.skel.h" #include "tcp_ca_write_sk_pacing.skel.h" #include "tcp_ca_incompl_cong_ops.skel.h" @@ -381,6 +382,51 @@ static void test_unsupp_cong_op(void) libbpf_set_print(old_print_fn); } +static void test_update_ca(void) +{ + struct tcp_ca_update *skel; + struct bpf_link *link; + int saved_ca1_cnt; + int err; + + skel = tcp_ca_update__open(); + if (!ASSERT_OK_PTR(skel, "open")) + return; + + err = bpf_map__set_map_flags(skel->maps.ca_update_1, + bpf_map__map_flags(skel->maps.ca_update_1) | BPF_F_LINK); + if (!ASSERT_OK(err, "set_map_flags_1")) + return; + + err = bpf_map__set_map_flags(skel->maps.ca_update_2, + bpf_map__map_flags(skel->maps.ca_update_2) | BPF_F_LINK); + if (!ASSERT_OK(err, "set_map_flags_2")) + return; + + err = tcp_ca_update__load(skel); + if (!ASSERT_OK(err, "load")) { + tcp_ca_update__destroy(skel); + return; + } + + link = bpf_map__attach_struct_ops(skel->maps.ca_update_1); + ASSERT_OK_PTR(link, "attach_struct_ops"); + + do_test("tcp_ca_update", NULL); + saved_ca1_cnt = skel->bss->ca1_cnt; + ASSERT_GT(saved_ca1_cnt, 0, "ca1_ca1_cnt"); + + err = bpf_link__update_struct_ops(link, skel->maps.ca_update_2); + ASSERT_OK(err, "update_struct_ops"); + + do_test("tcp_ca_update", NULL); + ASSERT_EQ(skel->bss->ca1_cnt, saved_ca1_cnt, "ca2_ca1_cnt"); + ASSERT_GT(skel->bss->ca2_cnt, 0, "ca2_ca2_cnt"); + + bpf_link__destroy(link); + tcp_ca_update__destroy(skel); +} + void test_bpf_tcp_ca(void) { if (test__start_subtest("dctcp")) @@ -399,4 +445,6 @@ void test_bpf_tcp_ca(void) test_incompl_cong_ops(); if (test__start_subtest("unsupp_cong_op")) test_unsupp_cong_op(); + if (test__start_subtest("update_ca")) + test_update_ca(); } diff --git a/tools/testing/selftests/bpf/progs/tcp_ca_update.c b/tools/testing/selftests/bpf/progs/tcp_ca_update.c new file mode 100644 index 000000000000..cf51fe54ac01 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/tcp_ca_update.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "vmlinux.h" + +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> + +char _license[] SEC("license") = "GPL"; + +int ca1_cnt = 0; +int ca2_cnt = 0; + +#define USEC_PER_SEC 1000000UL + +#define min(a, b) ((a) < (b) ? (a) : (b)) + +static inline struct tcp_sock *tcp_sk(const struct sock *sk) +{ + return (struct tcp_sock *)sk; +} + +SEC("struct_ops/ca_update_init") +void BPF_PROG(ca_update_init, struct sock *sk) +{ +#ifdef ENABLE_ATOMICS_TESTS + __sync_bool_compare_and_swap(&sk->sk_pacing_status, SK_PACING_NONE, + SK_PACING_NEEDED); +#else + sk->sk_pacing_status = SK_PACING_NEEDED; +#endif +} + +SEC("struct_ops/ca_update_1_cong_control") +void BPF_PROG(ca_update_1_cong_control, struct sock *sk, + const struct rate_sample *rs) +{ + ca1_cnt++; +} + +SEC("struct_ops/ca_update_2_cong_control") +void BPF_PROG(ca_update_2_cong_control, struct sock *sk, + const struct rate_sample *rs) +{ + ca2_cnt++; +} + +SEC("struct_ops/ca_update_ssthresh") +__u32 BPF_PROG(ca_update_ssthresh, struct sock *sk) +{ + return tcp_sk(sk)->snd_ssthresh; +} + +SEC("struct_ops/ca_update_undo_cwnd") +__u32 BPF_PROG(ca_update_undo_cwnd, struct sock *sk) +{ + return tcp_sk(sk)->snd_cwnd; +} + +SEC(".struct_ops") +struct tcp_congestion_ops ca_update_1 = { + .init = (void *)ca_update_init, + .cong_control = (void *)ca_update_1_cong_control, + .ssthresh = (void *)ca_update_ssthresh, + .undo_cwnd = (void *)ca_update_undo_cwnd, + .name = "tcp_ca_update", +}; + +SEC(".struct_ops") +struct tcp_congestion_ops ca_update_2 = { + .init = (void *)ca_update_init, + .cong_control = (void *)ca_update_2_cong_control, + .ssthresh = (void *)ca_update_ssthresh, + .undo_cwnd = (void *)ca_update_undo_cwnd, + .name = "tcp_ca_update", +};
Create a pair of sockets that utilize the congestion control algorithm under a particular name. Then switch up this congestion control algorithm to another implementation and check whether newly created connections using the same cc name now run the new implementation. Signed-off-by: Kui-Feng Lee <kuifeng@meta.com> --- .../selftests/bpf/prog_tests/bpf_tcp_ca.c | 48 ++++++++++++ .../selftests/bpf/progs/tcp_ca_update.c | 75 +++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/tcp_ca_update.c