11a2b549bSRobin Jarry /* SPDX-License-Identifier: BSD-3-Clause 21a2b549bSRobin Jarry * Copyright(c) 1982, 1986, 1990, 1993 31a2b549bSRobin Jarry * The Regents of the University of California. 41a2b549bSRobin Jarry * Copyright(c) 2010-2014 Intel Corporation. 51a2b549bSRobin Jarry * Copyright(c) 2014 6WIND S.A. 61a2b549bSRobin Jarry * All rights reserved. 71a2b549bSRobin Jarry */ 81a2b549bSRobin Jarry 91a2b549bSRobin Jarry #ifndef _RTE_IP4_H_ 101a2b549bSRobin Jarry #define _RTE_IP4_H_ 111a2b549bSRobin Jarry 121a2b549bSRobin Jarry /** 131a2b549bSRobin Jarry * @file 141a2b549bSRobin Jarry * 151a2b549bSRobin Jarry * IPv4-related defines 161a2b549bSRobin Jarry */ 171a2b549bSRobin Jarry 181a2b549bSRobin Jarry #include <stdint.h> 191a2b549bSRobin Jarry 201a2b549bSRobin Jarry #ifdef RTE_EXEC_ENV_WINDOWS 211a2b549bSRobin Jarry #include <ws2tcpip.h> 221a2b549bSRobin Jarry #else 231a2b549bSRobin Jarry #include <sys/socket.h> 241a2b549bSRobin Jarry #include <sys/types.h> 251a2b549bSRobin Jarry #include <netinet/in.h> 261a2b549bSRobin Jarry #include <arpa/inet.h> 271a2b549bSRobin Jarry #include <netinet/ip.h> 281a2b549bSRobin Jarry #include <netinet/ip6.h> 291a2b549bSRobin Jarry #endif 301a2b549bSRobin Jarry 311a2b549bSRobin Jarry #include <rte_byteorder.h> 321a2b549bSRobin Jarry #include <rte_cksum.h> 331a2b549bSRobin Jarry #include <rte_mbuf.h> 341a2b549bSRobin Jarry 351a2b549bSRobin Jarry #ifdef __cplusplus 361a2b549bSRobin Jarry extern "C" { 371a2b549bSRobin Jarry #endif 381a2b549bSRobin Jarry 391a2b549bSRobin Jarry /** 401a2b549bSRobin Jarry * IPv4 Header 411a2b549bSRobin Jarry */ 42*fba98755SAndre Muezerie struct __rte_aligned(2) __rte_packed_begin rte_ipv4_hdr { 431a2b549bSRobin Jarry __extension__ 441a2b549bSRobin Jarry union { 451a2b549bSRobin Jarry uint8_t version_ihl; /**< version and header length */ 461a2b549bSRobin Jarry struct { 471a2b549bSRobin Jarry #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 481a2b549bSRobin Jarry uint8_t ihl:4; /**< header length */ 491a2b549bSRobin Jarry uint8_t version:4; /**< version */ 501a2b549bSRobin Jarry #elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN 511a2b549bSRobin Jarry uint8_t version:4; /**< version */ 521a2b549bSRobin Jarry uint8_t ihl:4; /**< header length */ 531a2b549bSRobin Jarry #endif 541a2b549bSRobin Jarry }; 551a2b549bSRobin Jarry }; 561a2b549bSRobin Jarry uint8_t type_of_service; /**< type of service */ 571a2b549bSRobin Jarry rte_be16_t total_length; /**< length of packet */ 581a2b549bSRobin Jarry rte_be16_t packet_id; /**< packet ID */ 591a2b549bSRobin Jarry rte_be16_t fragment_offset; /**< fragmentation offset */ 601a2b549bSRobin Jarry uint8_t time_to_live; /**< time to live */ 611a2b549bSRobin Jarry uint8_t next_proto_id; /**< protocol ID */ 621a2b549bSRobin Jarry rte_be16_t hdr_checksum; /**< header checksum */ 631a2b549bSRobin Jarry rte_be32_t src_addr; /**< source address */ 641a2b549bSRobin Jarry rte_be32_t dst_addr; /**< destination address */ 65*fba98755SAndre Muezerie } __rte_packed_end; 661a2b549bSRobin Jarry 671a2b549bSRobin Jarry /** Create IPv4 address */ 681a2b549bSRobin Jarry #define RTE_IPV4(a, b, c, d) ((uint32_t)(((a) & 0xff) << 24) | \ 691a2b549bSRobin Jarry (((b) & 0xff) << 16) | \ 701a2b549bSRobin Jarry (((c) & 0xff) << 8) | \ 711a2b549bSRobin Jarry ((d) & 0xff)) 721a2b549bSRobin Jarry 731a2b549bSRobin Jarry /** Maximal IPv4 packet length (including a header) */ 741a2b549bSRobin Jarry #define RTE_IPV4_MAX_PKT_LEN 65535 751a2b549bSRobin Jarry 761a2b549bSRobin Jarry /** Internet header length mask for version_ihl field */ 771a2b549bSRobin Jarry #define RTE_IPV4_HDR_IHL_MASK (0x0f) 781a2b549bSRobin Jarry /** 791a2b549bSRobin Jarry * Internet header length field multiplier (IHL field specifies overall header 801a2b549bSRobin Jarry * length in number of 4-byte words) 811a2b549bSRobin Jarry */ 821a2b549bSRobin Jarry #define RTE_IPV4_IHL_MULTIPLIER (4) 831a2b549bSRobin Jarry 841a2b549bSRobin Jarry /* Type of Service fields */ 851a2b549bSRobin Jarry #define RTE_IPV4_HDR_DSCP_MASK (0xfc) 861a2b549bSRobin Jarry #define RTE_IPV4_HDR_ECN_MASK (0x03) 871a2b549bSRobin Jarry #define RTE_IPV4_HDR_ECN_CE RTE_IPV4_HDR_ECN_MASK 881a2b549bSRobin Jarry 891a2b549bSRobin Jarry /* Fragment Offset * Flags. */ 901a2b549bSRobin Jarry #define RTE_IPV4_HDR_DF_SHIFT 14 911a2b549bSRobin Jarry #define RTE_IPV4_HDR_MF_SHIFT 13 921a2b549bSRobin Jarry #define RTE_IPV4_HDR_FO_SHIFT 3 931a2b549bSRobin Jarry 941a2b549bSRobin Jarry #define RTE_IPV4_HDR_DF_FLAG (1 << RTE_IPV4_HDR_DF_SHIFT) 951a2b549bSRobin Jarry #define RTE_IPV4_HDR_MF_FLAG (1 << RTE_IPV4_HDR_MF_SHIFT) 961a2b549bSRobin Jarry 971a2b549bSRobin Jarry #define RTE_IPV4_HDR_OFFSET_MASK ((1 << RTE_IPV4_HDR_MF_SHIFT) - 1) 981a2b549bSRobin Jarry 991a2b549bSRobin Jarry #define RTE_IPV4_HDR_OFFSET_UNITS 8 1001a2b549bSRobin Jarry 1011a2b549bSRobin Jarry /* IPv4 options */ 1021a2b549bSRobin Jarry #define RTE_IPV4_HDR_OPT_EOL 0 1031a2b549bSRobin Jarry #define RTE_IPV4_HDR_OPT_NOP 1 1041a2b549bSRobin Jarry #define RTE_IPV4_HDR_OPT_COPIED(v) ((v) & 0x80) 1051a2b549bSRobin Jarry #define RTE_IPV4_HDR_OPT_MAX_LEN 40 1061a2b549bSRobin Jarry 1071a2b549bSRobin Jarry /* 1081a2b549bSRobin Jarry * IPv4 address types 1091a2b549bSRobin Jarry */ 1101a2b549bSRobin Jarry #define RTE_IPV4_ANY ((uint32_t)0x00000000) /**< 0.0.0.0 */ 1111a2b549bSRobin Jarry #define RTE_IPV4_LOOPBACK ((uint32_t)0x7f000001) /**< 127.0.0.1 */ 1121a2b549bSRobin Jarry #define RTE_IPV4_BROADCAST ((uint32_t)0xe0000000) /**< 224.0.0.0 */ 1131a2b549bSRobin Jarry #define RTE_IPV4_ALLHOSTS_GROUP ((uint32_t)0xe0000001) /**< 224.0.0.1 */ 1141a2b549bSRobin Jarry #define RTE_IPV4_ALLRTRS_GROUP ((uint32_t)0xe0000002) /**< 224.0.0.2 */ 1151a2b549bSRobin Jarry #define RTE_IPV4_MAX_LOCAL_GROUP ((uint32_t)0xe00000ff) /**< 224.0.0.255 */ 1161a2b549bSRobin Jarry 1171a2b549bSRobin Jarry /* 1181a2b549bSRobin Jarry * IPv4 Multicast-related macros 1191a2b549bSRobin Jarry */ 1201a2b549bSRobin Jarry #define RTE_IPV4_MIN_MCAST \ 1211a2b549bSRobin Jarry RTE_IPV4(224, 0, 0, 0) /**< Minimal IPv4-multicast address */ 1221a2b549bSRobin Jarry #define RTE_IPV4_MAX_MCAST \ 1231a2b549bSRobin Jarry RTE_IPV4(239, 255, 255, 255) /**< Maximum IPv4 multicast address */ 1241a2b549bSRobin Jarry 1251a2b549bSRobin Jarry #define RTE_IS_IPV4_MCAST(x) \ 1261a2b549bSRobin Jarry ((x) >= RTE_IPV4_MIN_MCAST && (x) <= RTE_IPV4_MAX_MCAST) 1271a2b549bSRobin Jarry /**< check if IPv4 address is multicast */ 1281a2b549bSRobin Jarry 1291a2b549bSRobin Jarry /* IPv4 default fields values */ 1301a2b549bSRobin Jarry #define RTE_IPV4_MIN_IHL (0x5) 1311a2b549bSRobin Jarry #define RTE_IPV4_VHL_DEF ((IPVERSION << 4) | RTE_IPV4_MIN_IHL) 1321a2b549bSRobin Jarry 1331a2b549bSRobin Jarry /** 1341a2b549bSRobin Jarry * Get the length of an IPv4 header. 1351a2b549bSRobin Jarry * 1361a2b549bSRobin Jarry * @param ipv4_hdr 1371a2b549bSRobin Jarry * Pointer to the IPv4 header. 1381a2b549bSRobin Jarry * @return 1391a2b549bSRobin Jarry * The length of the IPv4 header (with options if present) in bytes. 1401a2b549bSRobin Jarry */ 1411a2b549bSRobin Jarry static inline uint8_t 1421a2b549bSRobin Jarry rte_ipv4_hdr_len(const struct rte_ipv4_hdr *ipv4_hdr) 1431a2b549bSRobin Jarry { 1441a2b549bSRobin Jarry return (uint8_t)((ipv4_hdr->version_ihl & RTE_IPV4_HDR_IHL_MASK) * 1451a2b549bSRobin Jarry RTE_IPV4_IHL_MULTIPLIER); 1461a2b549bSRobin Jarry } 1471a2b549bSRobin Jarry 1481a2b549bSRobin Jarry /** 1491a2b549bSRobin Jarry * Process the IPv4 checksum of an IPv4 header. 1501a2b549bSRobin Jarry * 1511a2b549bSRobin Jarry * The checksum field must be set to 0 by the caller. 1521a2b549bSRobin Jarry * 1531a2b549bSRobin Jarry * @param ipv4_hdr 1541a2b549bSRobin Jarry * The pointer to the contiguous IPv4 header. 1551a2b549bSRobin Jarry * @return 1561a2b549bSRobin Jarry * The complemented checksum to set in the IP packet. 1571a2b549bSRobin Jarry */ 1581a2b549bSRobin Jarry static inline uint16_t 1591a2b549bSRobin Jarry rte_ipv4_cksum(const struct rte_ipv4_hdr *ipv4_hdr) 1601a2b549bSRobin Jarry { 1611a2b549bSRobin Jarry uint16_t cksum; 1621a2b549bSRobin Jarry cksum = rte_raw_cksum(ipv4_hdr, rte_ipv4_hdr_len(ipv4_hdr)); 1631a2b549bSRobin Jarry return (uint16_t)~cksum; 1641a2b549bSRobin Jarry } 1651a2b549bSRobin Jarry 1661a2b549bSRobin Jarry /** 167f9e1d67fSBruce Richardson * @warning 168f9e1d67fSBruce Richardson * @b EXPERIMENTAL: this API may change without prior notice. 169f9e1d67fSBruce Richardson * 170f9e1d67fSBruce Richardson * Process the IPv4 checksum of an IPv4 header without any extensions. 171f9e1d67fSBruce Richardson * 172f9e1d67fSBruce Richardson * The checksum field does NOT have to be set by the caller, the field 173f9e1d67fSBruce Richardson * is skipped by the calculation. 174f9e1d67fSBruce Richardson * 175f9e1d67fSBruce Richardson * @param ipv4_hdr 176f9e1d67fSBruce Richardson * The pointer to the contiguous IPv4 header. 177f9e1d67fSBruce Richardson * @return 178f9e1d67fSBruce Richardson * The complemented checksum to set in the IP packet. 179f9e1d67fSBruce Richardson */ 180f9e1d67fSBruce Richardson __rte_experimental 181f9e1d67fSBruce Richardson static inline uint16_t 182f9e1d67fSBruce Richardson rte_ipv4_cksum_simple(const struct rte_ipv4_hdr *ipv4_hdr) 183f9e1d67fSBruce Richardson { 184f9e1d67fSBruce Richardson const uint16_t *v16_h; 185f9e1d67fSBruce Richardson uint32_t ip_cksum; 186f9e1d67fSBruce Richardson 187f9e1d67fSBruce Richardson /* 188f9e1d67fSBruce Richardson * Compute the sum of successive 16-bit words of the IPv4 header, 189f9e1d67fSBruce Richardson * skipping the checksum field of the header. 190f9e1d67fSBruce Richardson */ 191c14fba68SDavid Marchand v16_h = (const uint16_t *)ipv4_hdr; 192f9e1d67fSBruce Richardson ip_cksum = v16_h[0] + v16_h[1] + v16_h[2] + v16_h[3] + 193f9e1d67fSBruce Richardson v16_h[4] + v16_h[6] + v16_h[7] + v16_h[8] + v16_h[9]; 194f9e1d67fSBruce Richardson 195f9e1d67fSBruce Richardson /* reduce 32 bit checksum to 16 bits and complement it */ 196f9e1d67fSBruce Richardson ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16); 197f9e1d67fSBruce Richardson ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16); 198f9e1d67fSBruce Richardson return (uint16_t)(~ip_cksum); 199f9e1d67fSBruce Richardson } 200f9e1d67fSBruce Richardson 201f9e1d67fSBruce Richardson /** 2021a2b549bSRobin Jarry * Process the pseudo-header checksum of an IPv4 header. 2031a2b549bSRobin Jarry * 2041a2b549bSRobin Jarry * The checksum field must be set to 0 by the caller. 2051a2b549bSRobin Jarry * 2061a2b549bSRobin Jarry * Depending on the ol_flags, the pseudo-header checksum expected by the 2071a2b549bSRobin Jarry * drivers is not the same. For instance, when TSO is enabled, the IP 2081a2b549bSRobin Jarry * payload length must not be included in the packet. 2091a2b549bSRobin Jarry * 2101a2b549bSRobin Jarry * When ol_flags is 0, it computes the standard pseudo-header checksum. 2111a2b549bSRobin Jarry * 2121a2b549bSRobin Jarry * @param ipv4_hdr 2131a2b549bSRobin Jarry * The pointer to the contiguous IPv4 header. 2141a2b549bSRobin Jarry * @param ol_flags 2151a2b549bSRobin Jarry * The ol_flags of the associated mbuf. 2161a2b549bSRobin Jarry * @return 2171a2b549bSRobin Jarry * The non-complemented checksum to set in the L4 header. 2181a2b549bSRobin Jarry */ 2191a2b549bSRobin Jarry static inline uint16_t 2201a2b549bSRobin Jarry rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags) 2211a2b549bSRobin Jarry { 2221a2b549bSRobin Jarry struct ipv4_psd_header { 2231a2b549bSRobin Jarry uint32_t src_addr; /* IP address of source host. */ 2241a2b549bSRobin Jarry uint32_t dst_addr; /* IP address of destination host. */ 2251a2b549bSRobin Jarry uint8_t zero; /* zero. */ 2261a2b549bSRobin Jarry uint8_t proto; /* L4 protocol type. */ 2271a2b549bSRobin Jarry uint16_t len; /* L4 length. */ 2281a2b549bSRobin Jarry } psd_hdr; 2291a2b549bSRobin Jarry 2301a2b549bSRobin Jarry uint32_t l3_len; 2311a2b549bSRobin Jarry 2321a2b549bSRobin Jarry psd_hdr.src_addr = ipv4_hdr->src_addr; 2331a2b549bSRobin Jarry psd_hdr.dst_addr = ipv4_hdr->dst_addr; 2341a2b549bSRobin Jarry psd_hdr.zero = 0; 2351a2b549bSRobin Jarry psd_hdr.proto = ipv4_hdr->next_proto_id; 2361a2b549bSRobin Jarry if (ol_flags & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG)) { 2371a2b549bSRobin Jarry psd_hdr.len = 0; 2381a2b549bSRobin Jarry } else { 2391a2b549bSRobin Jarry l3_len = rte_be_to_cpu_16(ipv4_hdr->total_length); 2401a2b549bSRobin Jarry psd_hdr.len = rte_cpu_to_be_16((uint16_t)(l3_len - 2411a2b549bSRobin Jarry rte_ipv4_hdr_len(ipv4_hdr))); 2421a2b549bSRobin Jarry } 2431a2b549bSRobin Jarry return rte_raw_cksum(&psd_hdr, sizeof(psd_hdr)); 2441a2b549bSRobin Jarry } 2451a2b549bSRobin Jarry 2461a2b549bSRobin Jarry /** 2471a2b549bSRobin Jarry * @internal Calculate the non-complemented IPv4 L4 checksum 2481a2b549bSRobin Jarry */ 2491a2b549bSRobin Jarry static inline uint16_t 2501a2b549bSRobin Jarry __rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) 2511a2b549bSRobin Jarry { 2521a2b549bSRobin Jarry uint32_t cksum; 2531a2b549bSRobin Jarry uint32_t l3_len, l4_len; 2541a2b549bSRobin Jarry uint8_t ip_hdr_len; 2551a2b549bSRobin Jarry 2561a2b549bSRobin Jarry ip_hdr_len = rte_ipv4_hdr_len(ipv4_hdr); 2571a2b549bSRobin Jarry l3_len = rte_be_to_cpu_16(ipv4_hdr->total_length); 2581a2b549bSRobin Jarry if (l3_len < ip_hdr_len) 2591a2b549bSRobin Jarry return 0; 2601a2b549bSRobin Jarry 2611a2b549bSRobin Jarry l4_len = l3_len - ip_hdr_len; 2621a2b549bSRobin Jarry 2631a2b549bSRobin Jarry cksum = rte_raw_cksum(l4_hdr, l4_len); 2641a2b549bSRobin Jarry cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); 2651a2b549bSRobin Jarry 2661a2b549bSRobin Jarry cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); 2671a2b549bSRobin Jarry 2681a2b549bSRobin Jarry return (uint16_t)cksum; 2691a2b549bSRobin Jarry } 2701a2b549bSRobin Jarry 2711a2b549bSRobin Jarry /** 2721a2b549bSRobin Jarry * Process the IPv4 UDP or TCP checksum. 2731a2b549bSRobin Jarry * 2741a2b549bSRobin Jarry * The layer 4 checksum must be set to 0 in the L4 header by the caller. 2751a2b549bSRobin Jarry * 2761a2b549bSRobin Jarry * @param ipv4_hdr 2771a2b549bSRobin Jarry * The pointer to the contiguous IPv4 header. 2781a2b549bSRobin Jarry * @param l4_hdr 2791a2b549bSRobin Jarry * The pointer to the beginning of the L4 header. 2801a2b549bSRobin Jarry * @return 2811a2b549bSRobin Jarry * The complemented checksum to set in the L4 header. 2821a2b549bSRobin Jarry */ 2831a2b549bSRobin Jarry static inline uint16_t 2841a2b549bSRobin Jarry rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) 2851a2b549bSRobin Jarry { 2861a2b549bSRobin Jarry uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); 2871a2b549bSRobin Jarry 2881a2b549bSRobin Jarry cksum = ~cksum; 2891a2b549bSRobin Jarry 2901a2b549bSRobin Jarry /* 2911a2b549bSRobin Jarry * Per RFC 768: If the computed checksum is zero for UDP, 2921a2b549bSRobin Jarry * it is transmitted as all ones 2931a2b549bSRobin Jarry * (the equivalent in one's complement arithmetic). 2941a2b549bSRobin Jarry */ 2951a2b549bSRobin Jarry if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) 2961a2b549bSRobin Jarry cksum = 0xffff; 2971a2b549bSRobin Jarry 2981a2b549bSRobin Jarry return cksum; 2991a2b549bSRobin Jarry } 3001a2b549bSRobin Jarry 3011a2b549bSRobin Jarry /** 3021a2b549bSRobin Jarry * @internal Calculate the non-complemented IPv4 L4 checksum of a packet 3031a2b549bSRobin Jarry */ 3041a2b549bSRobin Jarry static inline uint16_t 3051a2b549bSRobin Jarry __rte_ipv4_udptcp_cksum_mbuf(const struct rte_mbuf *m, 3061a2b549bSRobin Jarry const struct rte_ipv4_hdr *ipv4_hdr, 3071a2b549bSRobin Jarry uint16_t l4_off) 3081a2b549bSRobin Jarry { 3091a2b549bSRobin Jarry uint16_t raw_cksum; 3101a2b549bSRobin Jarry uint32_t cksum; 3111a2b549bSRobin Jarry uint16_t len; 3121a2b549bSRobin Jarry 3131a2b549bSRobin Jarry if (unlikely(l4_off > m->pkt_len)) 3141a2b549bSRobin Jarry return 0; /* invalid params, return a dummy value */ 3151a2b549bSRobin Jarry 3161a2b549bSRobin Jarry len = rte_be_to_cpu_16(ipv4_hdr->total_length) - (uint16_t)rte_ipv4_hdr_len(ipv4_hdr); 3171a2b549bSRobin Jarry 3181a2b549bSRobin Jarry if (rte_raw_cksum_mbuf(m, l4_off, len, &raw_cksum)) 3191a2b549bSRobin Jarry return 0; 3201a2b549bSRobin Jarry 3211a2b549bSRobin Jarry cksum = raw_cksum + rte_ipv4_phdr_cksum(ipv4_hdr, 0); 3221a2b549bSRobin Jarry 3231a2b549bSRobin Jarry cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); 3241a2b549bSRobin Jarry 3251a2b549bSRobin Jarry return (uint16_t)cksum; 3261a2b549bSRobin Jarry } 3271a2b549bSRobin Jarry 3281a2b549bSRobin Jarry /** 3291a2b549bSRobin Jarry * Compute the IPv4 UDP/TCP checksum of a packet. 3301a2b549bSRobin Jarry * 3311a2b549bSRobin Jarry * @param m 3321a2b549bSRobin Jarry * The pointer to the mbuf. 3331a2b549bSRobin Jarry * @param ipv4_hdr 3341a2b549bSRobin Jarry * The pointer to the contiguous IPv4 header. 3351a2b549bSRobin Jarry * @param l4_off 3361a2b549bSRobin Jarry * The offset in bytes to start L4 checksum. 3371a2b549bSRobin Jarry * @return 3381a2b549bSRobin Jarry * The complemented checksum to set in the L4 header. 3391a2b549bSRobin Jarry */ 3401a2b549bSRobin Jarry static inline uint16_t 3411a2b549bSRobin Jarry rte_ipv4_udptcp_cksum_mbuf(const struct rte_mbuf *m, 3421a2b549bSRobin Jarry const struct rte_ipv4_hdr *ipv4_hdr, uint16_t l4_off) 3431a2b549bSRobin Jarry { 3441a2b549bSRobin Jarry uint16_t cksum = __rte_ipv4_udptcp_cksum_mbuf(m, ipv4_hdr, l4_off); 3451a2b549bSRobin Jarry 3461a2b549bSRobin Jarry cksum = ~cksum; 3471a2b549bSRobin Jarry 3481a2b549bSRobin Jarry /* 3491a2b549bSRobin Jarry * Per RFC 768: If the computed checksum is zero for UDP, 3501a2b549bSRobin Jarry * it is transmitted as all ones 3511a2b549bSRobin Jarry * (the equivalent in one's complement arithmetic). 3521a2b549bSRobin Jarry */ 3531a2b549bSRobin Jarry if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) 3541a2b549bSRobin Jarry cksum = 0xffff; 3551a2b549bSRobin Jarry 3561a2b549bSRobin Jarry return cksum; 3571a2b549bSRobin Jarry } 3581a2b549bSRobin Jarry 3591a2b549bSRobin Jarry /** 3601a2b549bSRobin Jarry * Validate the IPv4 UDP or TCP checksum. 3611a2b549bSRobin Jarry * 3621a2b549bSRobin Jarry * In case of UDP, the caller must first check if udp_hdr->dgram_cksum is 0 3631a2b549bSRobin Jarry * (i.e. no checksum). 3641a2b549bSRobin Jarry * 3651a2b549bSRobin Jarry * @param ipv4_hdr 3661a2b549bSRobin Jarry * The pointer to the contiguous IPv4 header. 3671a2b549bSRobin Jarry * @param l4_hdr 3681a2b549bSRobin Jarry * The pointer to the beginning of the L4 header. 3691a2b549bSRobin Jarry * @return 3701a2b549bSRobin Jarry * Return 0 if the checksum is correct, else -1. 3711a2b549bSRobin Jarry */ 3721a2b549bSRobin Jarry static inline int 3731a2b549bSRobin Jarry rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, 3741a2b549bSRobin Jarry const void *l4_hdr) 3751a2b549bSRobin Jarry { 3761a2b549bSRobin Jarry uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); 3771a2b549bSRobin Jarry 3781a2b549bSRobin Jarry if (cksum != 0xffff) 3791a2b549bSRobin Jarry return -1; 3801a2b549bSRobin Jarry 3811a2b549bSRobin Jarry return 0; 3821a2b549bSRobin Jarry } 3831a2b549bSRobin Jarry 3841a2b549bSRobin Jarry /** 3851a2b549bSRobin Jarry * Verify the IPv4 UDP/TCP checksum of a packet. 3861a2b549bSRobin Jarry * 3871a2b549bSRobin Jarry * In case of UDP, the caller must first check if udp_hdr->dgram_cksum is 0 3881a2b549bSRobin Jarry * (i.e. no checksum). 3891a2b549bSRobin Jarry * 3901a2b549bSRobin Jarry * @param m 3911a2b549bSRobin Jarry * The pointer to the mbuf. 3921a2b549bSRobin Jarry * @param ipv4_hdr 3931a2b549bSRobin Jarry * The pointer to the contiguous IPv4 header. 3941a2b549bSRobin Jarry * @param l4_off 3951a2b549bSRobin Jarry * The offset in bytes to start L4 checksum. 3961a2b549bSRobin Jarry * @return 3971a2b549bSRobin Jarry * Return 0 if the checksum is correct, else -1. 3981a2b549bSRobin Jarry */ 3991a2b549bSRobin Jarry static inline int 4001a2b549bSRobin Jarry rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, 4011a2b549bSRobin Jarry const struct rte_ipv4_hdr *ipv4_hdr, 4021a2b549bSRobin Jarry uint16_t l4_off) 4031a2b549bSRobin Jarry { 4041a2b549bSRobin Jarry uint16_t cksum = __rte_ipv4_udptcp_cksum_mbuf(m, ipv4_hdr, l4_off); 4051a2b549bSRobin Jarry 4061a2b549bSRobin Jarry if (cksum != 0xffff) 4071a2b549bSRobin Jarry return -1; 4081a2b549bSRobin Jarry 4091a2b549bSRobin Jarry return 0; 4101a2b549bSRobin Jarry } 4111a2b549bSRobin Jarry 4121a2b549bSRobin Jarry #ifdef __cplusplus 4131a2b549bSRobin Jarry } 4141a2b549bSRobin Jarry #endif 4151a2b549bSRobin Jarry 4161a2b549bSRobin Jarry #endif /* _RTE_IP_H_ */ 417