xref: /dpdk/app/test/test_cksum.c (revision e0a8442ccd15bafbb7eb150c35331c8e3b828c53)
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