diff options
author | Daniele Di Proietto <diproiettod@vmware.com> | 2016-12-08 11:35:30 -0800 |
---|---|---|
committer | Daniele Di Proietto <diproiettod@vmware.com> | 2016-12-09 11:34:04 -0800 |
commit | 23b2a1baa6285838b9ae33ae0ac2759ef46e494f (patch) | |
tree | 44ef612769a012cccaabcdfa57d386129969bd80 /lib | |
parent | 1dea14357f9b9c1ce273538dd0cb36ba2a1993dd (diff) | |
download | openvswitch-23b2a1baa6285838b9ae33ae0ac2759ef46e494f.tar.gz |
csum: Fix csum_continue() on big endian with an odd number of bytes.
Even though it reads 16 bits at a time, csum_continue() is almost
neutral to endianness (see RFC 1071 1.2 (B), "Byte Order Independence").
Consider a buffer like the following:
00000000: XX YY XX YY XX YY XX YY ZZ
Each couple of bytes is interpreted on little endian as:
*data = 0xYYXX
while on big endian
*data = 0xXXYY
The last byte "ZZ" should be treated as the two bytes "ZZ 00"
little endian:
*data = 0x00ZZ
big endian:
*data = 0xZZ00
which means that the last byte (for odd buffers) should be left shifted
by 8 bits on big endian platforms.
This fixes a couple of connection tracking tests in userspace for big
endian platforms.
I guess RFC1071 4.1 (implementation example of the checksum in C), would
manifest the same problem on big endian.
Reported-at: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=840770
Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/csum.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/lib/csum.c b/lib/csum.c index a0e996716..5951576c0 100644 --- a/lib/csum.c +++ b/lib/csum.c @@ -44,7 +44,11 @@ csum_continue(uint32_t partial, const void *data_, size_t n) partial = csum_add16(partial, get_unaligned_be16(data)); } if (n) { +#ifdef WORDS_BIGENDIAN + partial += (*(uint8_t *) data) << 8; +#else partial += *(uint8_t *) data; +#endif } return partial; } |