diff options
author | Tom Gundersen <teg@jklm.no> | 2015-08-27 08:54:41 +0200 |
---|---|---|
committer | Tom Gundersen <teg@jklm.no> | 2015-08-28 11:05:32 +0200 |
commit | 83cedf7ae28925e37931e7e92d22be9c936a1def (patch) | |
tree | 89c615165cb234dc42da2ffe8554ab62e6f3ad92 /src | |
parent | 9c92a077b667fe3947cc8a9caa197dea8b80b8e0 (diff) |
sd-dhcp-server: improve predictability of leases
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).
Diffstat (limited to 'src')
-rw-r--r-- | src/libsystemd-network/dhcp-server-internal.h | 1 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp-server.c | 16 |
2 files changed, 13 insertions, 4 deletions
diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index 6cc794c937..268210fc50 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -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; diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index a46858258b..89b9a4c6be 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -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; } } |