aboutsummaryrefslogtreecommitdiff
path: root/helper
diff options
context:
space:
mode:
authorGrigore Ion <ion.grigore@freescale.com>2015-10-22 15:02:58 +0300
committerMaxim Uvarov <maxim.uvarov@linaro.org>2015-12-07 14:07:46 +0300
commit0043ff8f7dd86a0c1e143412ceb5a14c8ae9c727 (patch)
treecefc4045ed755b98637b36f84c065e9941de6fe8 /helper
parent7c957d4fb6608049ec06541d19800c786ef3f198 (diff)
helper : Fix UDP checksum computation
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 <ion.grigore@freescale.com> Reviewed-by: Bill Fischofer <bill.fischofer@linaro.org> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Diffstat (limited to 'helper')
-rw-r--r--helper/include/odp/helper/udp.h32
1 files changed, 13 insertions, 19 deletions
diff --git a/helper/include/odp/helper/udp.h b/helper/include/odp/helper/udp.h
index 06c439b4b..6fce3f21d 100644
--- a/helper/include/odp/helper/udp.h
+++ b/helper/include/odp/helper/udp.h
@@ -44,20 +44,16 @@ 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;
+ uint32_t sum;
odph_udphdr_t *udph;
odph_ipv4hdr_t *iph;
- uint16_t udplen;
- uint8_t *buf;
+ uint16_t udplen, *buf;
- if (!odp_packet_l3_offset(pkt))
- return 0;
-
- if (!odp_packet_l4_offset(pkt))
+ if (odp_packet_l4_offset(pkt) == ODP_PACKET_OFFSET_INVALID)
return 0;
iph = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
@@ -67,23 +63,21 @@ static inline uint16_t odph_ipv4_udp_chksum(odp_packet_t pkt)
/* 32-bit sum of all 16-bit words covered by UDP chksum */
sum = (iph->src_addr & 0xFFFF) + (iph->src_addr >> 16) +
(iph->dst_addr & 0xFFFF) + (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;
- }
+ odp_be_to_cpu_16(iph->proto) + udph->length;
+ for (buf = (uint16_t *)((void *)udph); udplen > 1; udplen -= 2)
+ sum += *buf++;
+ if (udplen) /* If length is not a multiple of 2 bytes */
+ sum += odp_be_to_cpu_16(*((uint8_t *)buf) << 8);
/* Fold sum to 16 bits: add carrier to result */
- while (sum >> 16)
- sum = (sum & 0xFFFF) + (sum >> 16);
+ sum = (sum & 0xFFFF) + (sum >> 16);
+ sum += (sum >> 16);
/* 1's complement */
sum = ~sum;
- /* set computation result */
- sum = (sum == 0x0) ? 0xFFFF : sum;
-
- return sum;
+ /* set computation result in CPU endianness*/
+ return (sum == 0x0) ? 0xFFFF : odp_be_to_cpu_16(sum);
}
/** @internal Compile time assert */