1+ /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
2+ /* Copyright Authors of Kmesh */
3+
4+ #pragma once
5+
6+ #define build_tc_packet (ctx , p_ethhdr , p_iphdr , p_tcphdr , body , body_len ) \
7+ ({ \
8+ int __ret = TEST_PASS; \
9+ \
10+ void *data = (void *)(long)((ctx)->data); \
11+ void *data_end = (void *)(long)((ctx)->data_end); \
12+ \
13+ /* Set Ethernet header */ \
14+ if (data + sizeof (struct ethhdr ) > data_end ) \
15+ return TEST_ERROR ; \
16+ if (p_ethhdr ) { \
17+ bpf_memcpy (data , (p_ethhdr ), sizeof (struct ethhdr )); \
18+ } else { \
19+ /* Default Ethernet header */ \
20+ __maybe_unused const struct ethhdr default_eth = { \
21+ .h_source = {0xAA , 0xBB , 0xCC , 0xDD , 0xEE , 0xFF }, \
22+ .h_dest = {0x12 , 0x23 , 0x34 , 0x45 , 0x56 , 0x67 }, \
23+ .h_proto = bpf_htons (ETH_P_IP )}; \
24+ bpf_memcpy (data , & default_eth , sizeof (struct ethhdr )); \
25+ } \
26+ data += sizeof (struct ethhdr ); \
27+ \
28+ /* Set IP header */ \
29+ if (data + sizeof (struct iphdr ) > data_end ) \
30+ return TEST_ERROR ; \
31+ if (p_iphdr ) { \
32+ bpf_memcpy (data , (p_iphdr ), sizeof (struct iphdr )); \
33+ } else { \
34+ /* Default IP header */ \
35+ __maybe_unused const unsigned int ip_payload_size = sizeof (struct tcphdr ) + (body ? body_len : 0 ); \
36+ __maybe_unused const struct iphdr default_ip = { \
37+ .version = 4 , \
38+ .ihl = 5 , \
39+ .tot_len = bpf_htons (sizeof (struct iphdr ) + ip_payload_size ), \
40+ .id = 0x5438 , \
41+ .frag_off = bpf_htons (IP_DF ), \
42+ .ttl = 64 , \
43+ .protocol = IPPROTO_TCP , \
44+ .saddr = 0x0F00000A , /* 10.0.0.15 */ \
45+ .daddr = 0x0100000A /* 10.0.0.1 - assuming DEST_IP */ \
46+ }; \
47+ bpf_memcpy (data , & default_ip , sizeof (struct iphdr )); \
48+ } \
49+ data += sizeof (struct iphdr ); \
50+ \
51+ /* Set TCP header */ \
52+ if (data + sizeof (struct tcphdr ) > data_end ) \
53+ return TEST_ERROR ; \
54+ if (p_tcphdr ) { \
55+ bpf_memcpy (data , (p_tcphdr ), sizeof (struct tcphdr )); \
56+ } else { \
57+ /* Default TCP header */ \
58+ __maybe_unused const struct tcphdr default_tcp = { \
59+ .source = bpf_htons (23445 ), \
60+ .dest = bpf_htons (80 ), /* assuming DEST_PORT */ \
61+ .seq = 2922048129 , \
62+ .doff = 5 , /* 5 * 4 = 20 bytes, no options */ \
63+ .syn = 1 , \
64+ .window = 64240 }; \
65+ bpf_memcpy (data , & default_tcp , sizeof (struct tcphdr )); \
66+ } \
67+ data += sizeof (struct tcphdr ); \
68+ \
69+ /* Set payload data */ \
70+ if (body && body_len > 0 ) { \
71+ if (data + body_len > data_end ) \
72+ return TEST_ERROR ; \
73+ bpf_memcpy (data , body , body_len ); \
74+ data += body_len ; \
75+ } \
76+ /* Shrink data payload to the exact size we used */ \
77+ bpf_skb_change_tail (ctx , data - (void * )(long )((ctx )-> data ), 0 ); \
78+ __ret ; \
79+ })
80+
81+ #define check_tc_packet (ctx , exp_status_code , exp_ethhdr , exp_iphdr , exp_tcphdr , exp_body , exp_body_len ) \
82+ do { \
83+ void *data = (void *)(long)((ctx)->data); \
84+ void *data_end = (void *)(long)((ctx)->data_end); \
85+ \
86+ if (data + sizeof(__u32) > data_end) \
87+ test_fatal("status code out of bounds"); \
88+ if (exp_status_code) { \
89+ __u32 *status_code = (__u32 *)data; \
90+ if (*status_code != *(exp_status_code)) \
91+ test_fatal("status code mismatch, expected %u, got %u", *(exp_status_code), *status_code); \
92+ } \
93+ data += sizeof(__u32); \
94+ \
95+ if (data + sizeof(struct ethhdr) > data_end) \
96+ test_fatal("ethhdr out of bounds"); \
97+ if (exp_ethhdr) { \
98+ struct ethhdr *eth = (struct ethhdr *)data; \
99+ if (memcmp(eth, (exp_ethhdr), sizeof(struct ethhdr)) != 0) \
100+ test_fatal("ethhdr mismatch"); \
101+ } \
102+ data += sizeof(struct ethhdr); \
103+ \
104+ if (data + sizeof(struct iphdr) > data_end) \
105+ test_fatal("iphdr out of bounds"); \
106+ if (exp_iphdr) { \
107+ struct iphdr *ip = (struct iphdr *)data; \
108+ if (memcmp(ip, (exp_iphdr), sizeof(struct iphdr)) != 0) \
109+ test_fatal("iphdr mismatch"); \
110+ } \
111+ data += sizeof(struct iphdr); \
112+ \
113+ if (data + sizeof(struct tcphdr) > data_end) \
114+ test_fatal("tcphdr out of bounds"); \
115+ if (exp_tcphdr) { \
116+ struct tcphdr *tcp = (struct tcphdr *)data; \
117+ if (memcmp(tcp, (exp_tcphdr), sizeof(struct tcphdr)) != 0) \
118+ test_fatal("tcphdr mismatch"); \
119+ } \
120+ data += sizeof(struct tcphdr); \
121+ if (data + exp_body_len > data_end) \
122+ test_fatal("body out of bounds"); \
123+ if (exp_body) { \
124+ char *body = (char *)data; \
125+ if (memcmp(body, (exp_body), exp_body_len) != 0) \
126+ test_fatal("body mismatch"); \
127+ } \
128+ } while (0)
0 commit comments