1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-30 06:25:37 +03:00

sd-radv: update how to calculate interval of sending advertisements

This commit is contained in:
Yu Watanabe 2021-10-27 16:08:22 +09:00
parent 0945767012
commit 804775577d
2 changed files with 25 additions and 24 deletions

View File

@ -17,6 +17,8 @@
* The maximum time allowed between sending unsolicited multicast Router Advertisements from the * The maximum time allowed between sending unsolicited multicast Router Advertisements from the
* interface, in seconds. MUST be no less than 4 seconds and no greater than 1800 seconds. * interface, in seconds. MUST be no less than 4 seconds and no greater than 1800 seconds.
* Default: 600 seconds */ * Default: 600 seconds */
#define RADV_MIN_MAX_TIMEOUT_USEC (4 * USEC_PER_SEC)
#define RADV_MAX_MAX_TIMEOUT_USEC (1800 * USEC_PER_SEC)
#define RADV_DEFAULT_MAX_TIMEOUT_USEC (600 * USEC_PER_SEC) #define RADV_DEFAULT_MAX_TIMEOUT_USEC (600 * USEC_PER_SEC)
/* RFC 4861 section 6.2.1. /* RFC 4861 section 6.2.1.
* MinRtrAdvInterval * MinRtrAdvInterval
@ -24,7 +26,7 @@
* interface, in seconds. MUST be no less than 3 seconds and no greater than .75 * MaxRtrAdvInterval. * interface, in seconds. MUST be no less than 3 seconds and no greater than .75 * MaxRtrAdvInterval.
* Default: 0.33 * MaxRtrAdvInterval If MaxRtrAdvInterval >= 9 seconds; otherwise, the Default is * Default: 0.33 * MaxRtrAdvInterval If MaxRtrAdvInterval >= 9 seconds; otherwise, the Default is
* MaxRtrAdvInterval (Note, this should be a typo. We use 0.75 * MaxRtrAdvInterval). */ * MaxRtrAdvInterval (Note, this should be a typo. We use 0.75 * MaxRtrAdvInterval). */
#define RADV_DEFAULT_MIN_TIMEOUT_USEC (RADV_DEFAULT_MAX_TIMEOUT_USEC / 3) #define RADV_MIN_MIN_TIMEOUT_USEC (3 * USEC_PER_SEC)
/* RFC 4861 section 6.2.4. /* RFC 4861 section 6.2.4.
* AdvDefaultLifetime * AdvDefaultLifetime
* The value to be placed in the Router Lifetime field of Router Advertisements sent from the interface, * The value to be placed in the Router Lifetime field of Router Advertisements sent from the interface,
@ -34,7 +36,7 @@
* point-to-point link the peers may have enough information about the number and status of devices at * point-to-point link the peers may have enough information about the number and status of devices at
* the other end so that advertisements are needed less frequently. * the other end so that advertisements are needed less frequently.
* Default: 3 * MaxRtrAdvInterval */ * Default: 3 * MaxRtrAdvInterval */
#define RADV_MIN_ROUTER_LIFETIME_USEC (4 * USEC_PER_SEC) #define RADV_MIN_ROUTER_LIFETIME_USEC RADV_MIN_MAX_TIMEOUT_USEC
#define RADV_MAX_ROUTER_LIFETIME_USEC (9000 * USEC_PER_SEC) #define RADV_MAX_ROUTER_LIFETIME_USEC (9000 * USEC_PER_SEC)
#define RADV_DEFAULT_ROUTER_LIFETIME_USEC (3 * RADV_DEFAULT_MAX_TIMEOUT_USEC) #define RADV_DEFAULT_ROUTER_LIFETIME_USEC (3 * RADV_DEFAULT_MAX_TIMEOUT_USEC)
/* RFC 4861 section 10. /* RFC 4861 section 10.

View File

@ -292,16 +292,6 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
return 0; return 0;
} }
static usec_t radv_compute_timeout(usec_t min, usec_t max) {
assert_return(min <= max, RADV_DEFAULT_MIN_TIMEOUT_USEC);
/* RFC 4861: min must be no less than 3s, max must be no less than 4s */
min = MAX(min, 3*USEC_PER_SEC);
max = MAX(max, 4*USEC_PER_SEC);
return min + (random_u32() % (max - min));
}
static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) { static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
usec_t min_timeout, max_timeout, time_now, timeout; usec_t min_timeout, max_timeout, time_now, timeout;
sd_radv *ra = userdata; sd_radv *ra = userdata;
@ -310,6 +300,7 @@ static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
assert(s); assert(s);
assert(ra); assert(ra);
assert(ra->event); assert(ra->event);
assert(router_lifetime_is_valid(ra->lifetime_usec));
r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now); r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now);
if (r < 0) if (r < 0)
@ -320,27 +311,35 @@ static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
log_radv_errno(ra, r, "Unable to send Router Advertisement: %m"); log_radv_errno(ra, r, "Unable to send Router Advertisement: %m");
/* RFC 4861, Section 6.2.4, sending initial Router Advertisements */ /* RFC 4861, Section 6.2.4, sending initial Router Advertisements */
if (ra->ra_sent < RADV_MAX_INITIAL_RTR_ADVERTISEMENTS) { if (ra->ra_sent < RADV_MAX_INITIAL_RTR_ADVERTISEMENTS)
max_timeout = RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC; max_timeout = RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC;
min_timeout = RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC / 3; else
} else {
max_timeout = RADV_DEFAULT_MAX_TIMEOUT_USEC; max_timeout = RADV_DEFAULT_MAX_TIMEOUT_USEC;
min_timeout = RADV_DEFAULT_MIN_TIMEOUT_USEC;
}
/* RFC 4861, Section 6.2.1, lifetime must be at least MaxRtrAdvInterval, /* RFC 4861, Section 6.2.1, lifetime must be at least MaxRtrAdvInterval,
so lower the interval here */ * so lower the interval here */
if (ra->lifetime_usec > 0 && ra->lifetime_usec < max_timeout) { if (ra->lifetime_usec > 0)
max_timeout = ra->lifetime_usec; max_timeout = MIN(max_timeout, ra->lifetime_usec);
min_timeout = max_timeout / 3;
}
timeout = radv_compute_timeout(min_timeout, max_timeout); if (max_timeout >= 9 * USEC_PER_SEC)
min_timeout = max_timeout / 3;
else
min_timeout = max_timeout * 3 / 4;
/* RFC 4861, Section 6.2.1.
* MaxRtrAdvInterval MUST be no less than 4 seconds and no greater than 1800 seconds.
* MinRtrAdvInterval MUST be no less than 3 seconds and no greater than .75 * MaxRtrAdvInterval. */
assert(max_timeout >= RADV_MIN_MAX_TIMEOUT_USEC);
assert(max_timeout <= RADV_MAX_MAX_TIMEOUT_USEC);
assert(min_timeout >= RADV_MIN_MIN_TIMEOUT_USEC);
assert(min_timeout <= max_timeout * 3 / 4);
timeout = min_timeout + random_u64_range(max_timeout - min_timeout);
log_radv(ra, "Next Router Advertisement in %s", FORMAT_TIMESPAN(timeout, USEC_PER_SEC)); log_radv(ra, "Next Router Advertisement in %s", FORMAT_TIMESPAN(timeout, USEC_PER_SEC));
r = event_reset_time(ra->event, &ra->timeout_event_source, r = event_reset_time(ra->event, &ra->timeout_event_source,
clock_boottime_or_monotonic(), clock_boottime_or_monotonic(),
time_now + timeout, MSEC_PER_SEC, usec_add(time_now, timeout), MSEC_PER_SEC,
radv_timeout, ra, radv_timeout, ra,
ra->event_priority, "radv-timeout", true); ra->event_priority, "radv-timeout", true);
if (r < 0) if (r < 0)