1 // SPDX-License-Identifier: GPL-2.0 2 #include <test_progs.h> 3 #include <network_helpers.h> 4 #include "kfree_skb.skel.h" 5 6 struct meta { 7 int ifindex; 8 __u32 cb32_0; 9 __u8 cb8_0; 10 }; 11 12 static union { 13 __u32 cb32[5]; 14 __u8 cb8[20]; 15 } cb = { 16 .cb32[0] = 0x81828384, 17 }; 18 19 static void on_sample(void *ctx, int cpu, void *data, __u32 size) 20 { 21 struct meta *meta = (struct meta *)data; 22 struct ipv6_packet *pkt_v6 = data + sizeof(*meta); 23 int duration = 0; 24 25 if (CHECK(size != 72 + sizeof(*meta), "check_size", "size %u != %zu\n", 26 size, 72 + sizeof(*meta))) 27 return; 28 if (CHECK(meta->ifindex != 1, "check_meta_ifindex", 29 "meta->ifindex = %d\n", meta->ifindex)) 30 /* spurious kfree_skb not on loopback device */ 31 return; 32 if (CHECK(meta->cb8_0 != cb.cb8[0], "check_cb8_0", "cb8_0 %x != %x\n", 33 meta->cb8_0, cb.cb8[0])) 34 return; 35 if (CHECK(meta->cb32_0 != cb.cb32[0], "check_cb32_0", 36 "cb32_0 %x != %x\n", 37 meta->cb32_0, cb.cb32[0])) 38 return; 39 if (CHECK(pkt_v6->eth.h_proto != 0xdd86, "check_eth", 40 "h_proto %x\n", pkt_v6->eth.h_proto)) 41 return; 42 if (CHECK(pkt_v6->iph.nexthdr != 6, "check_ip", 43 "iph.nexthdr %x\n", pkt_v6->iph.nexthdr)) 44 return; 45 if (CHECK(pkt_v6->tcp.doff != 5, "check_tcp", 46 "tcp.doff %x\n", pkt_v6->tcp.doff)) 47 return; 48 49 *(bool *)ctx = true; 50 } 51 52 /* TODO: fix kernel panic caused by this test in parallel mode */ 53 void serial_test_kfree_skb(void) 54 { 55 struct __sk_buff skb = {}; 56 LIBBPF_OPTS(bpf_test_run_opts, topts, 57 .data_in = &pkt_v6, 58 .data_size_in = sizeof(pkt_v6), 59 .ctx_in = &skb, 60 .ctx_size_in = sizeof(skb), 61 ); 62 struct kfree_skb *skel = NULL; 63 struct bpf_link *link; 64 struct bpf_object *obj; 65 struct perf_buffer *pb = NULL; 66 int err, prog_fd; 67 bool passed = false; 68 __u32 duration = 0; 69 const int zero = 0; 70 bool test_ok[2]; 71 72 err = bpf_prog_test_load("./test_pkt_access.o", BPF_PROG_TYPE_SCHED_CLS, 73 &obj, &prog_fd); 74 if (CHECK(err, "prog_load sched cls", "err %d errno %d\n", err, errno)) 75 return; 76 77 skel = kfree_skb__open_and_load(); 78 if (!ASSERT_OK_PTR(skel, "kfree_skb_skel")) 79 goto close_prog; 80 81 link = bpf_program__attach_raw_tracepoint(skel->progs.trace_kfree_skb, NULL); 82 if (!ASSERT_OK_PTR(link, "attach_raw_tp")) 83 goto close_prog; 84 skel->links.trace_kfree_skb = link; 85 86 link = bpf_program__attach_trace(skel->progs.fentry_eth_type_trans); 87 if (!ASSERT_OK_PTR(link, "attach fentry")) 88 goto close_prog; 89 skel->links.fentry_eth_type_trans = link; 90 91 link = bpf_program__attach_trace(skel->progs.fexit_eth_type_trans); 92 if (!ASSERT_OK_PTR(link, "attach fexit")) 93 goto close_prog; 94 skel->links.fexit_eth_type_trans = link; 95 96 /* set up perf buffer */ 97 pb = perf_buffer__new(bpf_map__fd(skel->maps.perf_buf_map), 1, 98 on_sample, NULL, &passed, NULL); 99 if (!ASSERT_OK_PTR(pb, "perf_buf__new")) 100 goto close_prog; 101 102 memcpy(skb.cb, &cb, sizeof(cb)); 103 err = bpf_prog_test_run_opts(prog_fd, &topts); 104 ASSERT_OK(err, "ipv6 test_run"); 105 ASSERT_OK(topts.retval, "ipv6 test_run retval"); 106 107 /* read perf buffer */ 108 err = perf_buffer__poll(pb, 100); 109 if (CHECK(err < 0, "perf_buffer__poll", "err %d\n", err)) 110 goto close_prog; 111 112 /* make sure kfree_skb program was triggered 113 * and it sent expected skb into ring buffer 114 */ 115 ASSERT_TRUE(passed, "passed"); 116 117 err = bpf_map_lookup_elem(bpf_map__fd(skel->maps.bss), &zero, test_ok); 118 if (CHECK(err, "get_result", 119 "failed to get output data: %d\n", err)) 120 goto close_prog; 121 122 CHECK_FAIL(!test_ok[0] || !test_ok[1]); 123 close_prog: 124 perf_buffer__free(pb); 125 bpf_object__close(obj); 126 kfree_skb__destroy(skel); 127 } 128