From 4c004e2a71af0864bd6308130d069ec8badf5748 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 5 Dec 2021 03:40:15 +0900 Subject: [PATCH 1/6] network: dhcp6pd: also allow to only assign prefix route for delegated prefix to upstream interface --- src/network/networkd-dhcp-prefix-delegation.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index dc4868300a..4d5cf3b23e 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -595,9 +595,6 @@ static int dhcp6_pd_distribute_prefix( if (link->network->dhcp6_pd_announce && !link->radv) continue; - if (link == dhcp6_link && !link->network->dhcp6_pd_assign) - continue; - r = dhcp6_pd_assign_prefix(link, pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec); if (r < 0) { if (link == dhcp6_link) From 5014e66019b5f9f4c23a32627af1907e9fa975a9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 5 Dec 2021 03:57:35 +0900 Subject: [PATCH 2/6] network: dhcp6pd: move dhcp6_pd_assign_prefixes() Preparation for the later commits. --- src/network/networkd-dhcp-prefix-delegation.c | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index 4d5cf3b23e..dbe7bcdc9a 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -770,6 +770,59 @@ static int dhcp6_pd_prefix_add(Link *link, const struct in6_addr *prefix, uint8_ return prefixlen <= 64; } +static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) { + usec_t timestamp_usec; + int r; + + assert(link); + assert(uplink); + assert(uplink->dhcp6_lease); + + /* This is similar to dhcp6_pd_prefix_acquired(), but called when a downstream interface + * appears later or reconfiguring the interface. */ + + r = sd_dhcp6_lease_get_timestamp(uplink->dhcp6_lease, clock_boottime_or_monotonic(), ×tamp_usec); + if (r < 0) + return r; + + r = dhcp6_pd_prepare(link); + if (r < 0) + return r; + + for (sd_dhcp6_lease_reset_pd_prefix_iter(uplink->dhcp6_lease);;) { + uint32_t lifetime_preferred_sec, lifetime_valid_sec; + usec_t lifetime_preferred_usec, lifetime_valid_usec; + struct in6_addr pd_prefix; + uint8_t pd_prefix_len; + + r = sd_dhcp6_lease_get_pd(uplink->dhcp6_lease, &pd_prefix, &pd_prefix_len, + &lifetime_preferred_sec, &lifetime_valid_sec); + if (r < 0) + break; + + lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec); + lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec); + + if (pd_prefix_len > 64) + continue; + + /* Mask prefix for safety. */ + r = in6_addr_mask(&pd_prefix, pd_prefix_len); + if (r < 0) + return r; + + r = dhcp6_pd_assign_prefix(link, &pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec); + if (r < 0) + return r; + } + + r = dhcp6_pd_finalize(link); + if (r < 0) + return r; + + return 0; +} + int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { usec_t timestamp_usec; Link *link; @@ -867,59 +920,6 @@ int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { return 0; } -static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) { - usec_t timestamp_usec; - int r; - - assert(link); - assert(uplink); - assert(uplink->dhcp6_lease); - - /* This is similar to dhcp6_pd_prefix_acquired(), but called when a downstream interface - * appears later or reconfiguring the interface. */ - - r = sd_dhcp6_lease_get_timestamp(uplink->dhcp6_lease, clock_boottime_or_monotonic(), ×tamp_usec); - if (r < 0) - return r; - - r = dhcp6_pd_prepare(link); - if (r < 0) - return r; - - for (sd_dhcp6_lease_reset_pd_prefix_iter(uplink->dhcp6_lease);;) { - uint32_t lifetime_preferred_sec, lifetime_valid_sec; - usec_t lifetime_preferred_usec, lifetime_valid_usec; - struct in6_addr pd_prefix; - uint8_t pd_prefix_len; - - r = sd_dhcp6_lease_get_pd(uplink->dhcp6_lease, &pd_prefix, &pd_prefix_len, - &lifetime_preferred_sec, &lifetime_valid_sec); - if (r < 0) - break; - - lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec); - lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec); - - if (pd_prefix_len > 64) - continue; - - /* Mask prefix for safety. */ - r = in6_addr_mask(&pd_prefix, pd_prefix_len); - if (r < 0) - return r; - - r = dhcp6_pd_assign_prefix(link, &pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec); - if (r < 0) - return r; - } - - r = dhcp6_pd_finalize(link); - if (r < 0) - return r; - - return 0; -} - static bool dhcp6_pd_uplink_is_ready(Link *link) { assert(link); From c3cd535132ddc5b6e4db5f74954e7d275d121282 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 5 Dec 2021 05:14:22 +0900 Subject: [PATCH 3/6] network: dhcp6pd: skip to assign prefixes to a downstream link if it is not ready --- src/network/networkd-dhcp-prefix-delegation.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index dbe7bcdc9a..44858c6603 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -621,7 +621,7 @@ static int dhcp6_pd_prepare(Link *link) { link_mark_addresses(link, NETWORK_CONFIG_SOURCE_DHCP6PD, NULL); link_mark_routes(link, NETWORK_CONFIG_SOURCE_DHCP6PD, NULL); - return 0; + return 1; } static int dhcp6_pd_finalize(Link *link) { @@ -781,11 +781,11 @@ static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) { /* This is similar to dhcp6_pd_prefix_acquired(), but called when a downstream interface * appears later or reconfiguring the interface. */ - r = sd_dhcp6_lease_get_timestamp(uplink->dhcp6_lease, clock_boottime_or_monotonic(), ×tamp_usec); - if (r < 0) + r = dhcp6_pd_prepare(link); + if (r <= 0) return r; - r = dhcp6_pd_prepare(link); + r = sd_dhcp6_lease_get_timestamp(uplink->dhcp6_lease, clock_boottime_or_monotonic(), ×tamp_usec); if (r < 0) return r; From 542d04950e75dcae230c28d5ffb7673d4867d7ac Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 5 Dec 2021 05:15:12 +0900 Subject: [PATCH 4/6] network: dhcp6pd: shorten code a bit --- src/network/networkd-dhcp-prefix-delegation.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index 44858c6603..d2d676c6f5 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -816,11 +816,7 @@ static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) { return r; } - r = dhcp6_pd_finalize(link); - if (r < 0) - return r; - - return 0; + return dhcp6_pd_finalize(link); } int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { From 21cf8e9e6de9badd521fa8926eff1b3867406d78 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 5 Dec 2021 05:15:57 +0900 Subject: [PATCH 5/6] network: dhcp6pd: first check prefixes, then calculate lifetime --- src/network/networkd-dhcp-prefix-delegation.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index d2d676c6f5..180a758c43 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -800,9 +800,6 @@ static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) { if (r < 0) break; - lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec); - lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec); - if (pd_prefix_len > 64) continue; @@ -811,6 +808,9 @@ static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) { if (r < 0) return r; + lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec); + lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec); + r = dhcp6_pd_assign_prefix(link, &pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec); if (r < 0) return r; From 416644567bf0b073af0ed24baf738b09a5598d06 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 5 Dec 2021 05:16:40 +0900 Subject: [PATCH 6/6] network: dhcp6pd: make dhcp6_pd_assign_prefixes() used also by dhcp6_pd_prefix_acquired() --- src/network/networkd-dhcp-prefix-delegation.c | 113 +++--------------- 1 file changed, 16 insertions(+), 97 deletions(-) diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index 180a758c43..00b79f09ee 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -570,44 +570,6 @@ static int dhcp6_pd_assign_prefix( return 1; } -static int dhcp6_pd_distribute_prefix( - Link *dhcp6_link, - const struct in6_addr *pd_prefix, - uint8_t pd_prefix_len, - usec_t lifetime_preferred_usec, - usec_t lifetime_valid_usec) { - - Link *link; - int r; - - assert(dhcp6_link); - assert(dhcp6_link->manager); - assert(pd_prefix); - assert(pd_prefix_len <= 64); - - HASHMAP_FOREACH(link, dhcp6_link->manager->links_by_index) { - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) - continue; - - if (!dhcp6_pd_is_uplink(link, dhcp6_link, /* accept_auto = */ true)) - continue; - - if (link->network->dhcp6_pd_announce && !link->radv) - continue; - - r = dhcp6_pd_assign_prefix(link, pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec); - if (r < 0) { - if (link == dhcp6_link) - return r; - - link_enter_failed(link); - continue; - } - } - - return 0; -} - static int dhcp6_pd_prepare(Link *link) { if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) return 0; @@ -630,12 +592,6 @@ static int dhcp6_pd_finalize(Link *link) { if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) return 0; - if (!link_dhcp6_pd_is_enabled(link)) - return 0; - - if (link->network->dhcp6_pd_announce && !link->radv) - return 0; - if (link->dhcp6_pd_messages == 0) { link->dhcp6_pd_configured = false; @@ -778,9 +734,6 @@ static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) { assert(uplink); assert(uplink->dhcp6_lease); - /* This is similar to dhcp6_pd_prefix_acquired(), but called when a downstream interface - * appears later or reconfiguring the interface. */ - r = dhcp6_pd_prepare(link); if (r <= 0) return r; @@ -831,23 +784,10 @@ int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { if (r < 0) return log_link_warning_errno(dhcp6_link, r, "Failed to get timestamp of DHCPv6 lease: %m"); - HASHMAP_FOREACH(link, dhcp6_link->manager->links_by_index) { - r = dhcp6_pd_prepare(link); - if (r < 0) { - /* When failed on the upstream interface (i.e., the case link == dhcp6_link), - * immediately abort the assignment of the prefixes. As, the all assigned - * prefixes will be dropped soon in link_enter_failed(), and it is meaningless - * to continue the assignment. */ - if (link == dhcp6_link) - return r; - - link_enter_failed(link); - } - } - + /* First, logs acquired prefixes and request unreachable routes. */ for (sd_dhcp6_lease_reset_pd_prefix_iter(dhcp6_link->dhcp6_lease);;) { uint32_t lifetime_preferred_sec, lifetime_valid_sec; - usec_t lifetime_preferred_usec, lifetime_valid_usec; + usec_t lifetime_valid_usec; struct in6_addr pd_prefix; uint8_t pd_prefix_len; @@ -856,7 +796,11 @@ int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { if (r < 0) break; - lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec); + /* Mask prefix for safety. */ + r = in6_addr_mask(&pd_prefix, pd_prefix_len); + if (r < 0) + return log_link_error_errno(dhcp6_link, r, "Failed to mask DHCPv6 PD prefix: %m"); + lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec); r = dhcp6_pd_prefix_add(dhcp6_link, &pd_prefix, pd_prefix_len); @@ -868,44 +812,19 @@ int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { r = dhcp6_request_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len, lifetime_valid_usec); if (r < 0) return r; - - /* We are doing prefix allocation in two steps: - * 1. all those links that have a preferred subnet id will be assigned their subnet - * 2. all those links that remain will receive prefixes in sequential order. Prefixes - * that were previously already allocated to another link will be skipped. - * The assignment has to be split in two phases since subnet id - * preferences should be honored. Meaning that any subnet id should be - * handed out to the requesting link and not to some link that didn't - * specify any preference. */ - - assert(pd_prefix_len <= 64); - - /* Mask prefix for safety. */ - r = in6_addr_mask(&pd_prefix, pd_prefix_len); - if (r < 0) - return log_link_error_errno(dhcp6_link, r, "Failed to mask DHCPv6 PD prefix: %m"); - - if (DEBUG_LOGGING) { - uint64_t n_prefixes = UINT64_C(1) << (64 - pd_prefix_len); - _cleanup_free_ char *buf = NULL; - - (void) in6_addr_prefix_to_string(&pd_prefix, pd_prefix_len, &buf); - log_link_debug(dhcp6_link, "Assigning up to %" PRIu64 " prefixes from %s", - n_prefixes, strna(buf)); - } - - r = dhcp6_pd_distribute_prefix(dhcp6_link, - &pd_prefix, - pd_prefix_len, - lifetime_preferred_usec, - lifetime_valid_usec); - if (r < 0) - return r; } + /* Then, assign subnet prefixes. */ HASHMAP_FOREACH(link, dhcp6_link->manager->links_by_index) { - r = dhcp6_pd_finalize(link); + if (!dhcp6_pd_is_uplink(link, dhcp6_link, /* accept_auto = */ true)) + continue; + + r = dhcp6_pd_assign_prefixes(link, dhcp6_link); if (r < 0) { + /* When failed on the upstream interface (i.e., the case link == dhcp6_link), + * immediately abort the assignment of the prefixes. As, the all assigned + * prefixes will be dropped soon in link_enter_failed(), and it is meaningless + * to continue the assignment. */ if (link == dhcp6_link) return r;