From a254fab20dcad1f605f979da3373ff20d2e65db6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 16 Jun 2021 03:37:57 +0900 Subject: [PATCH] network: use request queue to configure IPv6 RA engine --- src/network/networkd-link.c | 8 +-- src/network/networkd-queue.c | 16 +++++- src/network/networkd-queue.h | 1 + src/network/networkd-radv.c | 98 +++++++++++++++++++++++++++--------- src/network/networkd-radv.h | 8 +-- 5 files changed, 98 insertions(+), 33 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 3a56f89f0b4..17fb932f81a 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -618,12 +618,8 @@ static int link_acquire_dynamic_ipv6_conf(Link *link) { log_link_debug(link, "Starting IPv6 Router Advertisements"); - r = radv_emit_dns(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to configure DNS or Domains in IPv6 Router Advertisement: %m"); - r = sd_radv_start(link->radv); - if (r < 0 && r != -EBUSY) + if (r < 0) return log_link_warning_errno(link, r, "Could not start IPv6 Router Advertisement: %m"); } @@ -1147,7 +1143,7 @@ static int link_configure(Link *link) { if (r < 0) return r; - r = radv_configure(link); + r = link_request_radv(link); if (r < 0) return r; diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index bc0012e6d83..27a16f29517 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -43,6 +43,8 @@ static void request_free_object(RequestType type, void *object) { case REQUEST_TYPE_NEXTHOP: nexthop_free(object); break; + case REQUEST_TYPE_RADV: + break; case REQUEST_TYPE_ROUTE: route_free(object); break; @@ -121,6 +123,9 @@ static void request_hash_func(const Request *req, struct siphash *state) { case REQUEST_TYPE_NEXTHOP: nexthop_hash_func(req->nexthop, state); break; + case REQUEST_TYPE_RADV: + /* This type does not have an object. */ + break; case REQUEST_TYPE_ROUTE: route_hash_func(req->route, state); break; @@ -174,6 +179,8 @@ static int request_compare_func(const struct Request *a, const struct Request *b return nexthop_compare_func(a->nexthop, b->nexthop); case REQUEST_TYPE_ROUTE: return route_compare_func(a->route, b->route); + case REQUEST_TYPE_RADV: + return 0; case REQUEST_TYPE_ROUTING_POLICY_RULE: return routing_policy_rule_compare_func(a->rule, b->rule); case REQUEST_TYPE_SET_LINK: @@ -211,10 +218,14 @@ int link_queue_request( assert(IN_SET(type, REQUEST_TYPE_ACTIVATE_LINK, REQUEST_TYPE_DHCP_SERVER, + REQUEST_TYPE_RADV, REQUEST_TYPE_SET_LINK, REQUEST_TYPE_UP_DOWN) || object); - assert(type == REQUEST_TYPE_DHCP_SERVER || netlink_handler); + assert(IN_SET(type, + REQUEST_TYPE_DHCP_SERVER, + REQUEST_TYPE_RADV) || + netlink_handler); req = new(Request, 1); if (!req) { @@ -298,6 +309,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) { case REQUEST_TYPE_NEXTHOP: r = request_process_nexthop(req); break; + case REQUEST_TYPE_RADV: + r = request_process_radv(req); + break; case REQUEST_TYPE_ROUTE: r = request_process_route(req); break; diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 1f4b15f087d..85d2be7367d 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -31,6 +31,7 @@ typedef enum RequestType { REQUEST_TYPE_IPV6_PROXY_NDP, REQUEST_TYPE_NEIGHBOR, REQUEST_TYPE_NEXTHOP, + REQUEST_TYPE_RADV, REQUEST_TYPE_ROUTE, REQUEST_TYPE_ROUTING_POLICY_RULE, REQUEST_TYPE_SET_LINK, diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 805d3fff6cc..a21f69d6f3b 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -10,6 +10,7 @@ #include "networkd-link.h" #include "networkd-manager.h" #include "networkd-network.h" +#include "networkd-queue.h" #include "networkd-radv.h" #include "parse-util.h" #include "string-util.h" @@ -595,7 +596,7 @@ static int radv_set_dns(Link *link, Link *uplink) { return 0; - set_dns: +set_dns: return sd_radv_set_rdnss(link->radv, DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC), dns, n_dns); @@ -634,7 +635,7 @@ static int radv_set_domains(Link *link, Link *uplink) { return 0; - set_domains: +set_domains: s = ordered_set_get_strv(search_domains); if (!s) return log_oom(); @@ -645,23 +646,6 @@ static int radv_set_domains(Link *link, Link *uplink) { } -int radv_emit_dns(Link *link) { - Link *uplink = NULL; - int r; - - (void) manager_find_uplink(link->manager, AF_INET6, link, &uplink); - - r = radv_set_dns(link, uplink); - if (r < 0) - log_link_warning_errno(link, r, "Could not set RA DNS: %m"); - - r = radv_set_domains(link, uplink); - if (r < 0) - log_link_warning_errno(link, r, "Could not set RA Domains: %m"); - - return 0; -} - static bool link_radv_enabled(Link *link) { assert(link); @@ -671,8 +655,9 @@ static bool link_radv_enabled(Link *link) { return link->network->router_prefix_delegation; } -int radv_configure(Link *link) { +static int radv_configure(Link *link) { uint16_t router_lifetime; + Link *uplink = NULL; RoutePrefix *q; Prefix *p; int r; @@ -680,9 +665,6 @@ int radv_configure(Link *link) { assert(link); assert(link->network); - if (!link_radv_enabled(link)) - return 0; - if (link->radv) return -EBUSY; @@ -748,6 +730,16 @@ int radv_configure(Link *link) { return r; } + (void) manager_find_uplink(link->manager, AF_INET6, link, &uplink); + + r = radv_set_dns(link, uplink); + if (r < 0) + return log_link_debug_errno(link, r, "Could not set RA DNS: %m"); + + r = radv_set_domains(link, uplink); + if (r < 0) + return log_link_debug_errno(link, r, "Could not set RA Domains: %m"); + return 0; } @@ -779,6 +771,66 @@ int radv_update_mac(Link *link) { return 0; } +static bool radv_is_ready_to_configure(Link *link) { + assert(link); + assert(link->network); + + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return false; + + if (in6_addr_is_null(&link->ipv6ll_address)) + return false; + + return true; +} + +int request_process_radv(Request *req) { + Link *link; + int r; + + assert(req); + assert(req->link); + assert(req->type == REQUEST_TYPE_RADV); + + link = req->link; + + if (!radv_is_ready_to_configure(link)) + return 0; + + r = radv_configure(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure IPv6 Router Advertisement engine: %m"); + + if (link_has_carrier(link)) { + r = sd_radv_start(link->radv); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to start IPv6 Router Advertisement engine: %m"); + } + + log_link_debug(link, "IPv6 Router Advertisement engine is configured%s.", + link_has_carrier(link) ? " and started." : ""); + return 1; +} + +int link_request_radv(Link *link) { + int r; + + assert(link); + + if (!link_radv_enabled(link)) + return 0; + + if (link->radv) + return 0; + + r = link_queue_request(link, REQUEST_TYPE_RADV, NULL, false, NULL, NULL, NULL); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to request IPv6 Router Advertisement engine: %m"); + + log_link_debug(link, "IPv6 Router Advertisement engine is requested."); + return 0; +} + int radv_add_prefix( Link *link, const struct in6_addr *prefix, diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index f6efd326979..a8adb9bce1c 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -14,8 +14,9 @@ #include "conf-parser.h" #include "networkd-util.h" -typedef struct Network Network; typedef struct Link Link; +typedef struct Network Network; +typedef struct Request Request; typedef enum RADVPrefixDelegation { RADV_PREFIX_DELEGATION_NONE = 0, @@ -50,12 +51,13 @@ void network_drop_invalid_prefixes(Network *network); void network_drop_invalid_route_prefixes(Network *network); void network_adjust_radv(Network *network); -int radv_emit_dns(Link *link); -int radv_configure(Link *link); int radv_update_mac(Link *link); int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, uint32_t lifetime_preferred, uint32_t lifetime_valid); +int request_process_radv(Request *req); +int link_request_radv(Link *link); + const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_; RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;