1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 
4 #define CHECK_FLOW_KEYS(desc, got, expected)				\
5 	CHECK(memcmp(&got, &expected, sizeof(got)) != 0,		\
6 	      desc,							\
7 	      "nhoff=%u/%u "						\
8 	      "thoff=%u/%u "						\
9 	      "addr_proto=0x%x/0x%x "					\
10 	      "is_frag=%u/%u "						\
11 	      "is_first_frag=%u/%u "					\
12 	      "is_encap=%u/%u "						\
13 	      "n_proto=0x%x/0x%x "					\
14 	      "sport=%u/%u "						\
15 	      "dport=%u/%u\n",						\
16 	      got.nhoff, expected.nhoff,				\
17 	      got.thoff, expected.thoff,				\
18 	      got.addr_proto, expected.addr_proto,			\
19 	      got.is_frag, expected.is_frag,				\
20 	      got.is_first_frag, expected.is_first_frag,		\
21 	      got.is_encap, expected.is_encap,				\
22 	      got.n_proto, expected.n_proto,				\
23 	      got.sport, expected.sport,				\
24 	      got.dport, expected.dport)
25 
26 static struct bpf_flow_keys pkt_v4_flow_keys = {
27 	.nhoff = 0,
28 	.thoff = sizeof(struct iphdr),
29 	.addr_proto = ETH_P_IP,
30 	.ip_proto = IPPROTO_TCP,
31 	.n_proto = __bpf_constant_htons(ETH_P_IP),
32 };
33 
34 static struct bpf_flow_keys pkt_v6_flow_keys = {
35 	.nhoff = 0,
36 	.thoff = sizeof(struct ipv6hdr),
37 	.addr_proto = ETH_P_IPV6,
38 	.ip_proto = IPPROTO_TCP,
39 	.n_proto = __bpf_constant_htons(ETH_P_IPV6),
40 };
41 
42 void test_flow_dissector(void)
43 {
44 	struct bpf_flow_keys flow_keys;
45 	struct bpf_object *obj;
46 	__u32 duration, retval;
47 	int err, prog_fd;
48 	__u32 size;
49 
50 	err = bpf_flow_load(&obj, "./bpf_flow.o", "flow_dissector",
51 			    "jmp_table", &prog_fd);
52 	if (err) {
53 		error_cnt++;
54 		return;
55 	}
56 
57 	err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4),
58 				&flow_keys, &size, &retval, &duration);
59 	CHECK(size != sizeof(flow_keys) || err || retval != 1, "ipv4",
60 	      "err %d errno %d retval %d duration %d size %u/%lu\n",
61 	      err, errno, retval, duration, size, sizeof(flow_keys));
62 	CHECK_FLOW_KEYS("ipv4_flow_keys", flow_keys, pkt_v4_flow_keys);
63 
64 	err = bpf_prog_test_run(prog_fd, 10, &pkt_v6, sizeof(pkt_v6),
65 				&flow_keys, &size, &retval, &duration);
66 	CHECK(size != sizeof(flow_keys) || err || retval != 1, "ipv6",
67 	      "err %d errno %d retval %d duration %d size %u/%lu\n",
68 	      err, errno, retval, duration, size, sizeof(flow_keys));
69 	CHECK_FLOW_KEYS("ipv6_flow_keys", flow_keys, pkt_v6_flow_keys);
70 
71 	bpf_object__close(obj);
72 }
73