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

selftests/bpf: Add some tests with new bpf_program__attach_sockmap() APIs

Add a few more tests in sockmap_basic.c and sockmap_listen.c to
test bpf_link based APIs for SK_MSG and SK_SKB programs.
Link attach/detach/update are all tested.

All tests are passed.

Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Reviewed-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20240410043547.3738448-1-yonghong.song@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Yonghong Song and committed by
Alexei Starovoitov
8ba218e6 a15d58b2

+206 -2
+133
tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
··· 131 131 test_skmsg_load_helpers__destroy(skel); 132 132 } 133 133 134 + static void test_skmsg_helpers_with_link(enum bpf_map_type map_type) 135 + { 136 + struct bpf_program *prog, *prog_clone, *prog_clone2; 137 + DECLARE_LIBBPF_OPTS(bpf_link_update_opts, opts); 138 + struct test_skmsg_load_helpers *skel; 139 + struct bpf_link *link, *link2; 140 + int err, map; 141 + 142 + skel = test_skmsg_load_helpers__open_and_load(); 143 + if (!ASSERT_OK_PTR(skel, "test_skmsg_load_helpers__open_and_load")) 144 + return; 145 + 146 + prog = skel->progs.prog_msg_verdict; 147 + prog_clone = skel->progs.prog_msg_verdict_clone; 148 + prog_clone2 = skel->progs.prog_msg_verdict_clone2; 149 + map = bpf_map__fd(skel->maps.sock_map); 150 + 151 + link = bpf_program__attach_sockmap(prog, map); 152 + if (!ASSERT_OK_PTR(link, "bpf_program__attach_sockmap")) 153 + goto out; 154 + 155 + /* Fail since bpf_link for the same prog has been created. */ 156 + err = bpf_prog_attach(bpf_program__fd(prog), map, BPF_SK_MSG_VERDICT, 0); 157 + if (!ASSERT_ERR(err, "bpf_prog_attach")) 158 + goto out; 159 + 160 + /* Fail since bpf_link for the same prog type has been created. */ 161 + link2 = bpf_program__attach_sockmap(prog_clone, map); 162 + if (!ASSERT_ERR_PTR(link2, "bpf_program__attach_sockmap")) { 163 + bpf_link__detach(link2); 164 + goto out; 165 + } 166 + 167 + err = bpf_link__update_program(link, prog_clone); 168 + if (!ASSERT_OK(err, "bpf_link__update_program")) 169 + goto out; 170 + 171 + /* Fail since a prog with different type attempts to do update. */ 172 + err = bpf_link__update_program(link, skel->progs.prog_skb_verdict); 173 + if (!ASSERT_ERR(err, "bpf_link__update_program")) 174 + goto out; 175 + 176 + /* Fail since the old prog does not match the one in the kernel. */ 177 + opts.old_prog_fd = bpf_program__fd(prog_clone2); 178 + opts.flags = BPF_F_REPLACE; 179 + err = bpf_link_update(bpf_link__fd(link), bpf_program__fd(prog), &opts); 180 + if (!ASSERT_ERR(err, "bpf_link_update")) 181 + goto out; 182 + 183 + opts.old_prog_fd = bpf_program__fd(prog_clone); 184 + opts.flags = BPF_F_REPLACE; 185 + err = bpf_link_update(bpf_link__fd(link), bpf_program__fd(prog), &opts); 186 + if (!ASSERT_OK(err, "bpf_link_update")) 187 + goto out; 188 + out: 189 + bpf_link__detach(link); 190 + test_skmsg_load_helpers__destroy(skel); 191 + } 192 + 134 193 static void test_sockmap_update(enum bpf_map_type map_type) 135 194 { 136 195 int err, prog, src; ··· 351 292 ASSERT_EQ(err, -EBUSY, "prog_attach_fail"); 352 293 353 294 err = bpf_prog_detach2(verdict, map, first); 295 + if (!ASSERT_OK(err, "bpf_prog_detach2")) 296 + goto out; 297 + out: 298 + test_sockmap_skb_verdict_attach__destroy(skel); 299 + } 300 + 301 + static void test_sockmap_skb_verdict_attach_with_link(void) 302 + { 303 + struct test_sockmap_skb_verdict_attach *skel; 304 + struct bpf_program *prog; 305 + struct bpf_link *link; 306 + int err, map; 307 + 308 + skel = test_sockmap_skb_verdict_attach__open_and_load(); 309 + if (!ASSERT_OK_PTR(skel, "open_and_load")) 310 + return; 311 + prog = skel->progs.prog_skb_verdict; 312 + map = bpf_map__fd(skel->maps.sock_map); 313 + link = bpf_program__attach_sockmap(prog, map); 314 + if (!ASSERT_OK_PTR(link, "bpf_program__attach_sockmap")) 315 + goto out; 316 + 317 + bpf_link__detach(link); 318 + 319 + err = bpf_prog_attach(bpf_program__fd(prog), map, BPF_SK_SKB_STREAM_VERDICT, 0); 320 + if (!ASSERT_OK(err, "bpf_prog_attach")) 321 + goto out; 322 + 323 + /* Fail since attaching with the same prog/map has been done. */ 324 + link = bpf_program__attach_sockmap(prog, map); 325 + if (!ASSERT_ERR_PTR(link, "bpf_program__attach_sockmap")) 326 + bpf_link__detach(link); 327 + 328 + err = bpf_prog_detach2(bpf_program__fd(prog), map, BPF_SK_SKB_STREAM_VERDICT); 354 329 if (!ASSERT_OK(err, "bpf_prog_detach2")) 355 330 goto out; 356 331 out: ··· 622 529 test_sockmap_skb_verdict_peek_helper(map); 623 530 624 531 out: 532 + test_sockmap_pass_prog__destroy(pass); 533 + } 534 + 535 + static void test_sockmap_skb_verdict_peek_with_link(void) 536 + { 537 + struct test_sockmap_pass_prog *pass; 538 + struct bpf_program *prog; 539 + struct bpf_link *link; 540 + int err, map; 541 + 542 + pass = test_sockmap_pass_prog__open_and_load(); 543 + if (!ASSERT_OK_PTR(pass, "open_and_load")) 544 + return; 545 + prog = pass->progs.prog_skb_verdict; 546 + map = bpf_map__fd(pass->maps.sock_map_rx); 547 + link = bpf_program__attach_sockmap(prog, map); 548 + if (!ASSERT_OK_PTR(link, "bpf_program__attach_sockmap")) 549 + goto out; 550 + 551 + err = bpf_link__update_program(link, pass->progs.prog_skb_verdict_clone); 552 + if (!ASSERT_OK(err, "bpf_link__update_program")) 553 + goto out; 554 + 555 + /* Fail since a prog with different attach type attempts to do update. */ 556 + err = bpf_link__update_program(link, pass->progs.prog_skb_parser); 557 + if (!ASSERT_ERR(err, "bpf_link__update_program")) 558 + goto out; 559 + 560 + test_sockmap_skb_verdict_peek_helper(map); 561 + ASSERT_EQ(pass->bss->clone_called, 1, "clone_called"); 562 + out: 563 + bpf_link__detach(link); 625 564 test_sockmap_pass_prog__destroy(pass); 626 565 } 627 566 ··· 921 796 test_sockmap_skb_verdict_attach(BPF_SK_SKB_STREAM_VERDICT, 922 797 BPF_SK_SKB_VERDICT); 923 798 } 799 + if (test__start_subtest("sockmap skb_verdict attach_with_link")) 800 + test_sockmap_skb_verdict_attach_with_link(); 924 801 if (test__start_subtest("sockmap msg_verdict progs query")) 925 802 test_sockmap_progs_query(BPF_SK_MSG_VERDICT); 926 803 if (test__start_subtest("sockmap stream_parser progs query")) ··· 939 812 test_sockmap_skb_verdict_fionread(false); 940 813 if (test__start_subtest("sockmap skb_verdict msg_f_peek")) 941 814 test_sockmap_skb_verdict_peek(); 815 + if (test__start_subtest("sockmap skb_verdict msg_f_peek with link")) 816 + test_sockmap_skb_verdict_peek_with_link(); 942 817 if (test__start_subtest("sockmap unconnected af_unix")) 943 818 test_sockmap_unconnected_unix(); 944 819 if (test__start_subtest("sockmap one socket to many map entries")) ··· 949 820 test_sockmap_many_maps(); 950 821 if (test__start_subtest("sockmap same socket replace")) 951 822 test_sockmap_same_sock(); 823 + if (test__start_subtest("sockmap sk_msg attach sockmap helpers with link")) 824 + test_skmsg_helpers_with_link(BPF_MAP_TYPE_SOCKMAP); 825 + if (test__start_subtest("sockhash sk_msg attach sockhash helpers with link")) 826 + test_skmsg_helpers_with_link(BPF_MAP_TYPE_SOCKHASH); 952 827 }
+38
tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
··· 767 767 xbpf_prog_detach2(verdict, sock_map, BPF_SK_MSG_VERDICT); 768 768 } 769 769 770 + static void test_msg_redir_to_connected_with_link(struct test_sockmap_listen *skel, 771 + struct bpf_map *inner_map, int family, 772 + int sotype) 773 + { 774 + int prog_msg_verdict = bpf_program__fd(skel->progs.prog_msg_verdict); 775 + int verdict_map = bpf_map__fd(skel->maps.verdict_map); 776 + int sock_map = bpf_map__fd(inner_map); 777 + int link_fd; 778 + 779 + link_fd = bpf_link_create(prog_msg_verdict, sock_map, BPF_SK_MSG_VERDICT, NULL); 780 + if (!ASSERT_GE(link_fd, 0, "bpf_link_create")) 781 + return; 782 + 783 + redir_to_connected(family, sotype, sock_map, verdict_map, REDIR_EGRESS); 784 + 785 + close(link_fd); 786 + } 787 + 770 788 static void redir_to_listening(int family, int sotype, int sock_mapfd, 771 789 int verd_mapfd, enum redir_mode mode) 772 790 { ··· 885 867 redir_to_listening(family, sotype, sock_map, verdict_map, REDIR_EGRESS); 886 868 887 869 xbpf_prog_detach2(verdict, sock_map, BPF_SK_MSG_VERDICT); 870 + } 871 + 872 + static void test_msg_redir_to_listening_with_link(struct test_sockmap_listen *skel, 873 + struct bpf_map *inner_map, int family, 874 + int sotype) 875 + { 876 + struct bpf_program *verdict = skel->progs.prog_msg_verdict; 877 + int verdict_map = bpf_map__fd(skel->maps.verdict_map); 878 + int sock_map = bpf_map__fd(inner_map); 879 + struct bpf_link *link; 880 + 881 + link = bpf_program__attach_sockmap(verdict, sock_map); 882 + if (!ASSERT_OK_PTR(link, "bpf_program__attach_sockmap")) 883 + return; 884 + 885 + redir_to_listening(family, sotype, sock_map, verdict_map, REDIR_EGRESS); 886 + 887 + bpf_link__detach(link); 888 888 } 889 889 890 890 static void redir_partial(int family, int sotype, int sock_map, int parser_map) ··· 1352 1316 TEST(test_skb_redir_to_listening), 1353 1317 TEST(test_skb_redir_partial), 1354 1318 TEST(test_msg_redir_to_connected), 1319 + TEST(test_msg_redir_to_connected_with_link), 1355 1320 TEST(test_msg_redir_to_listening), 1321 + TEST(test_msg_redir_to_listening_with_link), 1356 1322 }; 1357 1323 const char *family_name, *map_name; 1358 1324 const struct redir_test *t;
+18
tools/testing/selftests/bpf/progs/test_skmsg_load_helpers.c
··· 49 49 return prog_msg_verdict_common(msg); 50 50 } 51 51 52 + SEC("sk_msg") 53 + int prog_msg_verdict_clone(struct sk_msg_md *msg) 54 + { 55 + return prog_msg_verdict_common(msg); 56 + } 57 + 58 + SEC("sk_msg") 59 + int prog_msg_verdict_clone2(struct sk_msg_md *msg) 60 + { 61 + return prog_msg_verdict_common(msg); 62 + } 63 + 64 + SEC("sk_skb/stream_verdict") 65 + int prog_skb_verdict(struct __sk_buff *skb) 66 + { 67 + return SK_PASS; 68 + } 69 + 52 70 char _license[] SEC("license") = "GPL";
+16 -1
tools/testing/selftests/bpf/progs/test_sockmap_pass_prog.c
··· 23 23 __type(value, int); 24 24 } sock_map_msg SEC(".maps"); 25 25 26 - SEC("sk_skb") 26 + SEC("sk_skb/stream_verdict") 27 27 int prog_skb_verdict(struct __sk_buff *skb) 28 + { 29 + return SK_PASS; 30 + } 31 + 32 + int clone_called; 33 + 34 + SEC("sk_skb/stream_verdict") 35 + int prog_skb_verdict_clone(struct __sk_buff *skb) 36 + { 37 + clone_called = 1; 38 + return SK_PASS; 39 + } 40 + 41 + SEC("sk_skb/stream_parser") 42 + int prog_skb_parser(struct __sk_buff *skb) 28 43 { 29 44 return SK_PASS; 30 45 }
+1 -1
tools/testing/selftests/bpf/progs/test_sockmap_skb_verdict_attach.c
··· 9 9 __type(value, __u64); 10 10 } sock_map SEC(".maps"); 11 11 12 - SEC("sk_skb") 12 + SEC("sk_skb/verdict") 13 13 int prog_skb_verdict(struct __sk_buff *skb) 14 14 { 15 15 return SK_DROP;