1 // SPDX-License-Identifier: GPL-2.0 2 #include <test_progs.h> 3 4 static void on_sample(void *ctx, int cpu, void *data, __u32 size) 5 { 6 int ifindex = *(int *)data, duration = 0; 7 struct ipv6_packet *pkt_v6 = data + 4; 8 9 if (ifindex != 1) 10 /* spurious kfree_skb not on loopback device */ 11 return; 12 if (CHECK(size != 76, "check_size", "size %u != 76\n", size)) 13 return; 14 if (CHECK(pkt_v6->eth.h_proto != 0xdd86, "check_eth", 15 "h_proto %x\n", pkt_v6->eth.h_proto)) 16 return; 17 if (CHECK(pkt_v6->iph.nexthdr != 6, "check_ip", 18 "iph.nexthdr %x\n", pkt_v6->iph.nexthdr)) 19 return; 20 if (CHECK(pkt_v6->tcp.doff != 5, "check_tcp", 21 "tcp.doff %x\n", pkt_v6->tcp.doff)) 22 return; 23 24 *(bool *)ctx = true; 25 } 26 27 void test_kfree_skb(void) 28 { 29 struct bpf_prog_load_attr attr = { 30 .file = "./kfree_skb.o", 31 }; 32 33 struct bpf_object *obj, *obj2 = NULL; 34 struct perf_buffer_opts pb_opts = {}; 35 struct perf_buffer *pb = NULL; 36 struct bpf_link *link = NULL; 37 struct bpf_map *perf_buf_map; 38 struct bpf_program *prog; 39 __u32 duration, retval; 40 int err, pkt_fd, kfree_skb_fd; 41 bool passed = false; 42 43 err = bpf_prog_load("./test_pkt_access.o", BPF_PROG_TYPE_SCHED_CLS, &obj, &pkt_fd); 44 if (CHECK(err, "prog_load sched cls", "err %d errno %d\n", err, errno)) 45 return; 46 47 err = bpf_prog_load_xattr(&attr, &obj2, &kfree_skb_fd); 48 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno)) 49 goto close_prog; 50 51 prog = bpf_object__find_program_by_title(obj2, "tp_btf/kfree_skb"); 52 if (CHECK(!prog, "find_prog", "prog kfree_skb not found\n")) 53 goto close_prog; 54 link = bpf_program__attach_raw_tracepoint(prog, NULL); 55 if (CHECK(IS_ERR(link), "attach_raw_tp", "err %ld\n", PTR_ERR(link))) 56 goto close_prog; 57 58 perf_buf_map = bpf_object__find_map_by_name(obj2, "perf_buf_map"); 59 if (CHECK(!perf_buf_map, "find_perf_buf_map", "not found\n")) 60 goto close_prog; 61 62 /* set up perf buffer */ 63 pb_opts.sample_cb = on_sample; 64 pb_opts.ctx = &passed; 65 pb = perf_buffer__new(bpf_map__fd(perf_buf_map), 1, &pb_opts); 66 if (CHECK(IS_ERR(pb), "perf_buf__new", "err %ld\n", PTR_ERR(pb))) 67 goto close_prog; 68 69 err = bpf_prog_test_run(pkt_fd, 1, &pkt_v6, sizeof(pkt_v6), 70 NULL, NULL, &retval, &duration); 71 CHECK(err || retval, "ipv6", 72 "err %d errno %d retval %d duration %d\n", 73 err, errno, retval, duration); 74 75 /* read perf buffer */ 76 err = perf_buffer__poll(pb, 100); 77 if (CHECK(err < 0, "perf_buffer__poll", "err %d\n", err)) 78 goto close_prog; 79 /* make sure kfree_skb program was triggered 80 * and it sent expected skb into ring buffer 81 */ 82 CHECK_FAIL(!passed); 83 close_prog: 84 perf_buffer__free(pb); 85 if (!IS_ERR_OR_NULL(link)) 86 bpf_link__destroy(link); 87 bpf_object__close(obj); 88 bpf_object__close(obj2); 89 } 90