[systemd-devel] PATCH: Improve the reaction of IPv6 SLAAC to renumbering events
Fernando Gont
fgont at si6networks.com
Sun Mar 29 21:40:10 UTC 2020
Folks,
IPv6 SLAAC reacts pretty badly to renumbering events -- actually, it
doesn't react ;-) (The problem is described in detail here:
https://tools.ietf.org/html/draft-ietf-v6ops-slaac-renum-01)
There are multiple improvements to be applied (please see:
https://tools.ietf.org/html/draft-gont-6man-slaac-renum-05). This one is
the long-hanging fruit: employ saner lifetimes -- that is e.g. in the
case of PIOs, never prefer an address/prefix for longer than the Router
Lifetime.
I compiled and tested the code. And submitted a pull request
(https://github.com/systemd/systemd/pull/15260).
Thoughts?
The patch is this one, anyway:
---- cut here ----
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index fe1de6387e..e43ecaea19 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -19,6 +19,8 @@
#define NDISC_DNSSL_MAX 64U
#define NDISC_RDNSS_MAX 64U
#define NDISC_PREFIX_LFT_MIN 7200U
+#define NDISC_PREFIX_LFT_MAX ((uint64_t) 0xffffffff)
+#define DFLT_VLTIME_MULT ((uint64_t) 48)
#define DAD_CONFLICTS_IDGEN_RETRIES_RFC7217 3
@@ -344,6 +346,7 @@ static int ndisc_router_generate_addresses(Link
*link, unsigned prefixlen, uint3
}
static int ndisc_router_process_autonomous_prefix(Link *link,
sd_ndisc_router *rt) {
+ uint16_t router_lifetime;
uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining;
_cleanup_set_free_free_ Set *addresses = NULL;
_cleanup_(address_freep) Address *address = NULL;
@@ -368,10 +371,19 @@ static int
ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
if (r < 0)
return log_link_error_errno(link, r, "Failed to get
prefix valid lifetime: %m");
+ r = sd_ndisc_router_get_lifetime(rt, &router_lifetime);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to get
gateway lifetime from RA: %m");
+
+ if(router_lifetime * DFLT_VLTIME_MULT < NDISC_PREFIX_LFT_MAX)
+ lifetime_valid = MIN(lifetime_valid, router_lifetime *
DFLT_VLTIME_MULT);
+
r = sd_ndisc_router_prefix_get_preferred_lifetime(rt,
&lifetime_preferred);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get
prefix preferred lifetime: %m");
+ lifetime_preferred = MIN(lifetime_preferred, router_lifetime);
+
/* The preferred lifetime is never greater than the valid
lifetime */
if (lifetime_preferred > lifetime_valid)
return 0;
@@ -425,6 +437,7 @@ static int
ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
static int ndisc_router_process_onlink_prefix(Link *link,
sd_ndisc_router *rt) {
_cleanup_(route_freep) Route *route = NULL;
usec_t time_now;
+ uint16_t router_lifetime;
uint32_t lifetime;
unsigned prefixlen;
int r;
@@ -444,6 +457,16 @@ static int ndisc_router_process_onlink_prefix(Link
*link, sd_ndisc_router *rt) {
if (r < 0)
return log_link_error_errno(link, r, "Failed to get
prefix lifetime: %m");
+ r = sd_ndisc_router_get_lifetime(rt, &router_lifetime);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to get
gateway lifetime from RA: %m");
+
+ /* On-link prefix Valid Lifetimes are capped to Router Lifetime
* DFLT_VLTIME_MULT.
+ See draft-gont-6man-slaac-renum
+ */
+ if(router_lifetime * DFLT_VLTIME_MULT < NDISC_PREFIX_LFT_MAX)
+ lifetime = MIN(lifetime, router_lifetime *
DFLT_VLTIME_MULT);
+
r = route_new(&route);
if (r < 0)
return log_link_error_errno(link, r, "Could not
allocate route: %m");
@@ -477,6 +500,7 @@ static int ndisc_router_process_route(Link *link,
sd_ndisc_router *rt) {
struct in6_addr gateway;
uint32_t lifetime;
unsigned preference, prefixlen;
+ uint16_t router_lifetime;
usec_t time_now;
int r;
@@ -486,6 +510,13 @@ static int ndisc_router_process_route(Link *link,
sd_ndisc_router *rt) {
if (r < 0)
return log_link_warning_errno(link, r, "Failed to get
gateway address from RA: %m");
+ r = sd_ndisc_router_get_lifetime(rt, &router_lifetime);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to get
gateway lifetime from RA: %m");
+
+ /* Route Lifetimes are capped to Router Lifetime. See
draft-gont-6man-slaac-renum */
+ lifetime = MIN(lifetime, router_lifetime);
+
if (lifetime == 0)
return 0;
---- cut here ----
Patch also available at:
https://www.gont.com.ar/code/patch-fgont-systemd-networkd-cap-lifetimes.txt
Thanks!
Cheers,
--
Fernando Gont
SI6 Networks
e-mail: fgont at si6networks.com
PGP Fingerprint: 6666 31C6 D484 63B2 8FB1 E3C4 AE25 0D55 1D4E 7492
More information about the systemd-devel
mailing list