On 1/4/2022 9:10 PM, Li, Xiaoyun wrote: > Hi > >> -----Original Message----- >> From: Li, Xiaoyun >> Sent: Tuesday, January 4, 2022 15:19 >> To: Singh, Aman Deep; Yigit, Ferruh >> ;olivier.matz@6wind.com; >> mb@smartsharesystems.com; Ananyev, Konstantin >> ;stephen@networkplumber.org; >> Medvedkin, Vladimir >> Cc:dev@dpdk.org >> Subject: RE: [PATCH v4 1/2] net: add functions to calculate UDP/TCP cksum in >> mbuf >> >> Hi >> >>> -----Original Message----- >>> From: Singh, Aman Deep >>> Sent: Wednesday, December 15, 2021 11:34 >>> To: Li, Xiaoyun; Yigit, Ferruh >>> ;olivier.matz@6wind.com; >>> mb@smartsharesystems.com; Ananyev, Konstantin >>> ;stephen@networkplumber.org; >> Medvedkin, >>> Vladimir >>> Cc:dev@dpdk.org >>> Subject: Re: [PATCH v4 1/2] net: add functions to calculate UDP/TCP >>> cksum in mbuf >>> >>> >>> On 12/3/2021 5:08 PM, Xiaoyun Li wrote: >>>> Add functions to call rte_raw_cksum_mbuf() to calculate IPv4/6 >>>> UDP/TCP checksum in mbuf which can be over multi-segments. >>>> >>>> Signed-off-by: Xiaoyun Li Acked-by: Aman Singh >>>> --- >>>> doc/guides/rel_notes/release_22_03.rst | 10 ++ >>>> lib/net/rte_ip.h | 186 +++++++++++++++++++++++++ >>>> lib/net/version.map | 10 ++ >>>> 3 files changed, 206 insertions(+) >>>> >>>> diff --git a/doc/guides/rel_notes/release_22_03.rst >>>> b/doc/guides/rel_notes/release_22_03.rst >>>> index 6d99d1eaa9..7a082c4427 100644 >>>> --- a/doc/guides/rel_notes/release_22_03.rst >>>> +++ b/doc/guides/rel_notes/release_22_03.rst >>>> @@ -55,6 +55,13 @@ New Features >>>> Also, make sure to start the actual text at the margin. >>>> ======================================================= >>>> >>>> +* **Added functions to calculate UDP/TCP checksum in mbuf.** >>>> + * Added the following functions to calculate UDP/TCP checksum of >>> packets >>>> + which can be over multi-segments: >>>> + - ``rte_ipv4_udptcp_cksum_mbuf()`` >>>> + - ``rte_ipv4_udptcp_cksum_mbuf_verify()`` >>>> + - ``rte_ipv6_udptcp_cksum_mbuf()`` >>>> + - ``rte_ipv6_udptcp_cksum_mbuf_verify()`` >>>> >>>> Removed Items >>>> ------------- >>>> @@ -84,6 +91,9 @@ API Changes >>>> Also, make sure to start the actual text at the margin. >>>> ======================================================= >>>> >>>> +* net: added experimental functions >>>> +``rte_ipv4_udptcp_cksum_mbuf()``, >>>> + ``rte_ipv4_udptcp_cksum_mbuf_verify()``, >>>> +``rte_ipv6_udptcp_cksum_mbuf()``, >>>> + ``rte_ipv6_udptcp_cksum_mbuf_verify()`` >>>> >>>> ABI Changes >>>> ----------- >>>> diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h index >>>> c575250852..534f401d26 100644 >>>> --- a/lib/net/rte_ip.h >>>> +++ b/lib/net/rte_ip.h >>>> @@ -400,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); >>> At times, even after above operation "cksum" might stay above 16-bits, >>> ex "cksum = 0x1FFFF" to start with. >>> Can we consider using "return __rte_raw_cksum_reduce(cksum);" >> Will use it in next version. Thanks. >> >> Also, not related to this patch. It means that __rte_ipv4_udptcp_cksum and >> __rte_ipv6_udptcp_cksum have the same issue, right? >> Should anyone fix that? > Forgot the intent here. > rte_raw_cksum_mbuf() already calls __rte_raw_cksum_reduce(). > So actually, it's a result of uint16_t + uint16_t. So it's impossible of your case. There's no need to call __rte_raw_cksum_reduce(). Got it, Thanks. With u16 + u16, max 1-bit overflow only possible. So effective operation here reduces to- cksum = ((cksum & 0x10000) >> 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. >>>> * >>>> @@ -426,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; >>> cksum other than 0xffff, should return error. Is that the intent or I >>> am missing something obvious. >> This is the intent. This function is to verify if the cksum in the packet is correct. >> >> It's different from calling rte_ipv4/6_udptcp_cksum_mbuf(). When calling >> rte_ipv4/6_udptcp_cksum_mbuf(), you need to set the cksum in udp/tcp >> header as 0. Then calculate the cksum. >> >> But here, user should directly call this function with the original packet. Then >> if the udp/tcp cksum is correct, after the calculation (please note that, this is >> calling __rte_ipv4_udptcp_cksum_mbuf(), so the result needs to be ~), it >> should be 0xffff, namely, ~cksum = 0 which means cksum is correct. You can >> see rte_ipv4/6_udptcp_cksum_verify() is doing the same. >> >>>> + >>>> + return 0; >>>> +} >>>> + >>>> /** >>>> * IPv6 Header >>>> */ >>>> @@ -538,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); >>> Same, please check if we can opt for __rte_raw_cksum_reduce(cksum) >>>> + >>>> + 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. >>>> * >>>> @@ -565,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 >>>> diff --git a/lib/net/version.map b/lib/net/version.map index >>>> 4f4330d1c4..0f2aacdef8 100644 >>>> --- a/lib/net/version.map >>>> +++ b/lib/net/version.map >>>> @@ -12,3 +12,13 @@ DPDK_22 { >>>> >>>> local: *; >>>> }; >>>> + >>>> +EXPERIMENTAL { >>>> + global: >>>> + >>>> + # added in 22.03 >>>> + rte_ipv4_udptcp_cksum_mbuf; >>>> + rte_ipv4_udptcp_cksum_mbuf_verify; >>>> + rte_ipv6_udptcp_cksum_mbuf; >>>> + rte_ipv6_udptcp_cksum_mbuf_verify; >>>> +};