diff options
author | Hans Dedecker <dedeckeh@gmail.com> | 2018-06-21 10:25:53 +0200 |
---|---|---|
committer | Hans Dedecker <dedeckeh@gmail.com> | 2018-06-22 15:10:38 +0200 |
commit | bb8470f590b7b51de6f8acbaa63ad185c0388e84 (patch) | |
tree | 61dada6109b87e52f13d2a5f782a3bcbd93c85f9 | |
parent | 62a1b09c5fb018b8ee223e0ccea5a9e084918570 (diff) |
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 <dedeckeh@gmail.com>
-rw-r--r-- | src/dhcpv4.c | 25 |
1 files changed, 24 insertions, 1 deletions
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); |