diff options
author | Steven Barth <steven@midlink.org> | 2014-02-17 14:15:27 +0100 |
---|---|---|
committer | Steven Barth <steven@midlink.org> | 2014-02-17 14:15:27 +0100 |
commit | 6d644f0991c51fffcc5312e73b42126b7c6559bf (patch) | |
tree | c4c95db81b3ef402f0cf88fae1d8a9298394b251 | |
parent | b618ad5373ae619e3d01a49f2c672a8cc1dc59a6 (diff) |
Dynamically calculate RA intervals when prefix lifetimes are short
-rw-r--r-- | src/router.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/src/router.c b/src/router.c index dfbcf60..372c400 100644 --- a/src/router.c +++ b/src/router.c @@ -273,6 +273,7 @@ static void send_router_advert(struct uloop_timeout *event) // If not currently shutting down struct odhcpd_ipaddr addrs[RELAYD_MAX_PREFIXES]; ssize_t ipcnt = 0; + uint64_t maxpreferred = 0; // If not shutdown if (event->cb) { @@ -318,9 +319,13 @@ static void send_router_advert(struct uloop_timeout *event) p = &adv.prefix[cnt++]; } - if ((addr->addr.s6_addr[0] & 0xfe) != 0xfc && addr->preferred > 0) + if ((addr->addr.s6_addr[0] & 0xfe) != 0xfc && addr->preferred > 0) { have_public = true; + if (maxpreferred < 1000 * addr->preferred) + maxpreferred = 1000 * addr->preferred; + } + memcpy(&p->nd_opt_pi_prefix, &addr->addr, 8); p->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; p->nd_opt_pi_len = 4; @@ -453,10 +458,23 @@ static void send_router_advert(struct uloop_timeout *event) // Rearm timer if not shut down if (event->cb) { + uint32_t maxinterval = MaxRtrAdvInterval * 1000; + uint32_t mininterval = MinRtrAdvInterval * 1000; + + if (maxpreferred > 0 && maxinterval > maxpreferred / 2) { + maxinterval = maxpreferred / 2; + if (maxinterval < 4000) + maxinterval = 4000; + + if (maxinterval >= 9000) + mininterval = maxinterval / 3; + else + mininterval = (maxinterval * 3) / 4; + } + int msecs; odhcpd_urandom(&msecs, sizeof(msecs)); - msecs = (labs(msecs) % (1000 * (MaxRtrAdvInterval - - MinRtrAdvInterval))) + (MinRtrAdvInterval * 1000); + msecs = (labs(msecs) % (maxinterval - mininterval)) + mininterval; uloop_timeout_set(&iface->timer_rs, msecs); } } |