[lng-odp] [PATCH] helper : Fix UDP checksum computation

2015-10-01 Thread ion.grigore
From: Grigore Ion 

This patch fixes the following problems:
- checksum computation for LE platforms
- checksum is computed in the CPU endianness. The returned result
must be converted to the BE ordering when it is used to update the
UDP checksum in a packet.
- checksum computation for packets having the UDP length not a
multiple of 2.

Signed-off-by: Grigore Ion 
---
 helper/include/odp/helper/udp.h |   55 --
 1 files changed, 23 insertions(+), 32 deletions(-)

diff --git a/helper/include/odp/helper/udp.h b/helper/include/odp/helper/udp.h
index 06c439b..f56b310 100644
--- a/helper/include/odp/helper/udp.h
+++ b/helper/include/odp/helper/udp.h
@@ -4,7 +4,6 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-
 /**
  * @file
  *
@@ -22,7 +21,6 @@ extern "C" {
 #include 
 #include 
 
-
 /** @addtogroup odph_header ODPH HEADER
  *  @{
  */
@@ -44,46 +42,39 @@ typedef struct ODP_PACKED {
  * This function uses odp packet to calc checksum
  *
  * @param pkt  calculate chksum for pkt
- * @return  checksum value
+ * @return  checksum value in CPU endianness
  */
 static inline uint16_t odph_ipv4_udp_chksum(odp_packet_t pkt)
 {
-   uint32_t sum = 0;
-   odph_udphdr_t *udph;
-   odph_ipv4hdr_t *iph;
-   uint16_t udplen;
-   uint8_t *buf;
-
-   if (!odp_packet_l3_offset(pkt))
-   return 0;
+   odph_ipv4hdr_t  *iph;
+   odph_udphdr_t   *udph;
+   uint32_tsum;
+   uint16_tudplen, *buf;
 
-   if (!odp_packet_l4_offset(pkt))
+   if (!odp_packet_l3_offset(pkt) || !odp_packet_l3_offset(pkt))
return 0;
-
iph = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
udph = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
-   udplen = odp_be_to_cpu_16(udph->length);
-
-   /* 32-bit sum of all 16-bit words covered by UDP chksum */
+   /* 32-bit sum of UDP pseudo-header */
sum = (iph->src_addr & 0x) + (iph->src_addr >> 16) +
- (iph->dst_addr & 0x) + (iph->dst_addr >> 16) +
- (uint16_t)iph->proto + udplen;
-   for (buf = (uint8_t *)udph; udplen > 1; udplen -= 2) {
-   sum += ((*buf << 8) + *(buf + 1));
-   buf += 2;
-   }
-
-   /* Fold sum to 16 bits: add carrier to result */
-   while (sum >> 16)
-   sum = (sum & 0x) + (sum >> 16);
-
+   (iph->dst_addr & 0x) + (iph->dst_addr >> 16) +
+   odp_be_to_cpu_16(iph->proto) + udph->length;
+   udplen = odp_be_to_cpu_16(udph->length);
+   buf = (uint16_t *)((void *)udph);
+   /* 32-bit sum of UDP header (checksum field cleared) and UDP data */
+   for ( ; udplen > 1; udplen -= 2)
+   sum += *buf++;
+   /* Length is not a multiple of 2 bytes */
+   if (udplen)
+   sum += odp_be_to_cpu_16(*((uint8_t *)buf) << 8);
+   /* Fold sum to 16 bits */
+   sum = (sum & 0x) + (sum >> 16);
+   /* Add carrier (0/1) to result */
+   sum += (sum >> 16);
/* 1's complement */
sum = ~sum;
-
-   /* set computation result */
-   sum = (sum == 0x0) ? 0x : sum;
-
-   return sum;
+   /* Set computation result */
+   return (sum == 0x0) ? 0x : odp_be_to_cpu_16(sum);
 }
 
 /** @internal Compile time assert */
-- 
1.7.3.4

___
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp


Re: [lng-odp] [PATCH] helper : Fix UDP checksum computation

2015-10-01 Thread Bill Fischofer
On Thu, Oct 1, 2015 at 8:45 AM,  wrote:

> From: Grigore Ion 
>
> This patch fixes the following problems:
> - checksum computation for LE platforms
> - checksum is computed in the CPU endianness. The returned result
> must be converted to the BE ordering when it is used to update the
> UDP checksum in a packet.
> - checksum computation for packets having the UDP length not a
> multiple of 2.
>
> Signed-off-by: Grigore Ion 
> ---
>  helper/include/odp/helper/udp.h |   55
> --
>  1 files changed, 23 insertions(+), 32 deletions(-)
>
> diff --git a/helper/include/odp/helper/udp.h
> b/helper/include/odp/helper/udp.h
> index 06c439b..5d6154f 100644
> --- a/helper/include/odp/helper/udp.h
> +++ b/helper/include/odp/helper/udp.h
> @@ -4,7 +4,6 @@
>   * SPDX-License-Identifier: BSD-3-Clause
>   */
>
> -
>  /**
>   * @file
>   *
> @@ -22,7 +21,6 @@ extern "C" {
>  #include 
>  #include 
>
> -
>  /** @addtogroup odph_header ODPH HEADER
>   *  @{
>   */
> @@ -44,46 +42,39 @@ typedef struct ODP_PACKED {
>   * This function uses odp packet to calc checksum
>   *
>   * @param pkt  calculate chksum for pkt
> - * @return  checksum value
> + * @return  checksum value in CPU endianness
>   */
>  static inline uint16_t odph_ipv4_udp_chksum(odp_packet_t pkt)
>  {
> -   uint32_t sum = 0;
> -   odph_udphdr_t *udph;
> -   odph_ipv4hdr_t *iph;
> -   uint16_t udplen;
> -   uint8_t *buf;
> -
> -   if (!odp_packet_l3_offset(pkt))
> -   return 0;
> +   odph_ipv4hdr_t  *iph;
> +   odph_udphdr_t   *udph;
> +   uint32_tsum;
> +   uint16_tudplen, *buf;
>
> -   if (!odp_packet_l4_offset(pkt))
> +   if (!odp_packet_l3_offset(pkt) || !odp_packet_l4_offset(pkt))
>

Both this code and the base code are incorrect.
 odp_packet_l(2/3/4)_offset() return ODP_PACKET_OFFSET_INVALID if the
packet contains no corresponding offset and that value may or may not be
zero.  Correct test is:

if (odp_packet_l4_offset(pkt) != ODP_PACKET_OFFSET_INVALID) ...

There's no need to check the L3 offset since if the packet has a recognized
L4 offset then it's guaranteed to have a valid L3 offset as well.


> return 0;
> -
> iph = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
> udph = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
> -   udplen = odp_be_to_cpu_16(udph->length);
> -
> -   /* 32-bit sum of all 16-bit words covered by UDP chksum */
> +   /* 32-bit sum of UDP pseudo-header */
> sum = (iph->src_addr & 0x) + (iph->src_addr >> 16) +
> - (iph->dst_addr & 0x) + (iph->dst_addr >> 16) +
> - (uint16_t)iph->proto + udplen;
> -   for (buf = (uint8_t *)udph; udplen > 1; udplen -= 2) {
> -   sum += ((*buf << 8) + *(buf + 1));
> -   buf += 2;
> -   }
> -
> -   /* Fold sum to 16 bits: add carrier to result */
> -   while (sum >> 16)
> -   sum = (sum & 0x) + (sum >> 16);
> -
> +   (iph->dst_addr & 0x) + (iph->dst_addr >> 16) +
> +   odp_be_to_cpu_16(iph->proto) + udph->length;
> +   udplen = odp_be_to_cpu_16(udph->length);
> +   buf = (uint16_t *)((void *)udph);
> +   /* 32-bit sum of UDP header (checksum field cleared) and UDP data
> */
> +   for ( ; udplen > 1; udplen -= 2)
> +   sum += *buf++;
> +   /* Length is not a multiple of 2 bytes */
> +   if (udplen)
> +   sum += odp_be_to_cpu_16(*((uint8_t *)buf) << 8);
> +   /* Fold sum to 16 bits */
> +   sum = (sum & 0x) + (sum >> 16);
> +   /* Add carrier (0/1) to result */
> +   sum += (sum >> 16);
> /* 1's complement */
> sum = ~sum;
> -
> -   /* set computation result */
> -   sum = (sum == 0x0) ? 0x : sum;
> -
> -   return sum;
> +   /* Set computation result */
> +   return (sum == 0x0) ? 0x : odp_be_to_cpu_16(sum);
>  }
>
>  /** @internal Compile time assert */
> --
> 1.7.3.4
>
> ___
> lng-odp mailing list
> lng-odp@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp
>
___
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp


[lng-odp] [PATCH] helper : Fix UDP checksum computation

2015-10-01 Thread ion.grigore
From: Grigore Ion 

This patch fixes the following problems:
- checksum computation for LE platforms
- checksum is computed in the CPU endianness. The returned result
must be converted to the BE ordering when it is used to update the
UDP checksum in a packet.
- checksum computation for packets having the UDP length not a
multiple of 2.

Signed-off-by: Grigore Ion 
---
 helper/include/odp/helper/udp.h |   55 --
 1 files changed, 23 insertions(+), 32 deletions(-)

diff --git a/helper/include/odp/helper/udp.h b/helper/include/odp/helper/udp.h
index 06c439b..5d6154f 100644
--- a/helper/include/odp/helper/udp.h
+++ b/helper/include/odp/helper/udp.h
@@ -4,7 +4,6 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-
 /**
  * @file
  *
@@ -22,7 +21,6 @@ extern "C" {
 #include 
 #include 
 
-
 /** @addtogroup odph_header ODPH HEADER
  *  @{
  */
@@ -44,46 +42,39 @@ typedef struct ODP_PACKED {
  * This function uses odp packet to calc checksum
  *
  * @param pkt  calculate chksum for pkt
- * @return  checksum value
+ * @return  checksum value in CPU endianness
  */
 static inline uint16_t odph_ipv4_udp_chksum(odp_packet_t pkt)
 {
-   uint32_t sum = 0;
-   odph_udphdr_t *udph;
-   odph_ipv4hdr_t *iph;
-   uint16_t udplen;
-   uint8_t *buf;
-
-   if (!odp_packet_l3_offset(pkt))
-   return 0;
+   odph_ipv4hdr_t  *iph;
+   odph_udphdr_t   *udph;
+   uint32_tsum;
+   uint16_tudplen, *buf;
 
-   if (!odp_packet_l4_offset(pkt))
+   if (!odp_packet_l3_offset(pkt) || !odp_packet_l4_offset(pkt))
return 0;
-
iph = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
udph = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
-   udplen = odp_be_to_cpu_16(udph->length);
-
-   /* 32-bit sum of all 16-bit words covered by UDP chksum */
+   /* 32-bit sum of UDP pseudo-header */
sum = (iph->src_addr & 0x) + (iph->src_addr >> 16) +
- (iph->dst_addr & 0x) + (iph->dst_addr >> 16) +
- (uint16_t)iph->proto + udplen;
-   for (buf = (uint8_t *)udph; udplen > 1; udplen -= 2) {
-   sum += ((*buf << 8) + *(buf + 1));
-   buf += 2;
-   }
-
-   /* Fold sum to 16 bits: add carrier to result */
-   while (sum >> 16)
-   sum = (sum & 0x) + (sum >> 16);
-
+   (iph->dst_addr & 0x) + (iph->dst_addr >> 16) +
+   odp_be_to_cpu_16(iph->proto) + udph->length;
+   udplen = odp_be_to_cpu_16(udph->length);
+   buf = (uint16_t *)((void *)udph);
+   /* 32-bit sum of UDP header (checksum field cleared) and UDP data */
+   for ( ; udplen > 1; udplen -= 2)
+   sum += *buf++;
+   /* Length is not a multiple of 2 bytes */
+   if (udplen)
+   sum += odp_be_to_cpu_16(*((uint8_t *)buf) << 8);
+   /* Fold sum to 16 bits */
+   sum = (sum & 0x) + (sum >> 16);
+   /* Add carrier (0/1) to result */
+   sum += (sum >> 16);
/* 1's complement */
sum = ~sum;
-
-   /* set computation result */
-   sum = (sum == 0x0) ? 0x : sum;
-
-   return sum;
+   /* Set computation result */
+   return (sum == 0x0) ? 0x : odp_be_to_cpu_16(sum);
 }
 
 /** @internal Compile time assert */
-- 
1.7.3.4

___
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp


Re: [lng-odp] [PATCH] helper : Fix UDP checksum computation

2015-10-01 Thread Ion Grigore
Hi,

Now all variables are declared on top of block.
The patch passed checkpatch verification.

I superseded the old patch.

Thanks,
Grig

-Original Message-
From: lng-odp [mailto:lng-odp-boun...@lists.linaro.org] On Behalf Of Maxim 
Uvarov
Sent: Wednesday, September 23, 2015 8:34 PM
To: lng-odp@lists.linaro.org
Subject: Re: [lng-odp] [PATCH] helper : Fix UDP checksum computation



On 09/21/15 08:45, ion.grig...@freescale.com wrote:
> From: Grigore Ion <ion.grig...@freescale.com>
>
> This patch fixes the following problems:
> - checksum computation for LE platforms
> - checksum is computed in the CPU endianess. The returned result must 
> be converted to the BE ordering when it is used to update the UDP checksum in 
> a packet.
> - checksum computation for packets having the UDP length not a multiple of 2.
>
> Signed-off-by: Grigore Ion <ion.grig...@freescale.com>
> ---
>   helper/include/odp/helper/udp.h |   54 
> ++-
>   1 files changed, 25 insertions(+), 29 deletions(-)
>
> diff --git a/helper/include/odp/helper/udp.h 
> b/helper/include/odp/helper/udp.h index 06c439b..74fad3c 100644
> --- a/helper/include/odp/helper/udp.h
> +++ b/helper/include/odp/helper/udp.h
> @@ -22,7 +22,6 @@ extern "C" {
>   #include 
>   #include 
>   
> -
>   /** @addtogroup odph_header ODPH HEADER
>*  @{
>*/
> @@ -44,46 +43,43 @@ typedef struct ODP_PACKED {
>* This function uses odp packet to calc checksum
>*
>* @param pkt  calculate chksum for pkt
> - * @return  checksum value
> + * @return  checksum value in CPU endianess
>*/
>   static inline uint16_t odph_ipv4_udp_chksum(odp_packet_t pkt)
>   {
> - uint32_t sum = 0;
> - odph_udphdr_t *udph;
> - odph_ipv4hdr_t *iph;
> - uint16_t udplen;
> - uint8_t *buf;
> -
> - if (!odp_packet_l3_offset(pkt))
> + if (!odp_packet_l3_offset(pkt) || !odp_packet_l3_offset(pkt))
that looks strange :)
>   return 0;
>   
> - if (!odp_packet_l4_offset(pkt))
> - return 0;
> + odph_ipv4hdr_t *iph = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
> + odph_udphdr_t *udph = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
iph and udph should be defined on top of the block. Interesting if checkpatch 
did not said about that.
The same for all other variables. So just not delete them from top and run 
./script/checkpatch.pl before sending.

Thanks,
Maxim.

> +
> + /* 32-bit sum of UDP pseudo-header */
> + uint32_t sum = (iph->src_addr & 0x) + (iph->src_addr >> 16) +
> + (iph->dst_addr & 0x) + (iph->dst_addr >> 16) +
> + odp_be_to_cpu_16(iph->proto) + udph->length;
>   
> - iph = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
> - udph = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
> - udplen = odp_be_to_cpu_16(udph->length);
> + uint16_t udplen = odp_be_to_cpu_16(udph->length);
> + uint16_t *buf = (uint16_t *)((void *)udph);
>   
> - /* 32-bit sum of all 16-bit words covered by UDP chksum */
> - sum = (iph->src_addr & 0x) + (iph->src_addr >> 16) +
> -   (iph->dst_addr & 0x) + (iph->dst_addr >> 16) +
> -   (uint16_t)iph->proto + udplen;
> - for (buf = (uint8_t *)udph; udplen > 1; udplen -= 2) {
> - sum += ((*buf << 8) + *(buf + 1));
> - buf += 2;
> - }
> + /* 32-bit sum of UDP header (checksum field cleared) and UDP data */
> + for ( ; udplen > 1; udplen -= 2)
> + sum += *buf++;
>   
> - /* Fold sum to 16 bits: add carrier to result */
> - while (sum >> 16)
> - sum = (sum & 0x) + (sum >> 16);
> + /* Length is not a multiple of 2 bytes */
> + if (udplen)
> + sum += odp_be_to_cpu_16(*((uint8_t *)buf) << 8);
> +
> + /* Fold sum to 16 bits */
> + sum = (sum & 0x) + (sum >> 16);
> +
> + /* Add carrier (0/1) to result */
> + sum += (sum >> 16);
>   
>   /* 1's complement */
>   sum = ~sum;
>   
> - /* set computation result */
> - sum = (sum == 0x0) ? 0x : sum;
> -
> - return sum;
> + /* Set computation result */
> + return (sum == 0x0) ? 0x : odp_be_to_cpu_16(sum);
>   }
>   
>   /** @internal Compile time assert */

___
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp
___
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp


Re: [lng-odp] [PATCH] helper : Fix UDP checksum computation

2015-09-23 Thread Maxim Uvarov



On 09/21/15 08:45, ion.grig...@freescale.com wrote:

From: Grigore Ion 

This patch fixes the following problems:
- checksum computation for LE platforms
- checksum is computed in the CPU endianess. The returned result must be 
converted
to the BE ordering when it is used to update the UDP checksum in a packet.
- checksum computation for packets having the UDP length not a multiple of 2.

Signed-off-by: Grigore Ion 
---
  helper/include/odp/helper/udp.h |   54 ++-
  1 files changed, 25 insertions(+), 29 deletions(-)

diff --git a/helper/include/odp/helper/udp.h b/helper/include/odp/helper/udp.h
index 06c439b..74fad3c 100644
--- a/helper/include/odp/helper/udp.h
+++ b/helper/include/odp/helper/udp.h
@@ -22,7 +22,6 @@ extern "C" {
  #include 
  #include 
  
-

  /** @addtogroup odph_header ODPH HEADER
   *  @{
   */
@@ -44,46 +43,43 @@ typedef struct ODP_PACKED {
   * This function uses odp packet to calc checksum
   *
   * @param pkt  calculate chksum for pkt
- * @return  checksum value
+ * @return  checksum value in CPU endianess
   */
  static inline uint16_t odph_ipv4_udp_chksum(odp_packet_t pkt)
  {
-   uint32_t sum = 0;
-   odph_udphdr_t *udph;
-   odph_ipv4hdr_t *iph;
-   uint16_t udplen;
-   uint8_t *buf;
-
-   if (!odp_packet_l3_offset(pkt))
+   if (!odp_packet_l3_offset(pkt) || !odp_packet_l3_offset(pkt))

that looks strange :)

return 0;
  
-	if (!odp_packet_l4_offset(pkt))

-   return 0;
+   odph_ipv4hdr_t *iph = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
+   odph_udphdr_t *udph = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
iph and udph should be defined on top of the block. Interesting if 
checkpatch did not said about that.
The same for all other variables. So just not delete them from top and 
run ./script/checkpatch.pl before sending.


Thanks,
Maxim.


+
+   /* 32-bit sum of UDP pseudo-header */
+   uint32_t sum = (iph->src_addr & 0x) + (iph->src_addr >> 16) +
+   (iph->dst_addr & 0x) + (iph->dst_addr >> 16) +
+   odp_be_to_cpu_16(iph->proto) + udph->length;
  
-	iph = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);

-   udph = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
-   udplen = odp_be_to_cpu_16(udph->length);
+   uint16_t udplen = odp_be_to_cpu_16(udph->length);
+   uint16_t *buf = (uint16_t *)((void *)udph);
  
-	/* 32-bit sum of all 16-bit words covered by UDP chksum */

-   sum = (iph->src_addr & 0x) + (iph->src_addr >> 16) +
- (iph->dst_addr & 0x) + (iph->dst_addr >> 16) +
- (uint16_t)iph->proto + udplen;
-   for (buf = (uint8_t *)udph; udplen > 1; udplen -= 2) {
-   sum += ((*buf << 8) + *(buf + 1));
-   buf += 2;
-   }
+   /* 32-bit sum of UDP header (checksum field cleared) and UDP data */
+   for ( ; udplen > 1; udplen -= 2)
+   sum += *buf++;
  
-	/* Fold sum to 16 bits: add carrier to result */

-   while (sum >> 16)
-   sum = (sum & 0x) + (sum >> 16);
+   /* Length is not a multiple of 2 bytes */
+   if (udplen)
+   sum += odp_be_to_cpu_16(*((uint8_t *)buf) << 8);
+
+   /* Fold sum to 16 bits */
+   sum = (sum & 0x) + (sum >> 16);
+
+   /* Add carrier (0/1) to result */
+   sum += (sum >> 16);
  
  	/* 1's complement */

sum = ~sum;
  
-	/* set computation result */

-   sum = (sum == 0x0) ? 0x : sum;
-
-   return sum;
+   /* Set computation result */
+   return (sum == 0x0) ? 0x : odp_be_to_cpu_16(sum);
  }
  
  /** @internal Compile time assert */


___
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp


[lng-odp] [PATCH] helper : Fix UDP checksum computation

2015-09-21 Thread ion.grigore
From: Grigore Ion 

This patch fixes the following problems:
- checksum computation for LE platforms
- checksum is computed in the CPU endianess. The returned result must be 
converted
to the BE ordering when it is used to update the UDP checksum in a packet.
- checksum computation for packets having the UDP length not a multiple of 2.

Signed-off-by: Grigore Ion 
---
 helper/include/odp/helper/udp.h |   54 ++-
 1 files changed, 25 insertions(+), 29 deletions(-)

diff --git a/helper/include/odp/helper/udp.h b/helper/include/odp/helper/udp.h
index 06c439b..74fad3c 100644
--- a/helper/include/odp/helper/udp.h
+++ b/helper/include/odp/helper/udp.h
@@ -22,7 +22,6 @@ extern "C" {
 #include 
 #include 
 
-
 /** @addtogroup odph_header ODPH HEADER
  *  @{
  */
@@ -44,46 +43,43 @@ typedef struct ODP_PACKED {
  * This function uses odp packet to calc checksum
  *
  * @param pkt  calculate chksum for pkt
- * @return  checksum value
+ * @return  checksum value in CPU endianess
  */
 static inline uint16_t odph_ipv4_udp_chksum(odp_packet_t pkt)
 {
-   uint32_t sum = 0;
-   odph_udphdr_t *udph;
-   odph_ipv4hdr_t *iph;
-   uint16_t udplen;
-   uint8_t *buf;
-
-   if (!odp_packet_l3_offset(pkt))
+   if (!odp_packet_l3_offset(pkt) || !odp_packet_l3_offset(pkt))
return 0;
 
-   if (!odp_packet_l4_offset(pkt))
-   return 0;
+   odph_ipv4hdr_t *iph = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
+   odph_udphdr_t *udph = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+
+   /* 32-bit sum of UDP pseudo-header */
+   uint32_t sum = (iph->src_addr & 0x) + (iph->src_addr >> 16) +
+   (iph->dst_addr & 0x) + (iph->dst_addr >> 16) +
+   odp_be_to_cpu_16(iph->proto) + udph->length;
 
-   iph = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
-   udph = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
-   udplen = odp_be_to_cpu_16(udph->length);
+   uint16_t udplen = odp_be_to_cpu_16(udph->length);
+   uint16_t *buf = (uint16_t *)((void *)udph);
 
-   /* 32-bit sum of all 16-bit words covered by UDP chksum */
-   sum = (iph->src_addr & 0x) + (iph->src_addr >> 16) +
- (iph->dst_addr & 0x) + (iph->dst_addr >> 16) +
- (uint16_t)iph->proto + udplen;
-   for (buf = (uint8_t *)udph; udplen > 1; udplen -= 2) {
-   sum += ((*buf << 8) + *(buf + 1));
-   buf += 2;
-   }
+   /* 32-bit sum of UDP header (checksum field cleared) and UDP data */
+   for ( ; udplen > 1; udplen -= 2)
+   sum += *buf++;
 
-   /* Fold sum to 16 bits: add carrier to result */
-   while (sum >> 16)
-   sum = (sum & 0x) + (sum >> 16);
+   /* Length is not a multiple of 2 bytes */
+   if (udplen)
+   sum += odp_be_to_cpu_16(*((uint8_t *)buf) << 8);
+
+   /* Fold sum to 16 bits */
+   sum = (sum & 0x) + (sum >> 16);
+
+   /* Add carrier (0/1) to result */
+   sum += (sum >> 16);
 
/* 1's complement */
sum = ~sum;
 
-   /* set computation result */
-   sum = (sum == 0x0) ? 0x : sum;
-
-   return sum;
+   /* Set computation result */
+   return (sum == 0x0) ? 0x : odp_be_to_cpu_16(sum);
 }
 
 /** @internal Compile time assert */
-- 
1.7.3.4

___
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp