diff options
author | Tom Gundersen <teg@jklm.no> | 2014-04-02 10:00:31 +0200 |
---|---|---|
committer | Patrik Flykt <patrik.flykt@linux.intel.com> | 2014-04-07 15:39:21 +0300 |
commit | d576127429a7be7d8e393d06f1bdd004fa37096c (patch) | |
tree | e59d35258f5fe2e18c918decbc2f9128c39069ea /src/libsystemd-network/dhcp-packet.c | |
parent | 298f77c60c954a4e31229592ec95ee8e06ff1baa (diff) |
libsystemd-network: Speed up checksum computation using 64 bit integers
Improve the checksum computation by using 64 bit integers instead of the 16 bit
integers in the existing implementation. This change speeds up the computation
with approximately 78% both on 64 bit and 32 bit systems.
Please see RFC 1071 for details.
Diffstat (limited to 'src/libsystemd-network/dhcp-packet.c')
-rw-r--r-- | src/libsystemd-network/dhcp-packet.c | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c index 102ed096af..fba9c46ef2 100644 --- a/src/libsystemd-network/dhcp-packet.c +++ b/src/libsystemd-network/dhcp-packet.c @@ -59,21 +59,48 @@ int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, return 0; } -uint16_t dhcp_packet_checksum(void *buf, int len) { - uint32_t sum; - uint16_t *check; - int i; - uint8_t *odd; +uint16_t dhcp_packet_checksum(void *buf, size_t len) { + uint64_t *buf_64 = buf; + uint64_t *end_64 = (uint64_t*)buf + (len / sizeof(uint64_t)); + uint32_t *buf_32; + uint16_t *buf_16; + uint8_t *buf_8; + uint64_t sum = 0; + + while (buf_64 < end_64) { + sum += *buf_64; + if (sum < *buf_64) + sum++; + + buf_64 ++; + } + + buf_32 = (uint32_t*)buf_64; + + if (len & sizeof(uint32_t)) { + sum += *buf_32; + if (sum < *buf_32) + sum++; + + buf_32 ++; + } + + buf_16 = (uint16_t*)buf_32; - sum = 0; - check = buf; + if (len & sizeof(uint16_t)) { + sum += *buf_16; + if (sum < *buf_16) + sum ++; + + buf_16 ++; + } - for (i = 0; i < len / 2 ; i++) - sum += check[i]; + buf_8 = (uint8_t*)buf_16; - if (len & 0x01) { - odd = buf; - sum += odd[len - 1]; + if (len & sizeof(uint8_t)) { + sum += *buf_8; + if (sum < *buf_8) + sum++; } while (sum >> 16) |