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 rte_pktmbuf_free(m); 222 223 return -1; 224 } 225 226 static int 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_TEST_COMMAND(cksum_autotest, test_cksum); 271