udhcpd: optional IP selection based on MAC hash

function                                             old     new   delta
find_free_or_expired_nip                             153     225     +72

Signed-off-by: Vladislav Grishenko <themiron@mail.ru>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Vladislav Grishenko 2011-02-16 13:31:30 +01:00 committed by Denys Vlasenko
parent 4fdb67cc65
commit 5827167338
2 changed files with 50 additions and 8 deletions

View File

@ -39,7 +39,21 @@ config FEATURE_UDHCPD_WRITE_LEASES_EARLY
If selected, udhcpd will write a new file with leases every
time a new lease has been accepted, thus eliminating the need
to send SIGUSR1 for the initial writing or updating. Any timed
rewriting remains undisturbed
rewriting remains undisturbed.
config FEATURE_UDHCPD_BASE_IP_ON_MAC
bool "Select IP address based on client MAC"
default n
depends on UDHCPD
help
If selected, udhcpd will base its selection of IP address to offer
on the client's hardware address. Otherwise udhcpd uses the next
consecutive free address.
This reduces the frequency of IP address changes for clients
which let their lease expire, and makes consecutive DHCPOFFERS
for the same client to (almost always) contain the same
IP address.
config DHCPD_LEASES_FILE
string "Absolute path to lease file"
@ -72,7 +86,7 @@ config FEATURE_UDHCPC_ARPING
config FEATURE_UDHCP_PORT
bool "Enable '-P port' option for udhcpd and udhcpc"
default y
default n
depends on UDHCPD || UDHCPC
help
At the cost of ~300 bytes, enables -P port option.

View File

@ -137,21 +137,42 @@ uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac)
uint32_t addr;
struct dyn_lease *oldest_lease = NULL;
addr = server_config.start_ip; /* addr is in host order here */
for (; addr <= server_config.end_ip; addr++) {
#if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC
uint32_t stop;
unsigned i, hash;
/* hash hwaddr: use the SDBM hashing algorithm. Seems to give good
* dispersal even with similarly-valued "strings".
*/
hash = 0;
for (i = 0; i < 6; i++)
hash += safe_mac[i] + (hash << 6) + (hash << 16) - hash;
/* pick a seed based on hwaddr then iterate until we find a free address. */
addr = server_config.start_ip
+ (hash % (1 + server_config.end_ip - server_config.start_ip));
stop = addr;
#else
addr = server_config.start_ip;
#define stop (server_config.end_ip + 1)
#endif
do {
uint32_t nip;
struct dyn_lease *lease;
/* ie, 192.168.55.0 */
if ((addr & 0xff) == 0)
continue;
goto next_addr;
/* ie, 192.168.55.255 */
if ((addr & 0xff) == 0xff)
continue;
goto next_addr;
nip = htonl(addr);
/* skip our own address */
if (nip == server_config.server_nip)
goto next_addr;
/* is this a static lease addr? */
if (is_nip_reserved(server_config.static_leases, nip))
continue;
goto next_addr;
lease = find_lease_by_nip(nip);
if (!lease) {
@ -162,7 +183,14 @@ uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac)
if (!oldest_lease || lease->expires < oldest_lease->expires)
oldest_lease = lease;
}
}
next_addr:
addr++;
#if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC
if (addr > server_config.end_ip)
addr = server_config.start_ip;
#endif
} while (addr != stop);
if (oldest_lease
&& is_expired_lease(oldest_lease)