]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: use request queue to configure IPv6 RA engine
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 15 Jun 2021 18:37:57 +0000 (03:37 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 4 Aug 2021 13:19:14 +0000 (22:19 +0900)
src/network/networkd-link.c
src/network/networkd-queue.c
src/network/networkd-queue.h
src/network/networkd-radv.c
src/network/networkd-radv.h

index 3a56f89f0b4b0fd87fdc667e085d06be1b040197..17fb932f81ac1d33fb4378fdfd32092306a063a6 100644 (file)
@@ -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;
 
index bc0012e6d8382efc338f83a1e8fb6a99dfa7bf31..27a16f295173e75acc0eb0bb6c7cc73e7e23f7cc 100644 (file)
@@ -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;
index 1f4b15f087dd2ae09b528203fbf6dc2b9134b92a..85d2be7367d30192d1dba4e18c8ad4dfafe02949 100644 (file)
@@ -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,
index 805d3fff6ccd5224dd722e47fec0635c6f45cc7f..a21f69d6f3bda928c746fd7506a2485a8a928d41 100644 (file)
@@ -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,
index f6efd326979b3d440c2759e8bde2df6b936fa655..a8adb9bce1c538f091fd462947581bb070896a00 100644 (file)
@@ -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_;