Skip to content

Commit cc07e77

Browse files
committed
selftests/bpf: Test bpf_mprog query API via libbpf and raw syscall
Add a new test case which performs double query of the bpf_mprog through libbpf API, but also via raw bpf(2) syscall. This is testing to gather first the count and then in a subsequent probe the full information with the program array without clearing passed structs in between. # ./vmtest.sh -- ./test_progs -t tc_opts [...] ./test_progs -t tc_opts [ 1.398818] tsc: Refined TSC clocksource calibration: 3407.999 MHz [ 1.400263] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x311fd336761, max_idle_ns: 440795243819 ns [ 1.402734] clocksource: Switched to clocksource tsc [ 1.426639] bpf_testmod: loading out-of-tree module taints kernel. [ 1.428112] bpf_testmod: module verification failed: signature and/or required key missing - tainting kernel torvalds#252 tc_opts_after:OK torvalds#253 tc_opts_append:OK torvalds#254 tc_opts_basic:OK torvalds#255 tc_opts_before:OK torvalds#256 tc_opts_chain_classic:OK torvalds#257 tc_opts_chain_mixed:OK torvalds#258 tc_opts_delete_empty:OK torvalds#259 tc_opts_demixed:OK torvalds#260 tc_opts_detach:OK torvalds#261 tc_opts_detach_after:OK torvalds#262 tc_opts_detach_before:OK torvalds#263 tc_opts_dev_cleanup:OK torvalds#264 tc_opts_invalid:OK torvalds#265 tc_opts_max:OK torvalds#266 tc_opts_mixed:OK torvalds#267 tc_opts_prepend:OK torvalds#268 tc_opts_query:OK <--- (new test) torvalds#269 tc_opts_replace:OK torvalds#270 tc_opts_revision:OK Summary: 19/0 PASSED, 0 SKIPPED, 0 FAILED Signed-off-by: Daniel Borkmann <[email protected]>
1 parent 6bd059b commit cc07e77

File tree

1 file changed

+167
-0
lines changed
  • tools/testing/selftests/bpf/prog_tests

1 file changed

+167
-0
lines changed

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

