X Tutup
Skip to content

Commit eef5ebe

Browse files
authored
Merge pull request systemd#21143 from yuwata/sd-radv-router-lifetime
sd-radv: several cleanups for router lifetime
2 parents 6663b50 + 4f1ac4a commit eef5ebe

File tree

9 files changed

+175
-87
lines changed

9 files changed

+175
-87
lines changed

man/systemd.network.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2622,7 +2622,8 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
26222622
<term><varname>RouterLifetimeSec=</varname></term>
26232623

26242624
<listitem><para>Takes a timespan. Configures the IPv6 router lifetime in seconds. When set to
2625-
0, the host is not acting as a router. Defaults to 30 minutes.</para>
2625+
0, the host is not acting as a router. The value must be 0 second, or between 4 seconds and
2626+
9000 seconds. Defaults to 1800 seconds (30 minutes).</para>
26262627
</listitem>
26272628
</varlistentry>
26282629

src/libsystemd-network/radv-internal.h

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,54 @@
1010
#include "list.h"
1111
#include "network-common.h"
1212
#include "sparse-endian.h"
13-
14-
assert_cc(SD_RADV_DEFAULT_MIN_TIMEOUT_USEC <= SD_RADV_DEFAULT_MAX_TIMEOUT_USEC);
15-
16-
#define SD_RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC (16*USEC_PER_SEC)
17-
#define SD_RADV_MAX_INITIAL_RTR_ADVERTISEMENTS 3
18-
#define SD_RADV_MAX_FINAL_RTR_ADVERTISEMENTS 3
19-
#define SD_RADV_MIN_DELAY_BETWEEN_RAS 3
20-
#define SD_RADV_MAX_RA_DELAY_TIME_USEC (500*USEC_PER_MSEC)
21-
22-
#define SD_RADV_OPT_ROUTE_INFORMATION 24
23-
#define SD_RADV_OPT_RDNSS 25
24-
#define SD_RADV_OPT_DNSSL 31
13+
#include "time-util.h"
14+
15+
/* RFC 4861 section 6.2.1.
16+
* MaxRtrAdvInterval
17+
* The maximum time allowed between sending unsolicited multicast Router Advertisements from the
18+
* interface, in seconds. MUST be no less than 4 seconds and no greater than 1800 seconds.
19+
* Default: 600 seconds */
20+
#define RADV_MIN_MAX_TIMEOUT_USEC (4 * USEC_PER_SEC)
21+
#define RADV_MAX_MAX_TIMEOUT_USEC (1800 * USEC_PER_SEC)
22+
#define RADV_DEFAULT_MAX_TIMEOUT_USEC (600 * USEC_PER_SEC)
23+
/* RFC 4861 section 6.2.1.
24+
* MinRtrAdvInterval
25+
* The minimum time allowed between sending unsolicited multicast Router Advertisements from the
26+
* interface, in seconds. MUST be no less than 3 seconds and no greater than .75 * MaxRtrAdvInterval.
27+
* Default: 0.33 * MaxRtrAdvInterval If MaxRtrAdvInterval >= 9 seconds; otherwise, the Default is
28+
* MaxRtrAdvInterval (Note, this should be a typo. We use 0.75 * MaxRtrAdvInterval). */
29+
#define RADV_MIN_MIN_TIMEOUT_USEC (3 * USEC_PER_SEC)
30+
/* RFC 4861 section 6.2.4.
31+
* AdvDefaultLifetime
32+
* The value to be placed in the Router Lifetime field of Router Advertisements sent from the interface,
33+
* in seconds. MUST be either zero or between MaxRtrAdvInterval and 9000 seconds. A value of zero
34+
* indicates that the router is not to be used as a default router. These limits may be overridden by
35+
* specific documents that describe how IPv6 operates over different link layers. For instance, in a
36+
* point-to-point link the peers may have enough information about the number and status of devices at
37+
* the other end so that advertisements are needed less frequently.
38+
* Default: 3 * MaxRtrAdvInterval */
39+
#define RADV_MIN_ROUTER_LIFETIME_USEC RADV_MIN_MAX_TIMEOUT_USEC
40+
#define RADV_MAX_ROUTER_LIFETIME_USEC (9000 * USEC_PER_SEC)
41+
#define RADV_DEFAULT_ROUTER_LIFETIME_USEC (3 * RADV_DEFAULT_MAX_TIMEOUT_USEC)
42+
/* RFC 4861 section 10.
43+
* MAX_INITIAL_RTR_ADVERT_INTERVAL 16 seconds
44+
* MAX_INITIAL_RTR_ADVERTISEMENTS 3 transmissions
45+
* MAX_FINAL_RTR_ADVERTISEMENTS 3 transmissions
46+
* MIN_DELAY_BETWEEN_RAS 3 seconds
47+
* MAX_RA_DELAY_TIME .5 seconds */
48+
#define RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC (16 * USEC_PER_SEC)
49+
#define RADV_MAX_INITIAL_RTR_ADVERTISEMENTS 3
50+
#define RADV_MAX_FINAL_RTR_ADVERTISEMENTS 3
51+
#define RADV_MIN_DELAY_BETWEEN_RAS 3
52+
#define RADV_MAX_RA_DELAY_TIME_USEC (500 * USEC_PER_MSEC)
53+
54+
#define RADV_OPT_ROUTE_INFORMATION 24
55+
#define RADV_OPT_RDNSS 25
56+
#define RADV_OPT_DNSSL 31
2557

