1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2021 6WIND S.A.
3 */
4
5 #include <string.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9
10 #include <rte_net.h>
11 #include <rte_mbuf.h>
12 #include <rte_ip.h>
13
14 #include "test.h"
15
16 #define MEMPOOL_CACHE_SIZE 0
17 #define MBUF_DATA_SIZE 256
18 #define NB_MBUF 128
19
20 /*
21 * Test L3/L4 checksum API.
22 */
23
24 #define GOTO_FAIL(str, ...) do { \
25 printf("cksum test FAILED (l.%d): <" str ">\n", \
26 __LINE__, ##__VA_ARGS__); \
27 goto fail; \
28 } while (0)
29
30 /* generated in scapy with Ether()/IP()/TCP())) */
31 static const char test_cksum_ipv4_tcp[] = {
32 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
33 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
34 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,
35 0x7c, 0xcd, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
36 0x00, 0x01, 0x00, 0x14, 0x00, 0x50, 0x00, 0x00,
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02,
38 0x20, 0x00, 0x91, 0x7c, 0x00, 0x00,
39
40 };
41
42 /* generated in scapy with Ether()/IPv6()/TCP()) */
43 static const char test_cksum_ipv6_tcp[] = {
44 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
45 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x60, 0x00,
46 0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14,
51 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x50, 0x02, 0x20, 0x00, 0x8f, 0x7d,
53 0x00, 0x00,
54 };
55
56 /* generated in scapy with Ether()/IP()/UDP()/Raw('x')) */
57 static const char test_cksum_ipv4_udp[] = {
58 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
60 0x00, 0x1d, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
61 0x7c, 0xcd, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
62 0x00, 0x01, 0x00, 0x35, 0x00, 0x35, 0x00, 0x09,
63 0x89, 0x6f, 0x78,
64 };
65
66 /* generated in scapy with Ether()/IPv6()/UDP()/Raw('x')) */
67 static const char test_cksum_ipv6_udp[] = {
68 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd, 0x60, 0x00,
70 0x00, 0x00, 0x00, 0x09, 0x11, 0x40, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x35,
75 0x00, 0x35, 0x00, 0x09, 0x87, 0x70, 0x78,
76 };
77
78 /* generated in scapy with Ether()/IP(options='\x00')/UDP()/Raw('x')) */
79 static const char test_cksum_ipv4_opts_udp[] = {
80 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x46, 0x00,
82 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
83 0x7b, 0xc9, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
84 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35,
85 0x00, 0x35, 0x00, 0x09, 0x89, 0x6f, 0x78,
86 };
87
88 /* test l3/l4 checksum api */
89 static int
test_l4_cksum(struct rte_mempool * pktmbuf_pool,const char * pktdata,size_t len)90 test_l4_cksum(struct rte_mempool *pktmbuf_pool, const char *pktdata, size_t len)
91 {
92 struct rte_net_hdr_lens hdr_lens;
93 struct rte_mbuf *m = NULL;
94 uint32_t packet_type;
95 uint16_t prev_cksum;
96 void *l3_hdr;
97 void *l4_hdr;
98 uint32_t l3;
99 uint32_t l4;
100 char *data;
101
102 m = rte_pktmbuf_alloc(pktmbuf_pool);
103 if (m == NULL)
104 GOTO_FAIL("Cannot allocate mbuf");
105
106 data = rte_pktmbuf_append(m, len);
107 if (data == NULL)
108 GOTO_FAIL("Cannot append data");
109
110 memcpy(data, pktdata, len);
111
112 packet_type = rte_net_get_ptype(m, &hdr_lens, RTE_PTYPE_ALL_MASK);
113 l3 = packet_type & RTE_PTYPE_L3_MASK;
114 l4 = packet_type & RTE_PTYPE_L4_MASK;
115
116 l3_hdr = rte_pktmbuf_mtod_offset(m, void *, hdr_lens.l2_len);
117 l4_hdr = rte_pktmbuf_mtod_offset(m, void *,
118 hdr_lens.l2_len + hdr_lens.l3_len);
119
120 if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) {
121 struct rte_ipv4_hdr *ip = l3_hdr;
122
123 /* verify IPv4 checksum */
124 if (rte_ipv4_cksum(l3_hdr) != 0)
125 GOTO_FAIL("invalid IPv4 checksum verification");
126
127 /* verify bad IPv4 checksum */
128 ip->hdr_checksum++;
129 if (rte_ipv4_cksum(l3_hdr) == 0)
130 GOTO_FAIL("invalid IPv4 bad checksum verification");
131 ip->hdr_checksum--;
132
133 /* recalculate IPv4 checksum */
134 prev_cksum = ip->hdr_checksum;
135 ip->hdr_checksum = 0;
136 ip->hdr_checksum = rte_ipv4_cksum(ip);
137 if (ip->hdr_checksum != prev_cksum)
138 GOTO_FAIL("invalid IPv4 checksum calculation");
139
140 /* verify L4 checksum */
141 if (rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr) != 0)
142 GOTO_FAIL("invalid L4 checksum verification");
143
144 if (l4 == RTE_PTYPE_L4_TCP) {
145 struct rte_tcp_hdr *tcp = l4_hdr;
146
147 /* verify bad TCP checksum */
148 tcp->cksum++;
149 if (rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0)
150 GOTO_FAIL("invalid bad TCP checksum verification");
151 tcp->cksum--;
152
153 /* recalculate TCP checksum */
154 prev_cksum = tcp->cksum;
155 tcp->cksum = 0;
156 tcp->cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr);
157 if (tcp->cksum != prev_cksum)
158 GOTO_FAIL("invalid TCP checksum calculation");
159
160 } else if (l4 == RTE_PTYPE_L4_UDP) {
161 struct rte_udp_hdr *udp = l4_hdr;
162
163 /* verify bad UDP checksum */
164 udp->dgram_cksum++;
165 if (rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0)
166 GOTO_FAIL("invalid bad UDP checksum verification");
167 udp->dgram_cksum--;
168
169 /* recalculate UDP checksum */
170 prev_cksum = udp->dgram_cksum;
171 udp->dgram_cksum = 0;
172 udp->dgram_cksum = rte_ipv4_udptcp_cksum(l3_hdr,
173 l4_hdr);
174 if (udp->dgram_cksum != prev_cksum)
175 GOTO_FAIL("invalid TCP checksum calculation");
176 }
177 } else if (l3 == RTE_PTYPE_L3_IPV6 || l3 == RTE_PTYPE_L3_IPV6_EXT) {
178 if (rte_ipv6_udptcp_cksum_verify(l3_hdr, l4_hdr) != 0)
179 GOTO_FAIL("invalid L4 checksum verification");
180
181 if (l4 == RTE_PTYPE_L4_TCP) {
182 struct rte_tcp_hdr *tcp = l4_hdr;
183
184 /* verify bad TCP checksum */
185 tcp->cksum++;
186 if (rte_ipv6_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0)
187 GOTO_FAIL("invalid bad TCP checksum verification");
188 tcp->cksum--;
189
190 /* recalculate TCP checksum */
191 prev_cksum = tcp->cksum;
192 tcp->cksum = 0;
193 tcp->cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr);
194 if (tcp->cksum != prev_cksum)
195 GOTO_FAIL("invalid TCP checksum calculation");
196
197 } else if (l4 == RTE_PTYPE_L4_UDP) {
198 struct rte_udp_hdr *udp = l4_hdr;
199
200 /* verify bad UDP checksum */
201 udp->dgram_cksum++;
202 if (rte_ipv6_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0)
203 GOTO_FAIL("invalid bad UDP checksum verification");
204 udp->dgram_cksum--;
205
206 /* recalculate UDP checksum */
207 prev_cksum = udp->dgram_cksum;
208 udp->dgram_cksum = 0;
209 udp->dgram_cksum = rte_ipv6_udptcp_cksum(l3_hdr,
210 l4_hdr);
211 if (udp->dgram_cksum != prev_cksum)
212 GOTO_FAIL("invalid TCP checksum calculation");
213 }
214 }
215
216 rte_pktmbuf_free(m);
217
218 return 0;
219
220 fail:
221 rte_pktmbuf_free(m);
222
223 return -1;
224 }
225
226 static int
test_cksum(void)227 test_cksum(void)
228 {
229 struct rte_mempool *pktmbuf_pool = NULL;
230
231 /* create pktmbuf pool if it does not exist */
232 pktmbuf_pool = rte_pktmbuf_pool_create("test_cksum_mbuf_pool",
233 NB_MBUF, MEMPOOL_CACHE_SIZE, 0, MBUF_DATA_SIZE,
234 SOCKET_ID_ANY);
235
236 if (pktmbuf_pool == NULL)
237 GOTO_FAIL("cannot allocate mbuf pool");
238
239 if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_tcp,
240 sizeof(test_cksum_ipv4_tcp)) < 0)
241 GOTO_FAIL("checksum error on ipv4_tcp");
242
243 if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv6_tcp,
244 sizeof(test_cksum_ipv6_tcp)) < 0)
245 GOTO_FAIL("checksum error on ipv6_tcp");
246
247 if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_udp,
248 sizeof(test_cksum_ipv4_udp)) < 0)
249 GOTO_FAIL("checksum error on ipv4_udp");
250
251 if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv6_udp,
252 sizeof(test_cksum_ipv6_udp)) < 0)
253 GOTO_FAIL("checksum error on ipv6_udp");
254
255 if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_opts_udp,
256 sizeof(test_cksum_ipv4_opts_udp)) < 0)
257 GOTO_FAIL("checksum error on ipv4_opts_udp");
258
259 rte_mempool_free(pktmbuf_pool);
260
261 return 0;
262
263 fail:
264 rte_mempool_free(pktmbuf_pool);
265
266 return -1;
267 }
268 #undef GOTO_FAIL
269
270 REGISTER_FAST_TEST(cksum_autotest, true, true, test_cksum);
271