summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--VNFs/DPPD-PROX/prox_cksum.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/VNFs/DPPD-PROX/prox_cksum.c b/VNFs/DPPD-PROX/prox_cksum.c
index 1b9119b0..add52f2b 100644
--- a/VNFs/DPPD-PROX/prox_cksum.c
+++ b/VNFs/DPPD-PROX/prox_cksum.c
@@ -20,13 +20,23 @@
#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) {