2658
enum RAdvState {
27-
SD_RADV_STATE_IDLE = 0,
28-
SD_RADV_STATE_ADVERTISING = 1,
59+
RADV_STATE_IDLE = 0,
60+
RADV_STATE_ADVERTISING = 1,
2961
};
3062
typedef enum RAdvState RAdvState;
3163

@@ -50,7 +82,7 @@ struct sd_radv {
5082
uint8_t hop_limit;
5183
uint8_t flags;
5284
uint32_t mtu;
53-
uint16_t lifetime;
85+
usec_t lifetime_usec; /* timespan */
5486

5587
int fd;
5688
unsigned ra_sent;

src/libsystemd-network/sd-radv.c

Lines changed: 61 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ _public_ int sd_radv_new(sd_radv **ret) {
3838
*ra = (sd_radv) {
3939
.n_ref = 1,
4040
.fd = -1,
41+
.lifetime_usec = RADV_DEFAULT_ROUTER_LIFETIME_USEC,
4142
};
4243

4344
*ret = TAKE_PTR(ra);
@@ -81,7 +82,7 @@ _public_ sd_event *sd_radv_get_event(sd_radv *ra) {
8182
_public_ int sd_radv_is_running(sd_radv *ra) {
8283
assert_return(ra, false);
8384

84-
return ra->state != SD_RADV_STATE_IDLE;
85+
return ra->state != RADV_STATE_IDLE;
8586
}
8687

8788
static void radv_reset(sd_radv *ra) {
@@ -128,7 +129,13 @@ static sd_radv *radv_free(sd_radv *ra) {
128129

129130
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv, sd_radv, radv_free);
130131

131-
static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_lifetime) {
132+
static bool router_lifetime_is_valid(usec_t lifetime_usec) {
133+
return lifetime_usec == 0 ||
134+
(lifetime_usec >= RADV_MIN_ROUTER_LIFETIME_USEC &&
135+
lifetime_usec <= RADV_MAX_ROUTER_LIFETIME_USEC);
136+
}
137+
138+
static int radv_send(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_usec) {
132139
sd_radv_route_prefix *rt;
133140
sd_radv_prefix *p;
134141
struct sockaddr_in6 dst_addr = {
@@ -162,6 +169,7 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_li
162169
int r;
163170

164171
assert(ra);
172+
assert(router_lifetime_is_valid(lifetime_usec));
165173

166174
r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now);
167175
if (r < 0)
@@ -173,7 +181,8 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_li
173181
adv.nd_ra_type = ND_ROUTER_ADVERT;
174182
adv.nd_ra_curhoplimit = ra->hop_limit;
175183
adv.nd_ra_flags_reserved = ra->flags;
176-
adv.nd_ra_router_lifetime = htobe16(router_lifetime);
184+
assert_cc(RADV_MAX_ROUTER_LIFETIME_USEC <= UINT16_MAX * USEC_PER_SEC);
185+
adv.nd_ra_router_lifetime = htobe16(DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC));
177186
iov[msg.msg_iovlen++] = IOVEC_MAKE(&adv, sizeof(adv));
178187

179188
/* MAC address is optional, either because the link does not use L2
@@ -274,7 +283,7 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
274283

275284
(void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &src, &addr);
276285

277-
r = radv_send(ra, &src, ra->lifetime);
286+
r = radv_send(ra, &src, ra->lifetime_usec);
278287
if (r < 0)
279288
log_radv_errno(ra, r, "Unable to send solicited Router Advertisement to %s, ignoring: %m", strnull(addr));
280289
else
@@ -283,54 +292,54 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
283292
return 0;
284293
}
285294

286-
static usec_t radv_compute_timeout(usec_t min, usec_t max) {
287-
assert_return(min <= max, SD_RADV_DEFAULT_MIN_TIMEOUT_USEC);
288-
289-
/* RFC 4861: min must be no less than 3s, max must be no less than 4s */
290-
min = MAX(min, 3*USEC_PER_SEC);
291-
max = MAX(max, 4*USEC_PER_SEC);
292-
293-
return min + (random_u32() % (max - min));
294-
}
295-
296295
static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
297-
int r;
296+
usec_t min_timeout, max_timeout, time_now, timeout;
298297
sd_radv *ra = userdata;
299-
usec_t min_timeout = SD_RADV_DEFAULT_MIN_TIMEOUT_USEC;
300-
usec_t max_timeout = SD_RADV_DEFAULT_MAX_TIMEOUT_USEC;
301-
usec_t time_now, timeout;
298+
int r;
302299

303300
assert(s);
304301
assert(ra);
305302
assert(ra->event);
303+
assert(router_lifetime_is_valid(ra->lifetime_usec));
306304

307305
r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now);
308306
if (r < 0)
309307
goto fail;
310308

311-
r = radv_send(ra, NULL, ra->lifetime);
309+
r = radv_send(ra, NULL, ra->lifetime_usec);
312310
if (r < 0)
313311
log_radv_errno(ra, r, "Unable to send Router Advertisement: %m");
314312

315313
/* RFC 4861, Section 6.2.4, sending initial Router Advertisements */
316-
if (ra->ra_sent < SD_RADV_MAX_INITIAL_RTR_ADVERTISEMENTS) {
317-
max_timeout = SD_RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC;
318-
min_timeout = SD_RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC / 3;
319-
}
314+
if (ra->ra_sent < RADV_MAX_INITIAL_RTR_ADVERTISEMENTS)
315+
max_timeout = RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC;
316+
else
317+
max_timeout = RADV_DEFAULT_MAX_TIMEOUT_USEC;
320318

321319
/* RFC 4861, Section 6.2.1, lifetime must be at least MaxRtrAdvInterval,
322-
so lower the interval here */
323-
if (ra->lifetime > 0 && (ra->lifetime * USEC_PER_SEC) < max_timeout) {
324-
max_timeout = ra->lifetime * USEC_PER_SEC;
320+
* so lower the interval here */
321+
if (ra->lifetime_usec > 0)
322+
max_timeout = MIN(max_timeout, ra->lifetime_usec);
323+
324+
if (max_timeout >= 9 * USEC_PER_SEC)
325325
min_timeout = max_timeout / 3;
326-
}
326+
else
327+
min_timeout = max_timeout * 3 / 4;
327328

328-
timeout = radv_compute_timeout(min_timeout, max_timeout);
329+
/* RFC 4861, Section 6.2.1.
330+
* MaxRtrAdvInterval MUST be no less than 4 seconds and no greater than 1800 seconds.
331+
* MinRtrAdvInterval MUST be no less than 3 seconds and no greater than .75 * MaxRtrAdvInterval. */
332+
assert(max_timeout >= RADV_MIN_MAX_TIMEOUT_USEC);
333+
assert(max_timeout <= RADV_MAX_MAX_TIMEOUT_USEC);
334+
assert(min_timeout >= RADV_MIN_MIN_TIMEOUT_USEC);
335+
assert(min_timeout <= max_timeout * 3 / 4);
336+
337+
timeout = min_timeout + random_u64_range(max_timeout - min_timeout);
329338
log_radv(ra, "Next Router Advertisement in %s", FORMAT_TIMESPAN(timeout, USEC_PER_SEC));
330339

331340
r = event_reset_time(ra->event, &ra->timeout_event_source,
332341
clock_boottime_or_monotonic(),
333-
time_now + timeout, MSEC_PER_SEC,
342+
usec_add(time_now, timeout), MSEC_PER_SEC,
334343
radv_timeout, ra,
335344
ra->event_priority, "radv-timeout", true);
336345
if (r < 0)
@@ -352,7 +361,7 @@ _public_ int sd_radv_stop(sd_radv *ra) {
352361
if (!ra)
353362
return 0;
354363

355-
if (ra->state == SD_RADV_STATE_IDLE)
364+
if (ra->state == RADV_STATE_IDLE)
356365
return 0;
357366

358367
log_radv(ra, "Stopping IPv6 Router Advertisement daemon");
@@ -365,7 +374,7 @@ _public_ int sd_radv_stop(sd_radv *ra) {
365374

366375
radv_reset(ra);
367376
ra->fd = safe_close(ra->fd);
368-
ra->state = SD_RADV_STATE_IDLE;
377+
ra->state = RADV_STATE_IDLE;
369378

370379
return 0;
371380
}
@@ -377,7 +386,7 @@ _public_ int sd_radv_start(sd_radv *ra) {
377386
assert_return(ra->event, -EINVAL);
378387
assert_return(ra->ifindex > 0, -EINVAL);
379388

380-
if (ra->state != SD_RADV_STATE_IDLE)
389+
if (ra->state != RADV_STATE_IDLE)
381390
return 0;
382391

383392
r = event_reset_time(ra->event, &ra->timeout_event_source,
@@ -404,7 +413,7 @@ _public_ int sd_radv_start(sd_radv *ra) {
404413

405414
(void) sd_event_source_set_description(ra->recv_event_source, "radv-receive-message");
406415

407-
ra->state = SD_RADV_STATE_ADVERTISING;
416+
ra->state = RADV_STATE_ADVERTISING;
408417

409418
log_radv(ra, "Started IPv6 Router Advertisement daemon");
410419

@@ -420,7 +429,7 @@ _public_ int sd_radv_set_ifindex(sd_radv *ra, int ifindex) {
420429
assert_return(ra, -EINVAL);
421430
assert_return(ifindex > 0, -EINVAL);
422431

423-
if (ra->state != SD_RADV_STATE_IDLE)
432+
if (ra->state != RADV_STATE_IDLE)
424433
return -EBUSY;
425434

426435
ra->ifindex = ifindex;
@@ -456,7 +465,7 @@ int sd_radv_get_ifname(sd_radv *ra, const char **ret) {
456465
_public_ int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr) {
457466
assert_return(ra, -EINVAL);
458467

459-
if (ra->state != SD_RADV_STATE_IDLE)
468+
if (ra->state != RADV_STATE_IDLE)
460469
return -EBUSY;
461470

462471
if (mac_addr)
@@ -479,35 +488,38 @@ _public_ int sd_radv_set_mtu(sd_radv *ra, uint32_t mtu) {
479488
_public_ int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit) {
480489
assert_return(ra, -EINVAL);
481490

482-
if (ra->state != SD_RADV_STATE_IDLE)
491+
if (ra->state != RADV_STATE_IDLE)
483492
return -EBUSY;
484493

485494
ra->hop_limit = hop_limit;
486495

487496
return 0;
488497
}
489498

490-
_public_ int sd_radv_set_router_lifetime(sd_radv *ra, uint16_t router_lifetime) {
499+
_public_ int sd_radv_set_router_lifetime(sd_radv *ra, uint64_t lifetime_usec) {
491500
assert_return(ra, -EINVAL);
492501

493-
if (ra->state != SD_RADV_STATE_IDLE)
502+
if (ra->state != RADV_STATE_IDLE)
494503
return -EBUSY;
495504

505+
if (!router_lifetime_is_valid(lifetime_usec))
506+
return -EINVAL;
507+
496508
/* RFC 4191, Section 2.2, "...If the Router Lifetime is zero, the preference value MUST be set
497509
* to (00) by the sender..." */
498-
if (router_lifetime == 0 &&
510+
if (lifetime_usec == 0 &&
499511
(ra->flags & (0x3 << 3)) != (SD_NDISC_PREFERENCE_MEDIUM << 3))
500-
return -ETIME;
512+
return -EINVAL;
501513

502-
ra->lifetime = router_lifetime;
514+
ra->lifetime_usec = lifetime_usec;
503515

504516
return 0;
505517
}
506518

507519
_public_ int sd_radv_set_managed_information(sd_radv *ra, int managed) {
508520
assert_return(ra, -EINVAL);
509521

510-
if (ra->state != SD_RADV_STATE_IDLE)
522+
if (ra->state != RADV_STATE_IDLE)
511523
return -EBUSY;
512524

513525
SET_FLAG(ra->flags, ND_RA_FLAG_MANAGED, managed);
@@ -518,7 +530,7 @@ _public_ int sd_radv_set_managed_information(sd_radv *ra, int managed) {
518530
_public_ int sd_radv_set_other_information(sd_radv *ra, int other) {
519531
assert_return(ra, -EINVAL);
520532

521-
if (ra->state != SD_RADV_STATE_IDLE)
533+
if (ra->state != RADV_STATE_IDLE)
522534
return -EBUSY;
523535

524536
SET_FLAG(ra->flags, ND_RA_FLAG_OTHER, other);
@@ -535,7 +547,7 @@ _public_ int sd_radv_set_preference(sd_radv *ra, unsigned preference) {
535547

536548
/* RFC 4191, Section 2.2, "...If the Router Lifetime is zero, the preference value MUST be set
537549
* to (00) by the sender..." */
538-
if (ra->lifetime == 0 && preference != SD_NDISC_PREFERENCE_MEDIUM)
550+
if (ra->lifetime_usec == 0 && preference != SD_NDISC_PREFERENCE_MEDIUM)
539551
return -EINVAL;
540552

541553
ra->flags = (ra->flags & ~(0x3 << 3)) | (preference << 3);
@@ -595,7 +607,7 @@ _public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic) {
595607

596608
/* If RAs have already been sent, send an RA immediately to announce the newly-added prefix */
597609
if (ra->ra_sent > 0) {
598-
r = radv_send(ra, NULL, ra->lifetime);
610+
r = radv_send(ra, NULL, ra->lifetime_usec);
599611
if (r < 0)
600612
log_radv_errno(ra, r, "Unable to send Router Advertisement for added prefix: %m");
601613
else
@@ -698,7 +710,7 @@ _public_ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int
698710

699711
/* If RAs have already been sent, send an RA immediately to announce the newly-added route prefix */
700712
if (ra->ra_sent > 0) {
701-
r = radv_send(ra, NULL, ra->lifetime);
713+
r = radv_send(ra, NULL, ra->lifetime_usec);
702714
if (r < 0)
703715
log_radv_errno(ra, r, "Unable to send Router Advertisement for added route prefix: %m");
704716
else
@@ -743,7 +755,7 @@ _public_ int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime,
743755
if (!opt_rdnss)
744756
return -ENOMEM;
745757

746-
opt_rdnss->type = SD_RADV_OPT_RDNSS;
758+
opt_rdnss->type = RADV_OPT_RDNSS;
747759
opt_rdnss->length = len / 8;
748760
opt_rdnss->lifetime = htobe32(lifetime);
749761

@@ -779,7 +791,7 @@ _public_ int sd_radv_set_dnssl(sd_radv *ra, uint32_t lifetime,
779791
if (!opt_dnssl)
780792
return -ENOMEM;
781793

782-
opt_dnssl->type = SD_RADV_OPT_DNSSL;
794+
opt_dnssl->type = RADV_OPT_DNSSL;
783795
opt_dnssl->length = len / 8;
784796
opt_dnssl->lifetime = htobe32(lifetime);
785797

@@ -911,7 +923,7 @@ _public_ int sd_radv_route_prefix_new(sd_radv_route_prefix **ret) {
911923
*p = (sd_radv_route_prefix) {
912924
.n_ref = 1,
913925

914-
.opt.type = SD_RADV_OPT_ROUTE_INFORMATION,
926+
.opt.type = RADV_OPT_ROUTE_INFORMATION,
915927
.opt.length = DIV_ROUND_UP(sizeof(p->opt), 8),
916928
.opt.prefixlen = 64,
917929

0 commit comments

Comments
 (0)
X Tutup