]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp-server: improve predictability of leases 1067/head
authorTom Gundersen <teg@jklm.no>
Thu, 27 Aug 2015 06:54:41 +0000 (08:54 +0200)
committerTom Gundersen <teg@jklm.no>
Fri, 28 Aug 2015 09:05:32 +0000 (11:05 +0200)
Rather than having all clients attempt to get the same leases (starting at the
beginning of the pool), make each client star at a random offset into the pool
determined by their client id. This greatly increases the chances of a given
client receiving the same IP address even though both the client and server
have lost any lease information (and distinct server instances handing out
the same leases).

src/libsystemd-network/dhcp-server-internal.h
src/libsystemd-network/sd-dhcp-server.c

index 6cc794c937777790d140d43695d24be14982ea69..268210fc50000f88cd69157b078a4e2b4ce16f63 100644 (file)
@@ -59,7 +59,6 @@ struct sd_dhcp_server {
         be32_t netmask;
         be32_t pool_start;
         size_t pool_size;
-        size_t next_offer;
 
         char *timezone;
 
index a46858258b3affc2c254bd3fbf206acd7f8c7af4..89b9a4c6be9480641789e7949e277788a2955e5b 100644 (file)
@@ -669,6 +669,8 @@ static int get_pool_offset(sd_dhcp_server *server, be32_t requested_ip) {
         return be32toh(requested_ip) - be32toh(server->pool_start);
 }
 
+#define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
+
 int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
                                size_t length) {
         _cleanup_dhcp_request_free_ DHCPRequest *req = NULL;
@@ -716,12 +718,20 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
                 if (existing_lease)
                         address = existing_lease->address;
                 else {
+                        size_t next_offer;
+
+                        /* even with no persistence of leases, we try to offer the same client
+                           the same IP address. we do this by using the hash of the client id
+                           as the offset into the pool of leases when finding the next free one */
+
+                        next_offer = client_id_hash_func(&req->client_id, HASH_KEY.bytes) % server->pool_size;
+
                         for (i = 0; i < server->pool_size; i++) {
-                                if (!server->bound_leases[server->next_offer]) {
-                                        address = htobe32(be32toh(server->pool_start) + server->next_offer);
+                                if (!server->bound_leases[next_offer]) {
+                                        address = htobe32(be32toh(server->pool_start) + next_offer);
                                         break;
                                 } else
-                                        server->next_offer = (server->next_offer + 1) % server->pool_size;
+                                        next_offer = (next_offer + 1) % server->pool_size;
                         }
                 }