Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: extend changes_pkt_data with cases w/o subprograms

Extend changes_pkt_data tests with test cases freplacing the main
program that does not have subprograms. Try four combinations when
both main program and replacement do and do not change packet data.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20241212070711.427443-2-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Eduard Zingerman and committed by
Alexei Starovoitov
04789af7 ac6542ad

+66 -22
+43 -12
tools/testing/selftests/bpf/prog_tests/changes_pkt_data.c
··· 10 10 fprintf(stdout, "VERIFIER LOG:\n=============\n%s=============\n", log); 11 11 } 12 12 13 - static void test_aux(const char *main_prog_name, const char *freplace_prog_name, bool expect_load) 13 + static void test_aux(const char *main_prog_name, 14 + const char *to_be_replaced, 15 + const char *replacement, 16 + bool expect_load) 14 17 { 15 18 struct changes_pkt_data_freplace *freplace = NULL; 16 19 struct bpf_program *freplace_prog = NULL; 20 + struct bpf_program *main_prog = NULL; 17 21 LIBBPF_OPTS(bpf_object_open_opts, opts); 18 22 struct changes_pkt_data *main = NULL; 19 23 char log[16*1024]; ··· 30 26 main = changes_pkt_data__open_opts(&opts); 31 27 if (!ASSERT_OK_PTR(main, "changes_pkt_data__open")) 32 28 goto out; 29 + main_prog = bpf_object__find_program_by_name(main->obj, main_prog_name); 30 + if (!ASSERT_OK_PTR(main_prog, "main_prog")) 31 + goto out; 32 + bpf_program__set_autoload(main_prog, true); 33 33 err = changes_pkt_data__load(main); 34 34 print_verifier_log(log); 35 35 if (!ASSERT_OK(err, "changes_pkt_data__load")) ··· 41 33 freplace = changes_pkt_data_freplace__open_opts(&opts); 42 34 if (!ASSERT_OK_PTR(freplace, "changes_pkt_data_freplace__open")) 43 35 goto out; 44 - freplace_prog = bpf_object__find_program_by_name(freplace->obj, freplace_prog_name); 36 + freplace_prog = bpf_object__find_program_by_name(freplace->obj, replacement); 45 37 if (!ASSERT_OK_PTR(freplace_prog, "freplace_prog")) 46 38 goto out; 47 39 bpf_program__set_autoload(freplace_prog, true); 48 40 bpf_program__set_autoattach(freplace_prog, true); 49 41 bpf_program__set_attach_target(freplace_prog, 50 - bpf_program__fd(main->progs.dummy), 51 - main_prog_name); 42 + bpf_program__fd(main_prog), 43 + to_be_replaced); 52 44 err = changes_pkt_data_freplace__load(freplace); 53 45 print_verifier_log(log); 54 46 if (expect_load) { ··· 70 62 * that either do or do not. It is only ok to freplace subprograms 71 63 * that do not change packet data with those that do not as well. 72 64 * The below tests check outcomes for each combination of such freplace. 65 + * Also test a case when main subprogram itself is replaced and is a single 66 + * subprogram in a program. 73 67 */ 74 68 void test_changes_pkt_data_freplace(void) 75 69 { 76 - if (test__start_subtest("changes_with_changes")) 77 - test_aux("changes_pkt_data", "changes_pkt_data", true); 78 - if (test__start_subtest("changes_with_doesnt_change")) 79 - test_aux("changes_pkt_data", "does_not_change_pkt_data", true); 80 - if (test__start_subtest("doesnt_change_with_changes")) 81 - test_aux("does_not_change_pkt_data", "changes_pkt_data", false); 82 - if (test__start_subtest("doesnt_change_with_doesnt_change")) 83 - test_aux("does_not_change_pkt_data", "does_not_change_pkt_data", true); 70 + struct { 71 + const char *main; 72 + const char *to_be_replaced; 73 + bool changes; 74 + } mains[] = { 75 + { "main_with_subprogs", "changes_pkt_data", true }, 76 + { "main_with_subprogs", "does_not_change_pkt_data", false }, 77 + { "main_changes", "main_changes", true }, 78 + { "main_does_not_change", "main_does_not_change", false }, 79 + }; 80 + struct { 81 + const char *func; 82 + bool changes; 83 + } replacements[] = { 84 + { "changes_pkt_data", true }, 85 + { "does_not_change_pkt_data", false } 86 + }; 87 + char buf[64]; 88 + 89 + for (int i = 0; i < ARRAY_SIZE(mains); ++i) { 90 + for (int j = 0; j < ARRAY_SIZE(replacements); ++j) { 91 + snprintf(buf, sizeof(buf), "%s_with_%s", 92 + mains[i].to_be_replaced, replacements[j].func); 93 + if (!test__start_subtest(buf)) 94 + continue; 95 + test_aux(mains[i].main, mains[i].to_be_replaced, replacements[j].func, 96 + mains[i].changes || !replacements[j].changes); 97 + } 98 + } 84 99 }
+20 -7
tools/testing/selftests/bpf/progs/changes_pkt_data.c
··· 4 4 #include <bpf/bpf_helpers.h> 5 5 6 6 __noinline 7 - long changes_pkt_data(struct __sk_buff *sk, __u32 len) 7 + long changes_pkt_data(struct __sk_buff *sk) 8 8 { 9 - return bpf_skb_pull_data(sk, len); 9 + return bpf_skb_pull_data(sk, 0); 10 10 } 11 11 12 12 __noinline __weak 13 - long does_not_change_pkt_data(struct __sk_buff *sk, __u32 len) 13 + long does_not_change_pkt_data(struct __sk_buff *sk) 14 14 { 15 15 return 0; 16 16 } 17 17 18 - SEC("tc") 19 - int dummy(struct __sk_buff *sk) 18 + SEC("?tc") 19 + int main_with_subprogs(struct __sk_buff *sk) 20 20 { 21 - changes_pkt_data(sk, 0); 22 - does_not_change_pkt_data(sk, 0); 21 + changes_pkt_data(sk); 22 + does_not_change_pkt_data(sk); 23 + return 0; 24 + } 25 + 26 + SEC("?tc") 27 + int main_changes(struct __sk_buff *sk) 28 + { 29 + bpf_skb_pull_data(sk, 0); 30 + return 0; 31 + } 32 + 33 + SEC("?tc") 34 + int main_does_not_change(struct __sk_buff *sk) 35 + { 23 36 return 0; 24 37 } 25 38
+3 -3
tools/testing/selftests/bpf/progs/changes_pkt_data_freplace.c
··· 4 4 #include <bpf/bpf_helpers.h> 5 5 6 6 SEC("?freplace") 7 - long changes_pkt_data(struct __sk_buff *sk, __u32 len) 7 + long changes_pkt_data(struct __sk_buff *sk) 8 8 { 9 - return bpf_skb_pull_data(sk, len); 9 + return bpf_skb_pull_data(sk, 0); 10 10 } 11 11 12 12 SEC("?freplace") 13 - long does_not_change_pkt_data(struct __sk_buff *sk, __u32 len) 13 + long does_not_change_pkt_data(struct __sk_buff *sk) 14 14 { 15 15 return 0; 16 16 }