Fix soft checksum calculation 65/67965/2
authorXavier Simonart <xavier.simonart@intel.com>
Tue, 28 May 2019 18:24:00 +0000 (20:24 +0200)
committerPatrice Buriez <patrice.buriez@intel.com>
Tue, 11 Jun 2019 11:58:49 +0000 (11:58 +0000)
Soft CRC was wrong in some cases, such as when compiled with gcc -O2
This might have caused the checksum to be set to 0 in those cases.

Change-Id: Idf01df92876bd2a152ad028293b67a31861a0dfc
Signed-off-by: Xavier Simonart <xavier.simonart@intel.com>
Signed-off-by: Patrice Buriez <patrice.buriez@intel.com>
VNFs/DPPD-PROX/prox_cksum.c

index 1b9119b..add52f2 100644 (file)
 #include "log.h"
 
 /* compute IP 16 bit checksum */
+/* The hdr_checksum field must be set to 0 by the caller. */
 inline void prox_ip_cksum_sw(struct ipv4_hdr *buf)
 {
        const uint16_t size = sizeof(struct ipv4_hdr);
        uint32_t cksum = 0;
        uint32_t nb_dwords;
        uint32_t tail, mask;
-       uint32_t *pdwd = (uint32_t *)buf;
+       /* Defining pdwd as (uint32_t *) causes some optimization issues (gcc -O2).
+        In prox_ip_cksum(), hdr_checksum is set to 0, as expected by the code below,
+        but when *pdwd is plain uint32_t, GCC does not see the pointer aliasing on
+        the IPv4 header, optimizes this hdr_checksum initialization away, and hence
+        breaks the expectations of the checksum computation loop below.
+        The following typedef tells GCC that the IPv4 header may be aliased by
+        pdwd, which prevents GCC from removing the hdr_checksum = 0 assignment.
+       */
+       typedef uint32_t __attribute__((__may_alias__)) uint32_may_alias;
+       uint32_may_alias *pdwd = (uint32_may_alias *)buf;
 
        /* compute 16 bit checksum using hi and low parts of 32 bit integers */
        for (nb_dwords = (size >> 2); nb_dwords > 0; --nb_dwords) {