Skip to content

Commit 06716e0

Browse files
jsitnickiAlexei Starovoitov
authored andcommitted
selftests/bpf: Extend test_flow_dissector to cover link creation
Extend the existing flow_dissector test case to run tests once using direct prog attachments, and then for the second time using indirect attachment via link. The intention is to exercises the newly added high-level API for attaching programs to network namespace with links (bpf_program__attach_netns). Signed-off-by: Jakub Sitnicki <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent b4b8a3b commit 06716e0

File tree

1 file changed

+82
-33
lines changed

1 file changed

+82
-33
lines changed

tools/testing/selftests/bpf/prog_tests/flow_dissector.c

Lines changed: 82 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ struct test {
103103

104104
#define VLAN_HLEN 4
105105

106+
static __u32 duration;
106107
struct test tests[] = {
107108
{
108109
.name = "ipv4",
@@ -474,11 +475,87 @@ static int init_prog_array(struct bpf_object *obj, struct bpf_map *prog_array)
474475
return 0;
475476
}
476477

478+
static void run_tests_skb_less(int tap_fd, struct bpf_map *keys)
479+
{
480+
int i, err, keys_fd;
481+
482+
keys_fd = bpf_map__fd(keys);
483+
if (CHECK(keys_fd < 0, "bpf_map__fd", "err %d\n", keys_fd))
484+
return;
485+
486+
for (i = 0; i < ARRAY_SIZE(tests); i++) {
487+
/* Keep in sync with 'flags' from eth_get_headlen. */
488+
__u32 eth_get_headlen_flags =
489+
BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG;
490+
struct bpf_prog_test_run_attr tattr = {};
491+
struct bpf_flow_keys flow_keys = {};
492+
__u32 key = (__u32)(tests[i].keys.sport) << 16 |
493+
tests[i].keys.dport;
494+
495+
/* For skb-less case we can't pass input flags; run
496+
* only the tests that have a matching set of flags.
497+
*/
498+
499+
if (tests[i].flags != eth_get_headlen_flags)
500+
continue;
501+
502+
err = tx_tap(tap_fd, &tests[i].pkt, sizeof(tests[i].pkt));
503+
CHECK(err < 0, "tx_tap", "err %d errno %d\n", err, errno);
504+
505+
err = bpf_map_lookup_elem(keys_fd, &key, &flow_keys);
506+
CHECK_ATTR(err, tests[i].name, "bpf_map_lookup_elem %d\n", err);
507+
508+
CHECK_ATTR(err, tests[i].name, "skb-less err %d\n", err);
509+
CHECK_FLOW_KEYS(tests[i].name, flow_keys, tests[i].keys);
510+
511+
err = bpf_map_delete_elem(keys_fd, &key);
512+
CHECK_ATTR(err, tests[i].name, "bpf_map_delete_elem %d\n", err);
513+
}
514+
}
515+
516+
static void test_skb_less_prog_attach(struct bpf_flow *skel, int tap_fd)
517+
{
518+
int err, prog_fd;
519+
520+
prog_fd = bpf_program__fd(skel->progs._dissect);
521+
if (CHECK(prog_fd < 0, "bpf_program__fd", "err %d\n", prog_fd))
522+
return;
523+
524+
err = bpf_prog_attach(prog_fd, 0, BPF_FLOW_DISSECTOR, 0);
525+
if (CHECK(err, "bpf_prog_attach", "err %d errno %d\n", err, errno))
526+
return;
527+
528+
run_tests_skb_less(tap_fd, skel->maps.last_dissection);
529+
530+
err = bpf_prog_detach(prog_fd, BPF_FLOW_DISSECTOR);
531+
CHECK(err, "bpf_prog_detach", "err %d errno %d\n", err, errno);
532+
}
533+
534+
static void test_skb_less_link_create(struct bpf_flow *skel, int tap_fd)
535+
{
536+
struct bpf_link *link;
537+
int err, net_fd;
538+
539+
net_fd = open("/proc/self/ns/net", O_RDONLY);
540+
if (CHECK(net_fd < 0, "open(/proc/self/ns/net)", "err %d\n", errno))
541+
return;
542+
543+
link = bpf_program__attach_netns(skel->progs._dissect, net_fd);
544+
if (CHECK(IS_ERR(link), "attach_netns", "err %ld\n", PTR_ERR(link)))
545+
goto out_close;
546+
547+
run_tests_skb_less(tap_fd, skel->maps.last_dissection);
548+
549+
err = bpf_link__destroy(link);
550+
CHECK(err, "bpf_link__destroy", "err %d\n", err);
551+
out_close:
552+
close(net_fd);
553+
}
554+
477555
void test_flow_dissector(void)
478556
{
479557
int i, err, prog_fd, keys_fd = -1, tap_fd;
480558
struct bpf_flow *skel;
481-
__u32 duration = 0;
482559

483560
skel = bpf_flow__open_and_load();
484561
if (CHECK(!skel, "skel", "failed to open/load skeleton\n"))
@@ -526,45 +603,17 @@ void test_flow_dissector(void)
526603
* via BPF map in this case.
527604
*/
528605

529-
err = bpf_prog_attach(prog_fd, 0, BPF_FLOW_DISSECTOR, 0);
530-
CHECK(err, "bpf_prog_attach", "err %d errno %d\n", err, errno);
531-
532606
tap_fd = create_tap("tap0");
533607
CHECK(tap_fd < 0, "create_tap", "tap_fd %d errno %d\n", tap_fd, errno);
534608
err = ifup("tap0");
535609
CHECK(err, "ifup", "err %d errno %d\n", err, errno);
536610

537-
for (i = 0; i < ARRAY_SIZE(tests); i++) {
538-
/* Keep in sync with 'flags' from eth_get_headlen. */
539-
__u32 eth_get_headlen_flags =
540-
BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG;
541-
struct bpf_prog_test_run_attr tattr = {};
542-
struct bpf_flow_keys flow_keys = {};
543-
__u32 key = (__u32)(tests[i].keys.sport) << 16 |
544-
tests[i].keys.dport;
545-
546-
/* For skb-less case we can't pass input flags; run
547-
* only the tests that have a matching set of flags.
548-
*/
549-
550-
if (tests[i].flags != eth_get_headlen_flags)
551-
continue;
552-
553-
err = tx_tap(tap_fd, &tests[i].pkt, sizeof(tests[i].pkt));
554-
CHECK(err < 0, "tx_tap", "err %d errno %d\n", err, errno);
555-
556-
err = bpf_map_lookup_elem(keys_fd, &key, &flow_keys);
557-
CHECK_ATTR(err, tests[i].name, "bpf_map_lookup_elem %d\n", err);
558-
559-
CHECK_ATTR(err, tests[i].name, "skb-less err %d\n", err);
560-
CHECK_FLOW_KEYS(tests[i].name, flow_keys, tests[i].keys);
561-
562-
err = bpf_map_delete_elem(keys_fd, &key);
563-
CHECK_ATTR(err, tests[i].name, "bpf_map_delete_elem %d\n", err);
564-
}
611+
/* Test direct prog attachment */
612+
test_skb_less_prog_attach(skel, tap_fd);
613+
/* Test indirect prog attachment via link */
614+
test_skb_less_link_create(skel, tap_fd);
565615

566616
close(tap_fd);
567-
bpf_prog_detach(prog_fd, BPF_FLOW_DISSECTOR);
568617
out_destroy_skel:
569618
bpf_flow__destroy(skel);
570619
}

0 commit comments

Comments
 (0)