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 struct bpf_prog_test_run_attr tattr = { 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; 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, &tattr.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_xattr(&tattr); 104 duration = tattr.duration; 105 CHECK(err || tattr.retval, "ipv6", 106 "err %d errno %d retval %d duration %d\n", 107 err, errno, tattr.retval, duration); 108 109 /* read perf buffer */ 110 err = perf_buffer__poll(pb, 100); 111 if (CHECK(err < 0, "perf_buffer__poll", "err %d\n", err)) 112 goto close_prog; 113 114 /* make sure kfree_skb program was triggered 115 * and it sent expected skb into ring buffer 116 */ 117 ASSERT_TRUE(passed, "passed"); 118 119 err = bpf_map_lookup_elem(bpf_map__fd(skel->maps.bss), &zero, test_ok); 120 if (CHECK(err, "get_result", 121 "failed to get output data: %d\n", err)) 122 goto close_prog; 123 124 CHECK_FAIL(!test_ok[0] || !test_ok[1]); 125 close_prog: 126 perf_buffer__free(pb); 127 bpf_object__close(obj); 128 kfree_skb__destroy(skel); 129 } 130