bpf: allow self-xor operation
[dpdk.git] / app / test / test_cksum.c
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
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         if (m)
222                 rte_pktmbuf_free(m);
223
224         return -1;
225 }
226
227 static int
228 test_cksum(void)
229 {
230         struct rte_mempool *pktmbuf_pool = NULL;
231
232         /* create pktmbuf pool if it does not exist */
233         pktmbuf_pool = rte_pktmbuf_pool_create("test_cksum_mbuf_pool",
234                         NB_MBUF, MEMPOOL_CACHE_SIZE, 0, MBUF_DATA_SIZE,
235                         SOCKET_ID_ANY);
236
237         if (pktmbuf_pool == NULL)
238                 GOTO_FAIL("cannot allocate mbuf pool");
239
240         if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_tcp,
241                           sizeof(test_cksum_ipv4_tcp)) < 0)
242                 GOTO_FAIL("checksum error on ipv4_tcp");
243
244         if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv6_tcp,
245                           sizeof(test_cksum_ipv6_tcp)) < 0)
246                 GOTO_FAIL("checksum error on ipv6_tcp");
247
248         if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_udp,
249                           sizeof(test_cksum_ipv4_udp)) < 0)
250                 GOTO_FAIL("checksum error on ipv4_udp");
251
252         if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv6_udp,
253                           sizeof(test_cksum_ipv6_udp)) < 0)
254                 GOTO_FAIL("checksum error on ipv6_udp");
255
256         if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_opts_udp,
257                           sizeof(test_cksum_ipv4_opts_udp)) < 0)
258                 GOTO_FAIL("checksum error on ipv4_opts_udp");
259
260         rte_mempool_free(pktmbuf_pool);
261
262         return 0;
263
264 fail:
265         rte_mempool_free(pktmbuf_pool);
266
267         return -1;
268 }
269 #undef GOTO_FAIL
270
271 REGISTER_TEST_COMMAND(cksum_autotest, test_cksum);