1 // SPDX-License-Identifier: GPL-2.0 2 #include <test_progs.h> 3 4 #define IFINDEX_LO 1 5 #define XDP_FLAGS_REPLACE (1U << 4) 6 7 static void test_xdp_attach(const char *file) 8 { 9 __u32 duration = 0, id1, id2, id0 = 0, len; 10 struct bpf_object *obj1, *obj2, *obj3; 11 struct bpf_prog_info info = {}; 12 int err, fd1, fd2, fd3; 13 LIBBPF_OPTS(bpf_xdp_attach_opts, opts); 14 15 len = sizeof(info); 16 17 err = bpf_prog_test_load(file, BPF_PROG_TYPE_XDP, &obj1, &fd1); 18 if (CHECK_FAIL(err)) 19 return; 20 err = bpf_prog_get_info_by_fd(fd1, &info, &len); 21 if (CHECK_FAIL(err)) 22 goto out_1; 23 id1 = info.id; 24 25 err = bpf_prog_test_load(file, BPF_PROG_TYPE_XDP, &obj2, &fd2); 26 if (CHECK_FAIL(err)) 27 goto out_1; 28 29 memset(&info, 0, sizeof(info)); 30 err = bpf_prog_get_info_by_fd(fd2, &info, &len); 31 if (CHECK_FAIL(err)) 32 goto out_2; 33 id2 = info.id; 34 35 err = bpf_prog_test_load(file, BPF_PROG_TYPE_XDP, &obj3, &fd3); 36 if (CHECK_FAIL(err)) 37 goto out_2; 38 39 err = bpf_xdp_attach(IFINDEX_LO, fd1, XDP_FLAGS_REPLACE, &opts); 40 if (CHECK(err, "load_ok", "initial load failed")) 41 goto out_close; 42 43 err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0); 44 if (CHECK(err || id0 != id1, "id1_check", 45 "loaded prog id %u != id1 %u, err %d", id0, id1, err)) 46 goto out_close; 47 48 err = bpf_xdp_attach(IFINDEX_LO, fd2, XDP_FLAGS_REPLACE, &opts); 49 if (CHECK(!err, "load_fail", "load with expected id didn't fail")) 50 goto out; 51 52 opts.old_prog_fd = fd1; 53 err = bpf_xdp_attach(IFINDEX_LO, fd2, 0, &opts); 54 if (CHECK(err, "replace_ok", "replace valid old_fd failed")) 55 goto out; 56 err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0); 57 if (CHECK(err || id0 != id2, "id2_check", 58 "loaded prog id %u != id2 %u, err %d", id0, id2, err)) 59 goto out_close; 60 61 err = bpf_xdp_attach(IFINDEX_LO, fd3, 0, &opts); 62 if (CHECK(!err, "replace_fail", "replace invalid old_fd didn't fail")) 63 goto out; 64 65 err = bpf_xdp_detach(IFINDEX_LO, 0, &opts); 66 if (CHECK(!err, "remove_fail", "remove invalid old_fd didn't fail")) 67 goto out; 68 69 opts.old_prog_fd = fd2; 70 err = bpf_xdp_detach(IFINDEX_LO, 0, &opts); 71 if (CHECK(err, "remove_ok", "remove valid old_fd failed")) 72 goto out; 73 74 err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0); 75 if (CHECK(err || id0 != 0, "unload_check", 76 "loaded prog id %u != 0, err %d", id0, err)) 77 goto out_close; 78 out: 79 bpf_xdp_detach(IFINDEX_LO, 0, NULL); 80 out_close: 81 bpf_object__close(obj3); 82 out_2: 83 bpf_object__close(obj2); 84 out_1: 85 bpf_object__close(obj1); 86 } 87 88 void serial_test_xdp_attach(void) 89 { 90 if (test__start_subtest("xdp_attach")) 91 test_xdp_attach("./test_xdp.bpf.o"); 92 if (test__start_subtest("xdp_attach_dynptr")) 93 test_xdp_attach("./test_xdp_dynptr.bpf.o"); 94 } 95