Files
scylladb/ip.cc
Avi Kivity 9f5c0dbf59 ip: improve endianness adjustment
Rather than hacking around the inability to bind references to unaligned
scalars, wrap them in a struct (which can then be marked as unaligned),
and use the wrapped values everywhere.  This ensures the code works on
platforms that need special instructions for unaligned access.

Adjust the forwarding functions to require references; passing by value
accidentally can lose the conversion.
2014-08-28 23:16:48 +03:00

39 lines
855 B
C++

/*
* Copyright (C) 2014 Cloudius Systems, Ltd.
*
*/
#include "ip.hh"
namespace net {
uint16_t ip_checksum(void* data, size_t len) {
uint64_t csum = 0;
auto p64 = reinterpret_cast<packed<uint64_t>*>(data);
while (len >= 8) {
auto old = csum;
csum += ntohq(*p64++);
csum += (csum < old);
len -= 8;
}
auto p16 = reinterpret_cast<packed<uint16_t>*>(p64);
while (len >= 2) {
auto old = csum;
csum += ntohs(*p16++);
csum += (csum < old);
len -= 2;
}
auto p8 = reinterpret_cast<uint8_t*>(p16);
if (len) {
auto old = csum;
csum += *p8++;
csum += (csum < old);
len -= 1;
}
csum = (csum & 0xffff) + ((csum >> 16) & 0xffff) + ((csum >> 32) & 0xffff) + (csum >> 48);
csum += csum >> 16;
return htons(~csum);
}
}