From bb8470f590b7b51de6f8acbaa63ad185c0388e84 Mon Sep 17 00:00:00 2001 From: Hans Dedecker Date: Thu, 21 Jun 2018 10:25:53 +0200 Subject: [PATCH] dhcpv4: delay forced renew transaction start Delay the start of the forced renew transaction start with a random delay between 500 and 1000 ms. This avoids sending DHCP forced renew messages in case the DHCP client starts sending discover messages triggered by link state flap. Also it distributes sending of DHCP forced renew messages to different clients over an interval instead of sending DHCP forced renew messages in a burst mode. Signed-off-by: Hans Dedecker --- src/dhcpv4.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/dhcpv4.c b/src/dhcpv4.c index 8c9e9ba..dc10ba3 100644 --- a/src/dhcpv4.c +++ b/src/dhcpv4.c @@ -43,6 +43,7 @@ static void valid_until_cb(struct uloop_timeout *event); static void handle_addrlist_change(struct interface *iface); static void free_dhcpv4_assignment(struct dhcpv4_assignment *a); static void dhcpv4_fr_start(struct dhcpv4_assignment *a); +static void dhcpv4_fr_rand_delay(struct dhcpv4_assignment *a); static void dhcpv4_fr_stop(struct dhcpv4_assignment *a); static void handle_dhcpv4(void *addr, void *data, size_t len, struct interface *iface, void *dest_addr); @@ -461,7 +462,7 @@ static void handle_addrlist_change(struct interface *iface) list_for_each_entry(c, &iface->dhcpv4_assignments, head) { if ((c->flags & OAF_BOUND) && c->fr_ip && !c->fr_cnt) { if (c->accept_fr_nonce || iface->dhcpv4_forcereconf) - dhcpv4_fr_start(c); + dhcpv4_fr_rand_delay(c); else dhcpv4_fr_stop(c); } @@ -630,6 +631,28 @@ static void dhcpv4_fr_start(struct dhcpv4_assignment *a) dhcpv4_fr_send(a); } +static void dhcpv4_fr_delay_timer(struct uloop_timeout *event) +{ + struct dhcpv4_assignment *a = container_of(event, struct dhcpv4_assignment, fr_timer); + struct interface *iface = a->iface; + + (iface->dhcpv4_event.uloop.fd == -1 ? dhcpv4_fr_rand_delay(a) : dhcpv4_fr_start(a)); +} + +static void dhcpv4_fr_rand_delay(struct dhcpv4_assignment *a) +{ +#define MIN_DELAY 500 +#define MAX_FUZZ 500 + int msecs; + + odhcpd_urandom(&msecs, sizeof(msecs)); + + msecs = labs(msecs)%MAX_FUZZ + MIN_DELAY; + + uloop_timeout_set(&a->fr_timer, msecs); + a->fr_timer.cb = dhcpv4_fr_delay_timer; +} + static void dhcpv4_fr_stop(struct dhcpv4_assignment *a) { uloop_timeout_cancel(&a->fr_timer); -- 2.30.2