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

selftests/bpf: Add a test for using a cpumap from an freplace-to-XDP program

This adds a simple test for inserting an XDP program into a cpumap that is
"owned" by an XDP program that was loaded as PROG_TYPE_EXT (as libxdp
does). Prior to the kernel fix this would fail because the map type
ownership would be set to PROG_TYPE_EXT instead of being resolved to
PROG_TYPE_XDP.

v5:
- Fix a few nits from Andrii, add his ACK
v4:
- Use skeletons for selftest
v3:
- Update comment to better explain the cause
- Add Yonghong's ACK

Acked-by: Yonghong Song <yhs@fb.com>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://lore.kernel.org/r/20221214230254.790066-2-toke@redhat.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>

authored by

Toke Høiland-Jørgensen and committed by
Martin KaFai Lau
f506439e 1c123c56

+72
+48
tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
··· 4 4 #include <network_helpers.h> 5 5 #include <bpf/btf.h> 6 6 #include "bind4_prog.skel.h" 7 + #include "freplace_progmap.skel.h" 8 + #include "xdp_dummy.skel.h" 7 9 8 10 typedef int (*test_cb)(struct bpf_object *obj); 9 11 ··· 502 500 bind4_prog__destroy(skel); 503 501 } 504 502 503 + static void test_func_replace_progmap(void) 504 + { 505 + struct bpf_cpumap_val value = { .qsize = 1 }; 506 + struct freplace_progmap *skel = NULL; 507 + struct xdp_dummy *tgt_skel = NULL; 508 + __u32 key = 0; 509 + int err; 510 + 511 + skel = freplace_progmap__open(); 512 + if (!ASSERT_OK_PTR(skel, "prog_open")) 513 + return; 514 + 515 + tgt_skel = xdp_dummy__open_and_load(); 516 + if (!ASSERT_OK_PTR(tgt_skel, "tgt_prog_load")) 517 + goto out; 518 + 519 + err = bpf_program__set_attach_target(skel->progs.xdp_cpumap_prog, 520 + bpf_program__fd(tgt_skel->progs.xdp_dummy_prog), 521 + "xdp_dummy_prog"); 522 + if (!ASSERT_OK(err, "set_attach_target")) 523 + goto out; 524 + 525 + err = freplace_progmap__load(skel); 526 + if (!ASSERT_OK(err, "obj_load")) 527 + goto out; 528 + 529 + /* Prior to fixing the kernel, loading the PROG_TYPE_EXT 'redirect' 530 + * program above will cause the map owner type of 'cpumap' to be set to 531 + * PROG_TYPE_EXT. This in turn will cause the bpf_map_update_elem() 532 + * below to fail, because the program we are inserting into the map is 533 + * of PROG_TYPE_XDP. After fixing the kernel, the initial ownership will 534 + * be correctly resolved to the *target* of the PROG_TYPE_EXT program 535 + * (i.e., PROG_TYPE_XDP) and the map update will succeed. 536 + */ 537 + value.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_drop_prog); 538 + err = bpf_map_update_elem(bpf_map__fd(skel->maps.cpu_map), 539 + &key, &value, 0); 540 + ASSERT_OK(err, "map_update"); 541 + 542 + out: 543 + xdp_dummy__destroy(tgt_skel); 544 + freplace_progmap__destroy(skel); 545 + } 546 + 505 547 /* NOTE: affect other tests, must run in serial mode */ 506 548 void serial_test_fexit_bpf2bpf(void) 507 549 { ··· 571 525 test_func_replace_global_func(); 572 526 if (test__start_subtest("fentry_to_cgroup_bpf")) 573 527 test_fentry_to_cgroup_bpf(); 528 + if (test__start_subtest("func_replace_progmap")) 529 + test_func_replace_progmap(); 574 530 }
+24
tools/testing/selftests/bpf/progs/freplace_progmap.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <linux/bpf.h> 3 + #include <bpf/bpf_helpers.h> 4 + 5 + struct { 6 + __uint(type, BPF_MAP_TYPE_CPUMAP); 7 + __type(key, __u32); 8 + __type(value, struct bpf_cpumap_val); 9 + __uint(max_entries, 1); 10 + } cpu_map SEC(".maps"); 11 + 12 + SEC("xdp/cpumap") 13 + int xdp_drop_prog(struct xdp_md *ctx) 14 + { 15 + return XDP_DROP; 16 + } 17 + 18 + SEC("freplace") 19 + int xdp_cpumap_prog(struct xdp_md *ctx) 20 + { 21 + return bpf_redirect_map(&cpu_map, 0, XDP_PASS); 22 + } 23 + 24 + char _license[] SEC("license") = "GPL";