X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Fnet%2Frte_ip.h;h=534f401d260a4cc3fb8b3eae7d78cfa5b911e2cd;hb=d178f693bbfe07506d6e3e23a3ce9c34ee554444;hp=05948b69b7ffac279c31354bd323ae39fb2d1865;hpb=45a08ef55e4409043ed405135fb5a728408d65b7;p=dpdk.git diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h index 05948b69b7..534f401d26 100644 --- a/lib/net/rte_ip.h +++ b/lib/net/rte_ip.h @@ -25,6 +25,7 @@ #include #include #include +#include #endif #include @@ -38,7 +39,19 @@ extern "C" { * IPv4 Header */ struct rte_ipv4_hdr { - uint8_t version_ihl; /**< version and header length */ + __extension__ + union { + uint8_t version_ihl; /**< version and header length */ + struct { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint8_t ihl:4; /**< header length */ + uint8_t version:4; /**< version */ +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint8_t version:4; /**< version */ + uint8_t ihl:4; /**< header length */ +#endif + }; + }; uint8_t type_of_service; /**< type of service */ rte_be16_t total_length; /**< length of packet */ rte_be16_t packet_id; /**< packet ID */ @@ -141,29 +154,18 @@ rte_ipv4_hdr_len(const struct rte_ipv4_hdr *ipv4_hdr) static inline uint32_t __rte_raw_cksum(const void *buf, size_t len, uint32_t sum) { - /* workaround gcc strict-aliasing warning */ - uintptr_t ptr = (uintptr_t)buf; + /* extend strict-aliasing rules */ typedef uint16_t __attribute__((__may_alias__)) u16_p; - const u16_p *u16_buf = (const u16_p *)ptr; - - while (len >= (sizeof(*u16_buf) * 4)) { - sum += u16_buf[0]; - sum += u16_buf[1]; - sum += u16_buf[2]; - sum += u16_buf[3]; - len -= sizeof(*u16_buf) * 4; - u16_buf += 4; - } - while (len >= sizeof(*u16_buf)) { + const u16_p *u16_buf = (const u16_p *)buf; + const u16_p *end = u16_buf + len / sizeof(*u16_buf); + + for (; u16_buf != end; ++u16_buf) sum += *u16_buf; - len -= sizeof(*u16_buf); - u16_buf += 1; - } - /* if length is in odd bytes */ - if (len == 1) { + /* if length is odd, keeping it byte order independent */ + if (unlikely(len % 2)) { uint16_t left = 0; - *(uint8_t *)&left = *(const uint8_t *)u16_buf; + *(unsigned char *)&left = *(const unsigned char *)end; sum += left; } @@ -333,7 +335,7 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags) psd_hdr.dst_addr = ipv4_hdr->dst_addr; psd_hdr.zero = 0; psd_hdr.proto = ipv4_hdr->next_proto_id; - if (ol_flags & PKT_TX_TCP_SEG) { + if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) { psd_hdr.len = 0; } else { l3_len = rte_be_to_cpu_16(ipv4_hdr->total_length); @@ -371,15 +373,14 @@ __rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) /** * Process the IPv4 UDP or TCP checksum. * - * The IP and layer 4 checksum must be set to 0 in the packet by - * the caller. + * The layer 4 checksum must be set to 0 in the L4 header by the caller. * * @param ipv4_hdr * The pointer to the contiguous IPv4 header. * @param l4_hdr * The pointer to the beginning of the L4 header. * @return - * The complemented checksum to set in the IP packet. + * The complemented checksum to set in the L4 header. */ static inline uint16_t rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) @@ -399,6 +400,65 @@ rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) return cksum; } +/** + * @internal Calculate the non-complemented IPv4 L4 checksum of a packet + */ +static inline uint16_t +__rte_ipv4_udptcp_cksum_mbuf(const struct rte_mbuf *m, + const struct rte_ipv4_hdr *ipv4_hdr, + uint16_t l4_off) +{ + uint16_t raw_cksum; + uint32_t cksum; + + if (l4_off > m->pkt_len) + return 0; + + if (rte_raw_cksum_mbuf(m, l4_off, m->pkt_len - l4_off, &raw_cksum)) + return 0; + + cksum = raw_cksum + rte_ipv4_phdr_cksum(ipv4_hdr, 0); + + cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); + + return (uint16_t)cksum; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Compute the IPv4 UDP/TCP checksum of a packet. + * + * @param m + * The pointer to the mbuf. + * @param ipv4_hdr + * The pointer to the contiguous IPv4 header. + * @param l4_off + * The offset in bytes to start L4 checksum. + * @return + * The complemented checksum to set in the L4 header. + */ +__rte_experimental +static inline uint16_t +rte_ipv4_udptcp_cksum_mbuf(const struct rte_mbuf *m, + const struct rte_ipv4_hdr *ipv4_hdr, uint16_t l4_off) +{ + uint16_t cksum = __rte_ipv4_udptcp_cksum_mbuf(m, ipv4_hdr, l4_off); + + cksum = ~cksum; + + /* + * Per RFC 768: If the computed checksum is zero for UDP, + * it is transmitted as all ones + * (the equivalent in one's complement arithmetic). + */ + if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) + cksum = 0xffff; + + return cksum; +} + /** * Validate the IPv4 UDP or TCP checksum. * @@ -425,6 +485,38 @@ rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, return 0; } +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Verify the IPv4 UDP/TCP checksum of a packet. + * + * In case of UDP, the caller must first check if udp_hdr->dgram_cksum is 0 + * (i.e. no checksum). + * + * @param m + * The pointer to the mbuf. + * @param ipv4_hdr + * The pointer to the contiguous IPv4 header. + * @param l4_off + * The offset in bytes to start L4 checksum. + * @return + * Return 0 if the checksum is correct, else -1. + */ +__rte_experimental +static inline uint16_t +rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, + const struct rte_ipv4_hdr *ipv4_hdr, + uint16_t l4_off) +{ + uint16_t cksum = __rte_ipv4_udptcp_cksum_mbuf(m, ipv4_hdr, l4_off); + + if (cksum != 0xffff) + return -1; + + return 0; +} + /** * IPv6 Header */ @@ -474,7 +566,7 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) } psd_hdr; psd_hdr.proto = (uint32_t)(ipv6_hdr->proto << 24); - if (ol_flags & PKT_TX_TCP_SEG) { + if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) { psd_hdr.len = 0; } else { psd_hdr.len = ipv6_hdr->payload_len; @@ -488,7 +580,7 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) } /** - * @internal Calculate the non-complemented IPv4 L4 checksum + * @internal Calculate the non-complemented IPv6 L4 checksum */ static inline uint16_t __rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) @@ -509,15 +601,15 @@ __rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) /** * Process the IPv6 UDP or TCP checksum. * - * The IPv4 header should not contains options. The layer 4 checksum - * must be set to 0 in the packet by the caller. + * The IPv6 header must not be followed by extension headers. The layer 4 + * checksum must be set to 0 in the L4 header by the caller. * * @param ipv6_hdr * The pointer to the contiguous IPv6 header. * @param l4_hdr * The pointer to the beginning of the L4 header. * @return - * The complemented checksum to set in the IP packet. + * The complemented checksum to set in the L4 header. */ static inline uint16_t rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) @@ -537,6 +629,68 @@ rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) return cksum; } +/** + * @internal Calculate the non-complemented IPv6 L4 checksum of a packet + */ +static inline uint16_t +__rte_ipv6_udptcp_cksum_mbuf(const struct rte_mbuf *m, + const struct rte_ipv6_hdr *ipv6_hdr, + uint16_t l4_off) +{ + uint16_t raw_cksum; + uint32_t cksum; + + if (l4_off > m->pkt_len) + return 0; + + if (rte_raw_cksum_mbuf(m, l4_off, m->pkt_len - l4_off, &raw_cksum)) + return 0; + + cksum = raw_cksum + rte_ipv6_phdr_cksum(ipv6_hdr, 0); + + cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); + + return (uint16_t)cksum; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Process the IPv6 UDP or TCP checksum of a packet. + * + * The IPv6 header must not be followed by extension headers. The layer 4 + * checksum must be set to 0 in the L4 header by the caller. + * + * @param m + * The pointer to the mbuf. + * @param ipv6_hdr + * The pointer to the contiguous IPv6 header. + * @param l4_off + * The offset in bytes to start L4 checksum. + * @return + * The complemented checksum to set in the L4 header. + */ +__rte_experimental +static inline uint16_t +rte_ipv6_udptcp_cksum_mbuf(const struct rte_mbuf *m, + const struct rte_ipv6_hdr *ipv6_hdr, uint16_t l4_off) +{ + uint16_t cksum = __rte_ipv6_udptcp_cksum_mbuf(m, ipv6_hdr, l4_off); + + cksum = ~cksum; + + /* + * Per RFC 768: If the computed checksum is zero for UDP, + * it is transmitted as all ones + * (the equivalent in one's complement arithmetic). + */ + if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP) + cksum = 0xffff; + + return cksum; +} + /** * Validate the IPv6 UDP or TCP checksum. * @@ -564,6 +718,39 @@ rte_ipv6_udptcp_cksum_verify(const struct rte_ipv6_hdr *ipv6_hdr, return 0; } +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Validate the IPv6 UDP or TCP checksum of a packet. + * + * In case of UDP, the caller must first check if udp_hdr->dgram_cksum is 0: + * this is either invalid or means no checksum in some situations. See 8.1 + * (Upper-Layer Checksums) in RFC 8200. + * + * @param m + * The pointer to the mbuf. + * @param ipv6_hdr + * The pointer to the contiguous IPv6 header. + * @param l4_off + * The offset in bytes to start L4 checksum. + * @return + * Return 0 if the checksum is correct, else -1. + */ +__rte_experimental +static inline int +rte_ipv6_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, + const struct rte_ipv6_hdr *ipv6_hdr, + uint16_t l4_off) +{ + uint16_t cksum = __rte_ipv6_udptcp_cksum_mbuf(m, ipv6_hdr, l4_off); + + if (cksum != 0xffff) + return -1; + + return 0; +} + /** IPv6 fragment extension header. */ #define RTE_IPV6_EHDR_MF_SHIFT 0 #define RTE_IPV6_EHDR_MF_MASK 1