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