Skip to content

Commit

Permalink
net: fix aliasing in checksum computation
Browse files Browse the repository at this point in the history
[ upstream commit 24f1955 ]

That means a superfluous cast is removed and aliasing through a uint8_t
pointer is eliminated. NB: The C standard specifies that a unsigned char
pointer may alias while the C standard doesn't include such requirement
for uint8_t pointers.

Also simplified the loop since a modern C compiler can speed up (i.e.
auto-vectorize) it in a similar way. For example, GCC auto-vectorizes it
for Haswell using AVX registers while halving the number of instructions
in the generated code.

Fixes: 6006818 ("net: new checksum functions")
Fixes: e079655 ("net: fix build with gcc 4.4.7 and strict aliasing")

Signed-off-by: Georg Sauthoff <mail@gms.tf>
Reviewed-by: Morten Brørup <mb@smartsharesystems.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
  • Loading branch information
gsauthof authored and cpaelzer committed Nov 30, 2021
1 parent ae332e0 commit e3285b3
Showing 1 changed file with 8 additions and 19 deletions.
27 changes: 8 additions & 19 deletions lib/librte_net/rte_ip.h
Expand Up @@ -119,29 +119,18 @@ struct rte_ipv4_hdr {
static inline uint32_t
__rte_raw_cksum(const void *buf, size_t len, uint32_t sum)
{
/* workaround gcc strict-aliasing warning */
uintptr_t ptr = (uintptr_t)buf;
/* extend strict-aliasing rules */
typedef uint16_t __attribute__((__may_alias__)) u16_p;
const u16_p *u16_buf = (const u16_p *)ptr;

while (len >= (sizeof(*u16_buf) * 4)) {
sum += u16_buf[0];
sum += u16_buf[1];
sum += u16_buf[2];
sum += u16_buf[3];
len -= sizeof(*u16_buf) * 4;
u16_buf += 4;
}
while (len >= sizeof(*u16_buf)) {
const u16_p *u16_buf = (const u16_p *)buf;
const u16_p *end = u16_buf + len / sizeof(*u16_buf);

for (; u16_buf != end; ++u16_buf)
sum += *u16_buf;
len -= sizeof(*u16_buf);
u16_buf += 1;
}

/* if length is in odd bytes */
if (len == 1) {
/* if length is odd, keeping it byte order independent */
if (unlikely(len % 2)) {
uint16_t left = 0;
*(uint8_t *)&left = *(const uint8_t *)u16_buf;
*(unsigned char *)&left = *(const unsigned char *)end;
sum += left;
}

Expand Down

0 comments on commit e3285b3

Please sign in to comment.