|
27 | 27 |
|
28 | 28 | static net_ipv4_stats_t ipv4_stats = { 0 }; |
29 | 29 |
|
30 | | -/* Perform an IP-style checksum on a block of data */ |
31 | | -uint16_t __pure net_ipv4_checksum(const uint8_t *data, size_t bytes, uint16_t start) { |
32 | | - uint32_t sum = start; |
33 | | - uintptr_t end = (uintptr_t)data + bytes; |
| 30 | +static inline uint16_t checksum_one(uint16_t val, uint16_t sum) { |
| 31 | + uint16_t result; |
34 | 32 |
|
35 | | - /* Make sure we don't do any unaligned memory accesses */ |
36 | | - if(((uint32_t)data) & 0x01) { |
37 | | - const uint8_t *ptr = data; |
| 33 | + return __builtin_add_overflow(val, sum, &result) + result; |
| 34 | +} |
38 | 35 |
|
39 | | - while((size_t)(&ptr[2]) <= end) { |
40 | | - sum += ptr[0] | ((ptr[1]) << 8); |
41 | | - ptr += 2; |
42 | | - } |
43 | | - } |
44 | | - /* Fast path assumes at least 2-byte alignment. */ |
45 | | - else { |
46 | | - const uint16_t *ptr = (const uint16_t *)data; |
47 | | - while((size_t)(&ptr[1]) <= end) { |
48 | | - sum += *ptr++; |
49 | | - } |
| 36 | +/* Perform an IP-style checksum on a block of data */ |
| 37 | +uint16_t __pure net_ipv4_checksum(const uint8_t *data, size_t bytes, uint16_t sum) { |
| 38 | + /* Make sure we don't do any unaligned memory accesses */ |
| 39 | + if((uintptr_t)data & 1) { |
| 40 | + sum = checksum_one(*data, sum); |
| 41 | + bytes--; |
| 42 | + data++; |
50 | 43 | } |
51 | 44 |
|
52 | | - /* Handle the last byte, if we have an odd byte count */ |
53 | | - if(bytes & 0x1) |
54 | | - sum += data[bytes - 1]; |
| 45 | + /* Compute checksum two bytes at a time */ |
| 46 | + for(; bytes > 1; bytes -= 2, data += 2) |
| 47 | + sum = checksum_one(*(const uint16_t *)data, sum); |
55 | 48 |
|
56 | | - /* Take care of any carry bits */ |
57 | | - while(sum >> 16) |
58 | | - sum = (sum >> 16) + (sum & 0xFFFF); |
| 49 | + /* Handle the last byte, if we have an odd byte count */ |
| 50 | + if(bytes) |
| 51 | + sum = checksum_one(*data, sum); |
59 | 52 |
|
60 | | - return (uint16_t)~sum; |
| 53 | + return ~sum; |
61 | 54 | } |
62 | 55 |
|
63 | 56 | /* Determine if a given IP is in the current network */ |
|
0 commit comments