From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id 656B15912 for ; Mon, 17 Nov 2014 19:05:18 +0100 (CET) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga102.fm.intel.com with ESMTP; 17 Nov 2014 10:15:34 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.97,862,1389772800"; d="scan'208";a="417695836" Received: from irsmsx154.ger.corp.intel.com ([163.33.192.96]) by FMSMGA003.fm.intel.com with ESMTP; 17 Nov 2014 10:06:17 -0800 Received: from irsmsx105.ger.corp.intel.com ([169.254.7.101]) by IRSMSX154.ger.corp.intel.com ([169.254.12.166]) with mapi id 14.03.0195.001; Mon, 17 Nov 2014 18:15:33 +0000 From: "Ananyev, Konstantin" To: Olivier Matz , "dev@dpdk.org" Thread-Topic: [dpdk-dev] [PATCH v2 09/13] mbuf: introduce new checksum API Thread-Index: AQHQAC1kpOV7OXu9hkWSKdm3t+rlaJxk+bog Date: Mon, 17 Nov 2014 18:15:32 +0000 Message-ID: <2601191342CEEE43887BDE71AB977258213AE563@IRSMSX105.ger.corp.intel.com> References: <1415635166-1364-1-git-send-email-olivier.matz@6wind.com> <1415984609-2484-1-git-send-email-olivier.matz@6wind.com> <1415984609-2484-10-git-send-email-olivier.matz@6wind.com> In-Reply-To: <1415984609-2484-10-git-send-email-olivier.matz@6wind.com> Accept-Language: en-IE, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [163.33.239.180] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Cc: "jigsaw@gmail.com" Subject: Re: [dpdk-dev] [PATCH v2 09/13] mbuf: introduce new checksum API X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 17 Nov 2014 18:05:19 -0000 > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Olivier Matz > Sent: Friday, November 14, 2014 5:03 PM > To: dev@dpdk.org > Cc: jigsaw@gmail.com > Subject: [dpdk-dev] [PATCH v2 09/13] mbuf: introduce new checksum API >=20 > Introduce new functions to calculate checksums. These new functions > are derivated from the ones provided csumonly.c but slightly reworked. > There is still some room for future optimization of these functions > (maybe SSE/AVX, ...). >=20 > This API will be modified in tbe next commits by the introduction of > TSO that requires a different pseudo header checksum to be set in the > packet. >=20 > Signed-off-by: Olivier Matz Acked-by: Konstantin Ananyev Just 2 nits from me: 1) > +static inline uint16_t > +rte_raw_cksum(const char *buf, size_t len) > +{ ... > + while (len >=3D 8) { > + sum +=3D u16[0]; sum +=3D u16[1]; sum +=3D u16[2]; sum +=3D u16[3]; Can you put each expression into a new line? sum +=3D u16[0]; sum +=3D u16[1]; ... To make it easier to read. Or can it be rewritten just like: sum =3D (uint32_t)u16[0] + u16[1] + u16[2] + u16[3]; here? 2)=20 > + while (len >=3D 8) { > + sum +=3D u16[0]; sum +=3D u16[1]; sum +=3D u16[2]; sum +=3D u16[3]; > + len -=3D 8; > + u16 +=3D 4; > + } > + while (len >=3D 2) { > + sum +=3D *u16; > + len -=3D 2; > + u16 +=3D 1; > + } In the code above, probably use sizeof(u16[0]) wherever appropriate. To make things a bit more clearer and consistent. ... while (len >=3D 4 * sizeof(u16[0])) len -=3D 4 * sizeof(u16[0]); u16 +=3D 4;=20 ... Same for second loop. > --- > app/test-pmd/csumonly.c | 133 ++------------------------------- > lib/librte_mbuf/rte_mbuf.h | 3 +- > lib/librte_net/rte_ip.h | 179 +++++++++++++++++++++++++++++++++++++++= ++++++ > 3 files changed, 189 insertions(+), 126 deletions(-) >=20 > diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c > index dda5d9e..39f974d 100644 > --- a/app/test-pmd/csumonly.c > +++ b/app/test-pmd/csumonly.c > @@ -86,137 +86,22 @@ > #define _htons(x) (x) > #endif >=20 > -static inline uint16_t > -get_16b_sum(uint16_t *ptr16, uint32_t nr) > -{ > - uint32_t sum =3D 0; > - while (nr > 1) > - { > - sum +=3D*ptr16; > - nr -=3D sizeof(uint16_t); > - ptr16++; > - if (sum > UINT16_MAX) > - sum -=3D UINT16_MAX; > - } > - > - /* If length is in odd bytes */ > - if (nr) > - sum +=3D *((uint8_t*)ptr16); > - > - sum =3D ((sum & 0xffff0000) >> 16) + (sum & 0xffff); > - sum &=3D 0x0ffff; > - return (uint16_t)sum; > -} > - > -static inline uint16_t > -get_ipv4_cksum(struct ipv4_hdr *ipv4_hdr) > -{ > - uint16_t cksum; > - cksum =3D get_16b_sum((uint16_t*)ipv4_hdr, sizeof(struct ipv4_hdr)); > - return (uint16_t)((cksum =3D=3D 0xffff)?cksum:~cksum); > -} > - > - > -static inline uint16_t > -get_ipv4_psd_sum(struct ipv4_hdr *ip_hdr) > -{ > - /* Pseudo Header for IPv4/UDP/TCP checksum */ > - union ipv4_psd_header { > - struct { > - uint32_t src_addr; /* IP address of source host. */ > - uint32_t dst_addr; /* IP address of destination host(s). */ > - uint8_t zero; /* zero. */ > - uint8_t proto; /* L4 protocol type. */ > - uint16_t len; /* L4 length. */ > - } __attribute__((__packed__)); > - uint16_t u16_arr[0]; > - } psd_hdr; > - > - psd_hdr.src_addr =3D ip_hdr->src_addr; > - psd_hdr.dst_addr =3D ip_hdr->dst_addr; > - psd_hdr.zero =3D 0; > - psd_hdr.proto =3D ip_hdr->next_proto_id; > - psd_hdr.len =3D rte_cpu_to_be_16((uint16_t)(rte_be_to_cpu_16(ip_hd= r->total_length) > - - sizeof(struct ipv4_hdr))); > - return get_16b_sum(psd_hdr.u16_arr, sizeof(psd_hdr)); > -} > - > -static inline uint16_t > -get_ipv6_psd_sum(struct ipv6_hdr *ip_hdr) > -{ > - /* Pseudo Header for IPv6/UDP/TCP checksum */ > - union ipv6_psd_header { > - struct { > - uint8_t src_addr[16]; /* IP address of source host. */ > - uint8_t dst_addr[16]; /* IP address of destination host(s). */ > - uint32_t len; /* L4 length. */ > - uint32_t proto; /* L4 protocol - top 3 bytes must be zero */ > - } __attribute__((__packed__)); > - > - uint16_t u16_arr[0]; /* allow use as 16-bit values with safe aliasing = */ > - } psd_hdr; > - > - rte_memcpy(&psd_hdr.src_addr, ip_hdr->src_addr, > - sizeof(ip_hdr->src_addr) + sizeof(ip_hdr->dst_addr)); > - psd_hdr.len =3D ip_hdr->payload_len; > - psd_hdr.proto =3D (ip_hdr->proto << 24); > - > - return get_16b_sum(psd_hdr.u16_arr, sizeof(psd_hdr)); > -} > - > static uint16_t > get_psd_sum(void *l3_hdr, uint16_t ethertype) > { > if (ethertype =3D=3D _htons(ETHER_TYPE_IPv4)) > - return get_ipv4_psd_sum(l3_hdr); > + return rte_ipv4_phdr_cksum(l3_hdr); > else /* assume ethertype =3D=3D ETHER_TYPE_IPv6 */ > - return get_ipv6_psd_sum(l3_hdr); > -} > - > -static inline uint16_t > -get_ipv4_udptcp_checksum(struct ipv4_hdr *ipv4_hdr, uint16_t *l4_hdr) > -{ > - uint32_t cksum; > - uint32_t l4_len; > - > - l4_len =3D rte_be_to_cpu_16(ipv4_hdr->total_length) - sizeof(struct ipv= 4_hdr); > - > - cksum =3D get_16b_sum(l4_hdr, l4_len); > - cksum +=3D get_ipv4_psd_sum(ipv4_hdr); > - > - cksum =3D ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > - cksum =3D (~cksum) & 0xffff; > - if (cksum =3D=3D 0) > - cksum =3D 0xffff; > - return (uint16_t)cksum; > -} > - > -static inline uint16_t > -get_ipv6_udptcp_checksum(struct ipv6_hdr *ipv6_hdr, uint16_t *l4_hdr) > -{ > - uint32_t cksum; > - uint32_t l4_len; > - > - l4_len =3D rte_be_to_cpu_16(ipv6_hdr->payload_len); > - > - cksum =3D get_16b_sum(l4_hdr, l4_len); > - cksum +=3D get_ipv6_psd_sum(ipv6_hdr); > - > - cksum =3D ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > - cksum =3D (~cksum) & 0xffff; > - if (cksum =3D=3D 0) > - cksum =3D 0xffff; > - > - return (uint16_t)cksum; > + return rte_ipv6_phdr_cksum(l3_hdr); > } >=20 > static uint16_t > get_udptcp_checksum(void *l3_hdr, void *l4_hdr, uint16_t ethertype) > { > if (ethertype =3D=3D _htons(ETHER_TYPE_IPv4)) > - return get_ipv4_udptcp_checksum(l3_hdr, l4_hdr); > + return rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); > else /* assume ethertype =3D=3D ETHER_TYPE_IPv6 */ > - return get_ipv6_udptcp_checksum(l3_hdr, l4_hdr); > + return rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); > } >=20 > /* > @@ -294,7 +179,7 @@ process_inner_cksums(void *l3_hdr, uint16_t ethertype= , uint16_t l3_len, > if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM) > ol_flags |=3D PKT_TX_IP_CKSUM; > else > - ipv4_hdr->hdr_checksum =3D get_ipv4_cksum(ipv4_hdr); > + ipv4_hdr->hdr_checksum =3D rte_ipv4_cksum(ipv4_hdr); >=20 > } > else if (ethertype !=3D _htons(ETHER_TYPE_IPv6)) > @@ -366,7 +251,7 @@ process_outer_cksums(void *outer_l3_hdr, uint16_t out= er_ethertype, > ipv4_hdr->hdr_checksum =3D 0; >=20 > if ((testpmd_ol_flags & TESTPMD_TX_OFFLOAD_VXLAN_CKSUM) =3D=3D 0) > - ipv4_hdr->hdr_checksum =3D get_ipv4_cksum(ipv4_hdr); > + ipv4_hdr->hdr_checksum =3D rte_ipv4_cksum(ipv4_hdr); > } >=20 > udp_hdr =3D (struct udp_hdr *)((char *)outer_l3_hdr + outer_l3_len); > @@ -376,12 +261,10 @@ process_outer_cksums(void *outer_l3_hdr, uint16_t o= uter_ethertype, > if ((testpmd_ol_flags & TESTPMD_TX_OFFLOAD_VXLAN_CKSUM) =3D=3D 0) { > if (outer_ethertype =3D=3D _htons(ETHER_TYPE_IPv4)) > udp_hdr->dgram_cksum =3D > - get_ipv4_udptcp_checksum(ipv4_hdr, > - (uint16_t *)udp_hdr); > + rte_ipv4_udptcp_cksum(ipv4_hdr, udp_hdr); > else > udp_hdr->dgram_cksum =3D > - get_ipv6_udptcp_checksum(ipv6_hdr, > - (uint16_t *)udp_hdr); > + rte_ipv6_udptcp_cksum(ipv6_hdr, udp_hdr); > } > } >=20 > diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h > index e76617f..3c8e825 100644 > --- a/lib/librte_mbuf/rte_mbuf.h > +++ b/lib/librte_mbuf/rte_mbuf.h > @@ -114,7 +114,8 @@ extern "C" { > * - fill l2_len and l3_len in mbuf > * - set the flags PKT_TX_TCP_CKSUM, PKT_TX_SCTP_CKSUM or PKT_TX_UDP_CK= SUM > * - calculate the pseudo header checksum and set it in the L4 header (= only > - * for TCP or UDP). For SCTP, set the crc field to 0. > + * for TCP or UDP). See rte_ipv4_phdr_cksum() and rte_ipv6_phdr_cksum= (). > + * For SCTP, set the crc field to 0. > */ > #define PKT_TX_L4_NO_CKSUM (0ULL << 52) /* Disable L4 cksum of TX pkt.= */ > #define PKT_TX_TCP_CKSUM (1ULL << 52) /**< TCP cksum of TX pkt. comp= uted by NIC. */ > diff --git a/lib/librte_net/rte_ip.h b/lib/librte_net/rte_ip.h > index e3f65c1..9cfca7f 100644 > --- a/lib/librte_net/rte_ip.h > +++ b/lib/librte_net/rte_ip.h > @@ -78,6 +78,9 @@ >=20 > #include >=20 > +#include > +#include > + > #ifdef __cplusplus > extern "C" { > #endif > @@ -247,6 +250,124 @@ struct ipv4_hdr { > ((x) >=3D IPV4_MIN_MCAST && (x) <=3D IPV4_MAX_MCAST) /**< check if IPv4= address is multicast */ >=20 > /** > + * Process the non-complemented checksum of a buffer. > + * > + * @param buf > + * Pointer to the buffer. > + * @param len > + * Length of the buffer. > + * @return > + * The non-complemented checksum. > + */ > +static inline uint16_t > +rte_raw_cksum(const char *buf, size_t len) > +{ > + const uint16_t *u16 =3D (const uint16_t *)buf; > + uint32_t sum =3D 0; > + > + while (len >=3D 8) { > + sum +=3D u16[0]; sum +=3D u16[1]; sum +=3D u16[2]; sum +=3D u16[3]; > + len -=3D 8; > + u16 +=3D 4; > + } > + while (len >=3D 2) { > + sum +=3D *u16; > + len -=3D 2; > + u16 +=3D 1; > + } > + > + /* if length is in odd bytes */ > + if (len =3D=3D 1) > + sum +=3D *((const uint8_t *)u16); > + > + sum =3D ((sum & 0xffff0000) >> 16) + (sum & 0xffff); > + sum =3D ((sum & 0xffff0000) >> 16) + (sum & 0xffff); > + return (uint16_t)sum; > +} > + > +/** > + * Process the IPv4 checksum of an IPv4 header. > + * > + * The checksum field must be set to 0 by the caller. > + * > + * @param ipv4_hdr > + * The pointer to the contiguous IPv4 header. > + * @return > + * The complemented checksum to set in the IP packet. > + */ > +static inline uint16_t > +rte_ipv4_cksum(const struct ipv4_hdr *ipv4_hdr) > +{ > + uint16_t cksum; > + cksum =3D rte_raw_cksum((const char *)ipv4_hdr, sizeof(struct ipv4_hdr)= ); > + return ((cksum =3D=3D 0xffff) ? cksum : ~cksum); > +} > + > +/** > + * Process the pseudo-header checksum of an IPv4 header. > + * > + * The checksum field must be set to 0 by the caller. > + * > + * @param ipv4_hdr > + * The pointer to the contiguous IPv4 header. > + * @return > + * The non-complemented checksum to set in the L4 header. > + */ > +static inline uint16_t > +rte_ipv4_phdr_cksum(const struct ipv4_hdr *ipv4_hdr) > +{ > + struct ipv4_psd_header { > + uint32_t src_addr; /* IP address of source host. */ > + uint32_t dst_addr; /* IP address of destination host. */ > + uint8_t zero; /* zero. */ > + uint8_t proto; /* L4 protocol type. */ > + uint16_t len; /* L4 length. */ > + } psd_hdr; > + > + psd_hdr.src_addr =3D ipv4_hdr->src_addr; > + psd_hdr.dst_addr =3D ipv4_hdr->dst_addr; > + psd_hdr.zero =3D 0; > + psd_hdr.proto =3D ipv4_hdr->next_proto_id; > + psd_hdr.len =3D rte_cpu_to_be_16( > + (uint16_t)(rte_be_to_cpu_16(ipv4_hdr->total_length) > + - sizeof(struct ipv4_hdr))); > + return rte_raw_cksum((const char *)&psd_hdr, sizeof(psd_hdr)); > +} > + > +/** > + * Process the IPv4 UDP or TCP checksum. > + * > + * The IPv4 header should not contains options. The IP and layer 4 > + * checksum must be set to 0 in the packet 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. > + */ > +static inline uint16_t > +rte_ipv4_udptcp_cksum(const struct ipv4_hdr *ipv4_hdr, const void *l4_hd= r) > +{ > + uint32_t cksum; > + uint32_t l4_len; > + > + l4_len =3D rte_be_to_cpu_16(ipv4_hdr->total_length) - > + sizeof(struct ipv4_hdr); > + > + cksum =3D rte_raw_cksum(l4_hdr, l4_len); > + cksum +=3D rte_ipv4_phdr_cksum(ipv4_hdr); > + > + cksum =3D ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > + cksum =3D (~cksum) & 0xffff; > + if (cksum =3D=3D 0) > + cksum =3D 0xffff; > + > + return cksum; > +} > + > +/** > * IPv6 Header > */ > struct ipv6_hdr { > @@ -258,6 +379,64 @@ struct ipv6_hdr { > uint8_t dst_addr[16]; /**< IP address of destination host(s). */ > } __attribute__((__packed__)); >=20 > +/** > + * Process the pseudo-header checksum of an IPv6 header. > + * > + * @param ipv6_hdr > + * The pointer to the contiguous IPv6 header. > + * @return > + * The non-complemented checksum to set in the L4 header. > + */ > +static inline uint16_t > +rte_ipv6_phdr_cksum(const struct ipv6_hdr *ipv6_hdr) > +{ > + struct ipv6_psd_header { > + uint8_t src_addr[16]; /* IP address of source host. */ > + uint8_t dst_addr[16]; /* IP address of destination host. */ > + uint32_t len; /* L4 length. */ > + uint32_t proto; /* L4 protocol - top 3 bytes must be zero */ > + } psd_hdr; > + > + rte_memcpy(&psd_hdr.src_addr, ipv6_hdr->src_addr, > + sizeof(ipv6_hdr->src_addr) + sizeof(ipv6_hdr->dst_addr)); > + psd_hdr.proto =3D (ipv6_hdr->proto << 24); > + psd_hdr.len =3D ipv6_hdr->payload_len; > + > + return rte_raw_cksum((const char *)&psd_hdr, sizeof(psd_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. > + * > + * @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. > + */ > +static inline uint16_t > +rte_ipv6_udptcp_cksum(const struct ipv6_hdr *ipv6_hdr, const void *l4_hd= r) > +{ > + uint32_t cksum; > + uint32_t l4_len; > + > + l4_len =3D rte_be_to_cpu_16(ipv6_hdr->payload_len); > + > + cksum =3D rte_raw_cksum(l4_hdr, l4_len); > + cksum +=3D rte_ipv6_phdr_cksum(ipv6_hdr, 0); > + > + cksum =3D ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > + cksum =3D (~cksum) & 0xffff; > + if (cksum =3D=3D 0) > + cksum =3D 0xffff; > + > + return cksum; > +} > + > #ifdef __cplusplus > } > #endif > -- > 2.1.0