chiark / gitweb /
libsystemd-network: Speed up checksum computation using 64 bit integers
authorTom Gundersen <teg@jklm.no>
Wed, 2 Apr 2014 08:00:31 +0000 (10:00 +0200)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Mon, 7 Apr 2014 12:39:21 +0000 (15:39 +0300)
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.

src/libsystemd-network/dhcp-internal.h
src/libsystemd-network/dhcp-packet.c

index 324c2a8d7af8fbe0b69b04c1b87d032494fa37a3..2188a7f89ac9f5332849ffe495d9508eea71e858 100644 (file)
@@ -48,7 +48,7 @@ int dhcp_option_parse(DHCPMessage *message, size_t len,
 int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, uint8_t type,
                       uint8_t **opt, size_t *optlen);
 
-uint16_t dhcp_packet_checksum(void *buf, int len);
+uint16_t dhcp_packet_checksum(void *buf, size_t len);
 
 void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr,
                                    uint16_t source, be32_t destination_addr,
index 102ed096aff666be3668813973587ab725f5efbc..fba9c46ef226fd9e3cf4d0bdbe2b67879c0e3aac 100644 (file)
@@ -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)