net: dhcpv4_server: Improve declined addresses management
In case conflict is detected (either due to receiving Decline message or due to ICMP probe getting reply), the conflicting address becomes blocked for further use. Although the RFC is not specific about how long should the address be blocked, it make sense to implement some fallback mechanisms to reuse blocked addresses in the server, otherwise, after longer period of operation, it may run out of usable address. This commit adds a timeout for declined addresses, so that by default the address is marked back as "free" after 24 hrs (default lease time). It also implements a mechanism, which allows to re-use the oldest declined entry in case the server runs out of fresh addresses to assign. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
9e1eec9ced
commit
e28428caae
@ -110,6 +110,17 @@ config NET_DHCPV4_SERVER_ADDR_LEASE_TIME
|
||||
The lease time determines when the IPv4 address lease expires if the
|
||||
client does not renew it.
|
||||
|
||||
config NET_DHCPV4_SERVER_ADDR_DECLINE_TIME
|
||||
int "The time IPv4 addresses remains blocked after conflict detection (seconds)"
|
||||
default 86400
|
||||
help
|
||||
In case IPv4 address becomes blocked (either because of receiving
|
||||
Decline message or due to ICMP probe detecting conflict), the address
|
||||
can no longer be assigned. This timeout specifies how long the address
|
||||
remains in the Declined state.
|
||||
Note, that the server may try to reuse the oldest declined address in
|
||||
case it runs out of free addresses to assign.
|
||||
|
||||
config NET_DHCPV4_SERVER_ICMP_PROBE_TIMEOUT
|
||||
int "Timeout for ICMP probes sent by the server (miliseconds)"
|
||||
default 1000
|
||||
|
||||
@ -33,6 +33,7 @@ LOG_MODULE_REGISTER(net_dhcpv4_server, CONFIG_NET_DHCPV4_SERVER_LOG_LEVEL);
|
||||
|
||||
#define ADDRESS_RESERVED_TIMEOUT K_SECONDS(5)
|
||||
#define ADDRESS_PROBE_TIMEOUT K_MSEC(CONFIG_NET_DHCPV4_SERVER_ICMP_PROBE_TIMEOUT)
|
||||
#define ADDRESS_DECLINED_TIMEOUT K_SECONDS(CONFIG_NET_DHCPV4_SERVER_ADDR_DECLINE_TIME)
|
||||
|
||||
#if (CONFIG_NET_DHCPV4_SERVER_ICMP_PROBE_TIMEOUT > 0)
|
||||
#define DHCPV4_SERVER_ICMP_PROBE 1
|
||||
@ -80,7 +81,8 @@ static void dhcpv4_server_timeout_recalc(struct dhcpv4_server_ctx *ctx)
|
||||
struct dhcpv4_addr_slot *slot = &ctx->addr_pool[i];
|
||||
|
||||
if (slot->state == DHCPV4_SERVER_ADDR_RESERVED ||
|
||||
slot->state == DHCPV4_SERVER_ADDR_ALLOCATED) {
|
||||
slot->state == DHCPV4_SERVER_ADDR_ALLOCATED ||
|
||||
slot->state == DHCPV4_SERVER_ADDR_DECLINED) {
|
||||
if (sys_timepoint_cmp(slot->expiry, next) < 0) {
|
||||
next = slot->expiry;
|
||||
}
|
||||
@ -738,6 +740,7 @@ static int echo_reply_handler(struct net_icmp_ctx *icmp_ctx,
|
||||
net_sprint_ipv4_addr(&probe_ctx->slot->addr));
|
||||
|
||||
probe_ctx->slot->state = DHCPV4_SERVER_ADDR_DECLINED;
|
||||
probe_ctx->slot->expiry = sys_timepoint_calc(ADDRESS_DECLINED_TIMEOUT);
|
||||
|
||||
/* Try to find next free address */
|
||||
for (int i = 0; i < ARRAY_SIZE(ctx->addr_pool); i++) {
|
||||
@ -933,6 +936,27 @@ static void dhcpv4_handle_discover(struct dhcpv4_server_ctx *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
/* In case no free address slot was found, as a last resort, try to
|
||||
* reuse the oldest declined entry, if present.
|
||||
*/
|
||||
if (selected == NULL) {
|
||||
for (int i = 0; i < ARRAY_SIZE(ctx->addr_pool); i++) {
|
||||
struct dhcpv4_addr_slot *slot = &ctx->addr_pool[i];
|
||||
|
||||
if (slot->state != DHCPV4_SERVER_ADDR_DECLINED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find first to expire (oldest) entry. */
|
||||
if ((selected == NULL) ||
|
||||
(sys_timepoint_cmp(slot->expiry,
|
||||
selected->expiry) < 0)) {
|
||||
selected = slot;
|
||||
probe = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selected == NULL) {
|
||||
LOG_ERR("No free address found in address pool");
|
||||
} else {
|
||||
@ -1190,7 +1214,8 @@ static void dhcpv4_handle_decline(struct dhcpv4_server_ctx *ctx,
|
||||
(slot->state == DHCPV4_SERVER_ADDR_RESERVED ||
|
||||
slot->state == DHCPV4_SERVER_ADDR_ALLOCATED)) {
|
||||
slot->state = DHCPV4_SERVER_ADDR_DECLINED;
|
||||
slot->expiry = sys_timepoint_calc(K_FOREVER);
|
||||
slot->expiry =
|
||||
sys_timepoint_calc(ADDRESS_DECLINED_TIMEOUT);
|
||||
dhcpv4_server_timeout_recalc(ctx);
|
||||
break;
|
||||
}
|
||||
@ -1280,6 +1305,11 @@ static void dhcpv4_server_timeout(struct k_work *work)
|
||||
slot->state = DHCPV4_SERVER_ADDR_FREE;
|
||||
}
|
||||
}
|
||||
|
||||
if (slot->state == DHCPV4_SERVER_ADDR_DECLINED &&
|
||||
sys_timepoint_expired(slot->expiry)) {
|
||||
slot->state = DHCPV4_SERVER_ADDR_FREE;
|
||||
}
|
||||
}
|
||||
|
||||
dhcpv4_server_timeout_recalc(ctx);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user