[systemd-commits] src/libsystemd-network

Patrik Flykt pflykt at kemper.freedesktop.org
Mon Apr 7 05:44:24 PDT 2014


 src/libsystemd-network/dhcp-internal.h |    2 -
 src/libsystemd-network/dhcp-packet.c   |   51 +++++++++++++++++++++++++--------
 2 files changed, 40 insertions(+), 13 deletions(-)

New commits:
commit d576127429a7be7d8e393d06f1bdd004fa37096c
Author: Tom Gundersen <teg at jklm.no>
Date:   Wed Apr 2 10:00:31 2014 +0200

    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.

diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h
index 324c2a8..2188a7f 100644
--- a/src/libsystemd-network/dhcp-internal.h
+++ b/src/libsystemd-network/dhcp-internal.h
@@ -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,
diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c
index 102ed09..fba9c46 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)



More information about the systemd-commits mailing list