+167
Original file line numberDiff line numberDiff line change
@@ -2462,3 +2462,170 @@ void serial_test_tc_opts_max(void)
24622462
test_tc_opts_max_target(BPF_TCX_INGRESS, BPF_F_AFTER, true);
24632463
test_tc_opts_max_target(BPF_TCX_EGRESS, BPF_F_AFTER, false);
24642464
}
2465+
2466+
static void test_tc_opts_query_target(int target)
2467+
{
2468+
const size_t attr_size = offsetofend(union bpf_attr, query);
2469+
LIBBPF_OPTS(bpf_prog_attach_opts, opta);
2470+
LIBBPF_OPTS(bpf_prog_detach_opts, optd);
2471+
LIBBPF_OPTS(bpf_prog_query_opts, optq);
2472+
__u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4;
2473+
struct test_tc_link *skel;
2474+
union bpf_attr attr;
2475+
__u32 prog_ids[5];
2476+
int err;
2477+
2478+
skel = test_tc_link__open_and_load();
2479+
if (!ASSERT_OK_PTR(skel, "skel_load"))
2480+
goto cleanup;
2481+
2482+
fd1 = bpf_program__fd(skel->progs.tc1);
2483+
fd2 = bpf_program__fd(skel->progs.tc2);
2484+
fd3 = bpf_program__fd(skel->progs.tc3);
2485+
fd4 = bpf_program__fd(skel->progs.tc4);
2486+
2487+
id1 = id_from_prog_fd(fd1);
2488+
id2 = id_from_prog_fd(fd2);
2489+
id3 = id_from_prog_fd(fd3);
2490+
id4 = id_from_prog_fd(fd4);
2491+
2492+
assert_mprog_count(target, 0);
2493+
2494+
LIBBPF_OPTS_RESET(opta,
2495+
.expected_revision = 1,
2496+
);
2497+
2498+
err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
2499+
if (!ASSERT_EQ(err, 0, "prog_attach"))
2500+
goto cleanup;
2501+
2502+
assert_mprog_count(target, 1);
2503+
2504+
LIBBPF_OPTS_RESET(opta,
2505+
.expected_revision = 2,
2506+
);
2507+
2508+
err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
2509+
if (!ASSERT_EQ(err, 0, "prog_attach"))
2510+
goto cleanup1;
2511+
2512+
assert_mprog_count(target, 2);
2513+
2514+
LIBBPF_OPTS_RESET(opta,
2515+
.expected_revision = 3,
2516+
);
2517+
2518+
err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
2519+
if (!ASSERT_EQ(err, 0, "prog_attach"))
2520+
goto cleanup2;
2521+
2522+
assert_mprog_count(target, 3);
2523+
2524+
LIBBPF_OPTS_RESET(opta,
2525+
.expected_revision = 4,
2526+
);
2527+
2528+
err = bpf_prog_attach_opts(fd4, loopback, target, &opta);
2529+
if (!ASSERT_EQ(err, 0, "prog_attach"))
2530+
goto cleanup3;
2531+
2532+
assert_mprog_count(target, 4);
2533+
2534+
/* Test 1: Double query via libbpf API */
2535+
err = bpf_prog_query_opts(loopback, target, &optq);
2536+
if (!ASSERT_OK(err, "prog_query"))
2537+
goto cleanup4;
2538+
2539+
ASSERT_EQ(optq.count, 4, "count");
2540+
ASSERT_EQ(optq.revision, 5, "revision");
2541+
ASSERT_EQ(optq.prog_ids, NULL, "prog_ids");
2542+
ASSERT_EQ(optq.link_ids, NULL, "link_ids");
2543+
2544+
memset(prog_ids, 0, sizeof(prog_ids));
2545+
optq.prog_ids = prog_ids;
2546+
2547+
err = bpf_prog_query_opts(loopback, target, &optq);
2548+
if (!ASSERT_OK(err, "prog_query"))
2549+
goto cleanup4;
2550+
2551+
ASSERT_EQ(optq.count, 4, "count");
2552+
ASSERT_EQ(optq.revision, 5, "revision");
2553+
ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
2554+
ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]");
2555+
ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]");
2556+
ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]");
2557+
ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
2558+
ASSERT_EQ(optq.link_ids, NULL, "link_ids");
2559+
2560+
/* Test 2: Double query via bpf_attr & bpf(2) directly */
2561+
memset(&attr, 0, attr_size);
2562+
attr.query.target_ifindex = loopback;
2563+
attr.query.attach_type = target;
2564+
2565+
err = syscall(__NR_bpf, BPF_PROG_QUERY, &attr, attr_size);
2566+
if (!ASSERT_OK(err, "prog_query"))
2567+
goto cleanup4;
2568+
2569+
ASSERT_EQ(attr.query.count, 4, "count");
2570+
ASSERT_EQ(attr.query.revision, 5, "revision");
2571+
ASSERT_EQ(attr.query.query_flags, 0, "query_flags");
2572+
ASSERT_EQ(attr.query.attach_flags, 0, "attach_flags");
2573+
ASSERT_EQ(attr.query.target_ifindex, loopback, "target_ifindex");
2574+
ASSERT_EQ(attr.query.attach_type, target, "attach_type");
2575+
ASSERT_EQ(attr.query.prog_ids, 0, "prog_ids");
2576+
ASSERT_EQ(attr.query.prog_attach_flags, 0, "prog_attach_flags");
2577+
ASSERT_EQ(attr.query.link_ids, 0, "link_ids");
2578+
ASSERT_EQ(attr.query.link_attach_flags, 0, "link_attach_flags");
2579+
2580+
memset(prog_ids, 0, sizeof(prog_ids));
2581+
attr.query.prog_ids = ptr_to_u64(prog_ids);
2582+
2583+
err = syscall(__NR_bpf, BPF_PROG_QUERY, &attr, attr_size);
2584+
if (!ASSERT_OK(err, "prog_query"))
2585+
goto cleanup4;
2586+
2587+
ASSERT_EQ(attr.query.count, 4, "count");
2588+
ASSERT_EQ(attr.query.revision, 5, "revision");
2589+
ASSERT_EQ(attr.query.query_flags, 0, "query_flags");
2590+
ASSERT_EQ(attr.query.attach_flags, 0, "attach_flags");
2591+
ASSERT_EQ(attr.query.target_ifindex, loopback, "target_ifindex");
2592+
ASSERT_EQ(attr.query.attach_type, target, "attach_type");
2593+
ASSERT_EQ(attr.query.prog_ids, ptr_to_u64(prog_ids), "prog_ids");
2594+
ASSERT_EQ(prog_ids[0], id1, "prog_ids[0]");
2595+
ASSERT_EQ(prog_ids[1], id2, "prog_ids[1]");
2596+
ASSERT_EQ(prog_ids[2], id3, "prog_ids[2]");
2597+
ASSERT_EQ(prog_ids[3], id4, "prog_ids[3]");
2598+
ASSERT_EQ(prog_ids[4], 0, "prog_ids[4]");
2599+
ASSERT_EQ(attr.query.prog_attach_flags, 0, "prog_attach_flags");
2600+
ASSERT_EQ(attr.query.link_ids, 0, "link_ids");
2601+
ASSERT_EQ(attr.query.link_attach_flags, 0, "link_attach_flags");
2602+
2603+
cleanup4:
2604+
err = bpf_prog_detach_opts(fd4, loopback, target, &optd);
2605+
ASSERT_OK(err, "prog_detach");
2606+
assert_mprog_count(target, 3);
2607+
2608+
cleanup3:
2609+
err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
2610+
ASSERT_OK(err, "prog_detach");
2611+
assert_mprog_count(target, 2);
2612+
2613+
cleanup2:
2614+
err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
2615+
ASSERT_OK(err, "prog_detach");
2616+
assert_mprog_count(target, 1);
2617+
2618+
cleanup1:
2619+
err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
2620+
ASSERT_OK(err, "prog_detach");
2621+
assert_mprog_count(target, 0);
2622+
2623+
cleanup:
2624+
test_tc_link__destroy(skel);
2625+
}
2626+
2627+
void serial_test_tc_opts_query(void)
2628+
{
2629+
test_tc_opts_query_target(BPF_TCX_INGRESS);
2630+
test_tc_opts_query_target(BPF_TCX_EGRESS);
2631+
}

0 commit comments

Comments
 (0)