1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 * Copyright 2014 6WIND S.A. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /* 36 * Copyright (c) 1982, 1986, 1990, 1993 37 * The Regents of the University of California. All rights reserved. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. All advertising materials mentioning features or use of this software 48 * must display the following acknowledgement: 49 * This product includes software developed by the University of 50 * California, Berkeley and its contributors. 51 * 4. Neither the name of the University nor the names of its contributors 52 * may be used to endorse or promote products derived from this software 53 * without specific prior written permission. 54 * 55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 65 * SUCH DAMAGE. 66 * 67 * @(#)in.h 8.3 (Berkeley) 1/3/94 68 * $FreeBSD: src/sys/netinet/in.h,v 1.82 2003/10/25 09:37:10 ume Exp $ 69 */ 70 71 #ifndef _RTE_IP_H_ 72 #define _RTE_IP_H_ 73 74 /** 75 * @file 76 * 77 * IP-related defines 78 */ 79 80 #include <stdint.h> 81 #include <netinet/in.h> 82 83 #include <rte_byteorder.h> 84 #include <rte_mbuf.h> 85 86 #ifdef __cplusplus 87 extern "C" { 88 #endif 89 90 /** 91 * IPv4 Header 92 */ 93 struct ipv4_hdr { 94 uint8_t version_ihl; /**< version and header length */ 95 uint8_t type_of_service; /**< type of service */ 96 uint16_t total_length; /**< length of packet */ 97 uint16_t packet_id; /**< packet ID */ 98 uint16_t fragment_offset; /**< fragmentation offset */ 99 uint8_t time_to_live; /**< time to live */ 100 uint8_t next_proto_id; /**< protocol ID */ 101 uint16_t hdr_checksum; /**< header checksum */ 102 uint32_t src_addr; /**< source address */ 103 uint32_t dst_addr; /**< destination address */ 104 } __attribute__((__packed__)); 105 106 /** Create IPv4 address */ 107 #define IPv4(a,b,c,d) ((uint32_t)(((a) & 0xff) << 24) | \ 108 (((b) & 0xff) << 16) | \ 109 (((c) & 0xff) << 8) | \ 110 ((d) & 0xff)) 111 112 /** Maximal IPv4 packet length (including a header) */ 113 #define IPV4_MAX_PKT_LEN 65535 114 115 /** Internet header length mask for version_ihl field */ 116 #define IPV4_HDR_IHL_MASK (0x0f) 117 /** 118 * Internet header length field multiplier (IHL field specifies overall header 119 * length in number of 4-byte words) 120 */ 121 #define IPV4_IHL_MULTIPLIER (4) 122 123 /* Fragment Offset * Flags. */ 124 #define IPV4_HDR_DF_SHIFT 14 125 #define IPV4_HDR_MF_SHIFT 13 126 #define IPV4_HDR_FO_SHIFT 3 127 128 #define IPV4_HDR_DF_FLAG (1 << IPV4_HDR_DF_SHIFT) 129 #define IPV4_HDR_MF_FLAG (1 << IPV4_HDR_MF_SHIFT) 130 131 #define IPV4_HDR_OFFSET_MASK ((1 << IPV4_HDR_MF_SHIFT) - 1) 132 133 #define IPV4_HDR_OFFSET_UNITS 8 134 135 /* 136 * IPv4 address types 137 */ 138 #define IPV4_ANY ((uint32_t)0x00000000) /**< 0.0.0.0 */ 139 #define IPV4_LOOPBACK ((uint32_t)0x7f000001) /**< 127.0.0.1 */ 140 #define IPV4_BROADCAST ((uint32_t)0xe0000000) /**< 224.0.0.0 */ 141 #define IPV4_ALLHOSTS_GROUP ((uint32_t)0xe0000001) /**< 224.0.0.1 */ 142 #define IPV4_ALLRTRS_GROUP ((uint32_t)0xe0000002) /**< 224.0.0.2 */ 143 #define IPV4_MAX_LOCAL_GROUP ((uint32_t)0xe00000ff) /**< 224.0.0.255 */ 144 145 /* 146 * IPv4 Multicast-related macros 147 */ 148 #define IPV4_MIN_MCAST IPv4(224, 0, 0, 0) /**< Minimal IPv4-multicast address */ 149 #define IPV4_MAX_MCAST IPv4(239, 255, 255, 255) /**< Maximum IPv4 multicast address */ 150 151 #define IS_IPV4_MCAST(x) \ 152 ((x) >= IPV4_MIN_MCAST && (x) <= IPV4_MAX_MCAST) /**< check if IPv4 address is multicast */ 153 154 /** 155 * @internal Calculate a sum of all words in the buffer. 156 * Helper routine for the rte_raw_cksum(). 157 * 158 * @param buf 159 * Pointer to the buffer. 160 * @param len 161 * Length of the buffer. 162 * @param sum 163 * Initial value of the sum. 164 * @return 165 * sum += Sum of all words in the buffer. 166 */ 167 static inline uint32_t 168 __rte_raw_cksum(const void *buf, size_t len, uint32_t sum) 169 { 170 /* workaround gcc strict-aliasing warning */ 171 uintptr_t ptr = (uintptr_t)buf; 172 typedef uint16_t __attribute__((__may_alias__)) u16_p; 173 const u16_p *u16 = (const u16_p *)ptr; 174 175 while (len >= (sizeof(*u16) * 4)) { 176 sum += u16[0]; 177 sum += u16[1]; 178 sum += u16[2]; 179 sum += u16[3]; 180 len -= sizeof(*u16) * 4; 181 u16 += 4; 182 } 183 while (len >= sizeof(*u16)) { 184 sum += *u16; 185 len -= sizeof(*u16); 186 u16 += 1; 187 } 188 189 /* if length is in odd bytes */ 190 if (len == 1) 191 sum += *((const uint8_t *)u16); 192 193 return sum; 194 } 195 196 /** 197 * @internal Reduce a sum to the non-complemented checksum. 198 * Helper routine for the rte_raw_cksum(). 199 * 200 * @param sum 201 * Value of the sum. 202 * @return 203 * The non-complemented checksum. 204 */ 205 static inline uint16_t 206 __rte_raw_cksum_reduce(uint32_t sum) 207 { 208 sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff); 209 sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff); 210 return (uint16_t)sum; 211 } 212 213 /** 214 * Process the non-complemented checksum of a buffer. 215 * 216 * @param buf 217 * Pointer to the buffer. 218 * @param len 219 * Length of the buffer. 220 * @return 221 * The non-complemented checksum. 222 */ 223 static inline uint16_t 224 rte_raw_cksum(const void *buf, size_t len) 225 { 226 uint32_t sum; 227 228 sum = __rte_raw_cksum(buf, len, 0); 229 return __rte_raw_cksum_reduce(sum); 230 } 231 232 /** 233 * Compute the raw (non complemented) checksum of a packet. 234 * 235 * @param m 236 * The pointer to the mbuf. 237 * @param off 238 * The offset in bytes to start the checksum. 239 * @param len 240 * The length in bytes of the data to checksum. 241 * @param cksum 242 * A pointer to the checksum, filled on success. 243 * @return 244 * 0 on success, -1 on error (bad length or offset). 245 */ 246 static inline int 247 rte_raw_cksum_mbuf(const struct rte_mbuf *m, uint32_t off, uint32_t len, 248 uint16_t *cksum) 249 { 250 const struct rte_mbuf *seg; 251 const char *buf; 252 uint32_t sum, tmp; 253 uint32_t seglen, done; 254 255 /* easy case: all data in the first segment */ 256 if (off + len <= rte_pktmbuf_data_len(m)) { 257 *cksum = rte_raw_cksum(rte_pktmbuf_mtod_offset(m, 258 const char *, off), len); 259 return 0; 260 } 261 262 if (unlikely(off + len > rte_pktmbuf_pkt_len(m))) 263 return -1; /* invalid params, return a dummy value */ 264 265 /* else browse the segment to find offset */ 266 seglen = 0; 267 for (seg = m; seg != NULL; seg = seg->next) { 268 seglen = rte_pktmbuf_data_len(seg); 269 if (off < seglen) 270 break; 271 off -= seglen; 272 } 273 seglen -= off; 274 buf = rte_pktmbuf_mtod_offset(seg, const char *, off); 275 if (seglen >= len) { 276 /* all in one segment */ 277 *cksum = rte_raw_cksum(buf, len); 278 return 0; 279 } 280 281 /* hard case: process checksum of several segments */ 282 sum = 0; 283 done = 0; 284 for (;;) { 285 tmp = __rte_raw_cksum(buf, seglen, 0); 286 if (done & 1) 287 tmp = rte_bswap16(tmp); 288 sum += tmp; 289 done += seglen; 290 if (done == len) 291 break; 292 seg = seg->next; 293 buf = rte_pktmbuf_mtod(seg, const char *); 294 seglen = rte_pktmbuf_data_len(seg); 295 if (seglen > len - done) 296 seglen = len - done; 297 } 298 299 *cksum = __rte_raw_cksum_reduce(sum); 300 return 0; 301 } 302 303 /** 304 * Process the IPv4 checksum of an IPv4 header. 305 * 306 * The checksum field must be set to 0 by the caller. 307 * 308 * @param ipv4_hdr 309 * The pointer to the contiguous IPv4 header. 310 * @return 311 * The complemented checksum to set in the IP packet. 312 */ 313 static inline uint16_t 314 rte_ipv4_cksum(const struct ipv4_hdr *ipv4_hdr) 315 { 316 uint16_t cksum; 317 cksum = rte_raw_cksum(ipv4_hdr, sizeof(struct ipv4_hdr)); 318 return (cksum == 0xffff) ? cksum : ~cksum; 319 } 320 321 /** 322 * Process the pseudo-header checksum of an IPv4 header. 323 * 324 * The checksum field must be set to 0 by the caller. 325 * 326 * Depending on the ol_flags, the pseudo-header checksum expected by the 327 * drivers is not the same. For instance, when TSO is enabled, the IP 328 * payload length must not be included in the packet. 329 * 330 * When ol_flags is 0, it computes the standard pseudo-header checksum. 331 * 332 * @param ipv4_hdr 333 * The pointer to the contiguous IPv4 header. 334 * @param ol_flags 335 * The ol_flags of the associated mbuf. 336 * @return 337 * The non-complemented checksum to set in the L4 header. 338 */ 339 static inline uint16_t 340 rte_ipv4_phdr_cksum(const struct ipv4_hdr *ipv4_hdr, uint64_t ol_flags) 341 { 342 struct ipv4_psd_header { 343 uint32_t src_addr; /* IP address of source host. */ 344 uint32_t dst_addr; /* IP address of destination host. */ 345 uint8_t zero; /* zero. */ 346 uint8_t proto; /* L4 protocol type. */ 347 uint16_t len; /* L4 length. */ 348 } psd_hdr; 349 350 psd_hdr.src_addr = ipv4_hdr->src_addr; 351 psd_hdr.dst_addr = ipv4_hdr->dst_addr; 352 psd_hdr.zero = 0; 353 psd_hdr.proto = ipv4_hdr->next_proto_id; 354 if (ol_flags & PKT_TX_TCP_SEG) { 355 psd_hdr.len = 0; 356 } else { 357 psd_hdr.len = rte_cpu_to_be_16( 358 (uint16_t)(rte_be_to_cpu_16(ipv4_hdr->total_length) 359 - sizeof(struct ipv4_hdr))); 360 } 361 return rte_raw_cksum(&psd_hdr, sizeof(psd_hdr)); 362 } 363 364 /** 365 * Process the IPv4 UDP or TCP checksum. 366 * 367 * The IPv4 header should not contains options. The IP and layer 4 368 * checksum must be set to 0 in the packet by the caller. 369 * 370 * @param ipv4_hdr 371 * The pointer to the contiguous IPv4 header. 372 * @param l4_hdr 373 * The pointer to the beginning of the L4 header. 374 * @return 375 * The complemented checksum to set in the IP packet. 376 */ 377 static inline uint16_t 378 rte_ipv4_udptcp_cksum(const struct ipv4_hdr *ipv4_hdr, const void *l4_hdr) 379 { 380 uint32_t cksum; 381 uint32_t l4_len; 382 383 l4_len = rte_be_to_cpu_16(ipv4_hdr->total_length) - 384 sizeof(struct ipv4_hdr); 385 386 cksum = rte_raw_cksum(l4_hdr, l4_len); 387 cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); 388 389 cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); 390 cksum = (~cksum) & 0xffff; 391 if (cksum == 0) 392 cksum = 0xffff; 393 394 return cksum; 395 } 396 397 /** 398 * IPv6 Header 399 */ 400 struct ipv6_hdr { 401 uint32_t vtc_flow; /**< IP version, traffic class & flow label. */ 402 uint16_t payload_len; /**< IP packet length - includes sizeof(ip_header). */ 403 uint8_t proto; /**< Protocol, next header. */ 404 uint8_t hop_limits; /**< Hop limits. */ 405 uint8_t src_addr[16]; /**< IP address of source host. */ 406 uint8_t dst_addr[16]; /**< IP address of destination host(s). */ 407 } __attribute__((__packed__)); 408 409 /* IPv6 vtc_flow: IPv / TC / flow_label */ 410 #define IPV6_HDR_FL_SHIFT 0 411 #define IPV6_HDR_TC_SHIFT 20 412 #define IPV6_HDR_FL_MASK ((1u << IPV6_HDR_TC_SHIFT) - 1) 413 #define IPV6_HDR_TC_MASK (0xf << IPV6_HDR_TC_SHIFT) 414 415 /** 416 * Process the pseudo-header checksum of an IPv6 header. 417 * 418 * Depending on the ol_flags, the pseudo-header checksum expected by the 419 * drivers is not the same. For instance, when TSO is enabled, the IPv6 420 * payload length must not be included in the packet. 421 * 422 * When ol_flags is 0, it computes the standard pseudo-header checksum. 423 * 424 * @param ipv6_hdr 425 * The pointer to the contiguous IPv6 header. 426 * @param ol_flags 427 * The ol_flags of the associated mbuf. 428 * @return 429 * The non-complemented checksum to set in the L4 header. 430 */ 431 static inline uint16_t 432 rte_ipv6_phdr_cksum(const struct ipv6_hdr *ipv6_hdr, uint64_t ol_flags) 433 { 434 uint32_t sum; 435 struct { 436 uint32_t len; /* L4 length. */ 437 uint32_t proto; /* L4 protocol - top 3 bytes must be zero */ 438 } psd_hdr; 439 440 psd_hdr.proto = (ipv6_hdr->proto << 24); 441 if (ol_flags & PKT_TX_TCP_SEG) { 442 psd_hdr.len = 0; 443 } else { 444 psd_hdr.len = ipv6_hdr->payload_len; 445 } 446 447 sum = __rte_raw_cksum(ipv6_hdr->src_addr, 448 sizeof(ipv6_hdr->src_addr) + sizeof(ipv6_hdr->dst_addr), 449 0); 450 sum = __rte_raw_cksum(&psd_hdr, sizeof(psd_hdr), sum); 451 return __rte_raw_cksum_reduce(sum); 452 } 453 454 /** 455 * Process the IPv6 UDP or TCP checksum. 456 * 457 * The IPv4 header should not contains options. The layer 4 checksum 458 * must be set to 0 in the packet by the caller. 459 * 460 * @param ipv6_hdr 461 * The pointer to the contiguous IPv6 header. 462 * @param l4_hdr 463 * The pointer to the beginning of the L4 header. 464 * @return 465 * The complemented checksum to set in the IP packet. 466 */ 467 static inline uint16_t 468 rte_ipv6_udptcp_cksum(const struct ipv6_hdr *ipv6_hdr, const void *l4_hdr) 469 { 470 uint32_t cksum; 471 uint32_t l4_len; 472 473 l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); 474 475 cksum = rte_raw_cksum(l4_hdr, l4_len); 476 cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); 477 478 cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); 479 cksum = (~cksum) & 0xffff; 480 if (cksum == 0) 481 cksum = 0xffff; 482 483 return cksum; 484 } 485 486 #ifdef __cplusplus 487 } 488 #endif 489 490 #endif /* _RTE_IP_H_ */ 491