summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorHans Dedecker <dedeckeh@gmail.com>2018-06-21 10:25:53 +0200
committerHans Dedecker <dedeckeh@gmail.com>2018-06-22 15:10:38 +0200
commitbb8470f590b7b51de6f8acbaa63ad185c0388e84 (patch)
tree61dada6109b87e52f13d2a5f782a3bcbd93c85f9
parent62a1b09c5fb018b8ee223e0ccea5a9e084918570 (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.c25
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);