]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: use request queue to configure routing policy rules
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 7 May 2021 06:57:13 +0000 (15:57 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 12 May 2021 02:26:06 +0000 (11:26 +0900)
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-manager.h
src/network/networkd-queue.c
src/network/networkd-queue.h
src/network/networkd-route.c
src/network/networkd-routing-policy-rule.c
src/network/networkd-routing-policy-rule.h

index 031a6692c2ecc41aac53dc548730618d7ad6ff3c..c41baec21546844c5e418e1a5e767ee97c1648da 100644 (file)
@@ -813,7 +813,7 @@ void link_check_ready(Link *link) {
         if (!link->static_nexthops_configured)
                 return (void) log_link_debug(link, "%s(): static nexthops are not configured.", __func__);
 
-        if (!link->routing_policy_rules_configured)
+        if (!link->static_routing_policy_rules_configured)
                 return (void) log_link_debug(link, "%s(): static routing policy rules are not configured.", __func__);
 
         if (!link->tc_configured)
@@ -884,7 +884,6 @@ static int link_set_static_configs(Link *link) {
         link->neighbors_configured = false;
         link->static_routes_configured = false;
         link->static_nexthops_configured = false;
-        link->routing_policy_rules_configured = false;
 
         r = link_set_bridge_fdb(link);
         if (r < 0)
@@ -894,6 +893,10 @@ static int link_set_static_configs(Link *link) {
         if (r < 0)
                 return r;
 
+        r = link_set_address_labels(link);
+        if (r < 0)
+                return r;
+
         r = link_set_neighbors(link);
         if (r < 0)
                 return r;
@@ -902,7 +905,7 @@ static int link_set_static_configs(Link *link) {
         if (r < 0)
                 return r;
 
-        r = link_set_address_labels(link);
+        r = link_request_static_routing_policy_rules(link);
         if (r < 0)
                 return r;
 
index 38659e16a959702762e706c33973b0b737b5d5f2..9fd95abc3f072f0911f8a46e6a8a50c9fe163027 100644 (file)
@@ -84,7 +84,7 @@ typedef struct Link {
         unsigned neighbor_messages;
         unsigned route_messages;
         unsigned nexthop_messages;
-        unsigned routing_policy_rule_messages;
+        unsigned static_routing_policy_rule_messages;
         unsigned tc_messages;
         unsigned sr_iov_messages;
         unsigned enslaving;
@@ -124,7 +124,7 @@ typedef struct Link {
         bool neighbors_configured:1;
         bool static_routes_configured:1;
         bool static_nexthops_configured:1;
-        bool routing_policy_rules_configured:1;
+        bool static_routing_policy_rules_configured:1;
         bool tc_configured:1;
         bool sr_iov_configured:1;
         bool setting_mtu:1;
index 26e88028719f482ea5e22f1d4863f9e5cdd8b7cf..0d677dc05d808c34b97427d504bf74d8479c6dc4 100644 (file)
@@ -62,6 +62,7 @@ struct Manager {
         char* dynamic_hostname;
         char* dynamic_timezone;
 
+        unsigned routing_policy_rule_remove_messages;
         Set *rules;
         Set *rules_foreign;
 
index 24bb2c845d0522c5cea6f109cd8e54683814413b..e06a16bbb48037f556ea9df7705243beee99a33f 100644 (file)
@@ -10,6 +10,9 @@
 
 static void request_free_object(RequestType type, void *object) {
         switch(type) {
+        case REQUEST_TYPE_ROUTING_POLICY_RULE:
+                routing_policy_rule_free(object);
+                break;
         default:
                 assert_not_reached("invalid request type.");
         }
@@ -101,6 +104,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
 
                 ORDERED_SET_FOREACH(req, manager->request_queue) {
                         switch(req->type) {
+                        case REQUEST_TYPE_ROUTING_POLICY_RULE:
+                                r = request_process_routing_policy_rule(req);
+                                break;
                         default:
                                 return -EINVAL;
                         }
index 4558ae548f33e92459b84e03c9f7c0b2d93a6b31..e666d446786d68d298a1a2fdcfc34974546302ab 100644 (file)
@@ -5,12 +5,15 @@
 
 #include "networkd-link.h"
 
+typedef struct RoutingPolicyRule RoutingPolicyRule;
+
 typedef struct Request Request;
 
 typedef int (*request_after_configure_handler_t)(Request*, void*);
 typedef void (*request_on_free_handler_t)(Request*);
 
 typedef enum RequestType {
+        REQUEST_TYPE_ROUTING_POLICY_RULE,
         _REQUEST_TYPE_MAX,
         _REQUEST_TYPE_INVALID = -EINVAL,
 } RequestType;
@@ -19,7 +22,10 @@ typedef struct Request {
         Link *link;
         RequestType type;
         bool consume_object;
-        void *object;
+        union {
+                RoutingPolicyRule *rule;
+                void *object;
+        };
         void *userdata;
         unsigned *message_counter;
         link_netlink_message_handler_t netlink_handler;
index 07a70db5365f9f8c579b677b849d288942b42f6d..f18bd12ccbb048c2395e7b4e2c0297ed7bbb7fe8 100644 (file)
@@ -1563,10 +1563,6 @@ int link_set_routes(Link *link) {
                 return 0;
         }
 
-        r = link_set_routing_policy_rules(link);
-        if (r < 0)
-                return r;
-
         /* First, add the routes that enable us to talk to gateways. */
         r = link_set_routes_internal(link, false);
         if (r < 0)
index 6a0e21d9f0a7e17fa59a04987e4ffe276af64fb4..b44ee8b627bb1441b0c6636b28e238e42ad22c71 100644 (file)
@@ -12,6 +12,8 @@
 #include "ip-protocol-list.h"
 #include "netlink-util.h"
 #include "networkd-manager.h"
+#include "networkd-queue.h"
+#include "networkd-route.h"
 #include "networkd-routing-policy-rule.h"
 #include "networkd-util.h"
 #include "parse-util.h"
@@ -313,7 +315,7 @@ static int routing_policy_rule_get(Manager *m, const RoutingPolicyRule *rule, Ro
         return -ENOENT;
 }
 
-static int routing_policy_rule_add(Manager *m, const RoutingPolicyRule *in, int family, RoutingPolicyRule **ret) {
+static int routing_policy_rule_add(Manager *m, const RoutingPolicyRule *in, RoutingPolicyRule **ret) {
         _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
         RoutingPolicyRule *existing;
         bool is_new = false;
@@ -321,15 +323,12 @@ static int routing_policy_rule_add(Manager *m, const RoutingPolicyRule *in, int
 
         assert(m);
         assert(in);
-        assert(IN_SET(family, AF_INET, AF_INET6));
-        assert(in->family == AF_UNSPEC || in->family == family);
+        assert(IN_SET(in->family, AF_INET, AF_INET6));
 
         r = routing_policy_rule_dup(in, &rule);
         if (r < 0)
                 return r;
 
-        rule->family = family;
-
         r = routing_policy_rule_get(m, rule, &existing);
         if (r == -ENOENT) {
                 /* Rule does not exist, use a new one. */
@@ -376,11 +375,11 @@ static int routing_policy_rule_consume_foreign(Manager *m, RoutingPolicyRule *ru
         return 1;
 }
 
-static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, int family, const char *str, const Link *link, const Manager *m) {
+static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, const char *str, const Link *link, const Manager *m) {
         _cleanup_free_ char *from = NULL, *to = NULL, *table = NULL;
 
         assert(rule);
-        assert(IN_SET(family, AF_INET, AF_INET6));
+        assert(IN_SET(rule->family, AF_INET, AF_INET6));
         assert(str);
         assert(m);
 
@@ -389,8 +388,8 @@ static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, int fam
         if (!DEBUG_LOGGING)
                 return;
 
-        (void) in_addr_prefix_to_string(family, &rule->from, rule->from_prefixlen, &from);
-        (void) in_addr_prefix_to_string(family, &rule->to, rule->to_prefixlen, &to);
+        (void) in_addr_prefix_to_string(rule->family, &rule->from, rule->from_prefixlen, &from);
+        (void) in_addr_prefix_to_string(rule->family, &rule->to, rule->to_prefixlen, &to);
         (void) manager_get_route_table_to_string(m, rule->table, &table);
 
         log_link_debug(link,
@@ -520,10 +519,14 @@ static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule *rule
         return 0;
 }
 
-static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
+static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Manager *manager) {
         int r;
 
         assert(m);
+        assert(manager);
+        assert(manager->routing_policy_rule_remove_messages > 0);
+
+        manager->routing_policy_rule_remove_messages--;
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0)
@@ -541,7 +544,7 @@ static int routing_policy_rule_remove(const RoutingPolicyRule *rule, Manager *ma
         assert(manager->rtnl);
         assert(IN_SET(rule->family, AF_INET, AF_INET6));
 
-        log_routing_policy_rule_debug(rule, rule->family, "Removing", NULL, manager);
+        log_routing_policy_rule_debug(rule, "Removing", NULL, manager);
 
         r = sd_rtnl_message_new_routing_policy_rule(manager->rtnl, &m, RTM_DELRULE, rule->family);
         if (r < 0)
@@ -551,18 +554,19 @@ static int routing_policy_rule_remove(const RoutingPolicyRule *rule, Manager *ma
         if (r < 0)
                 return r;
 
-        r = sd_netlink_call_async(manager->rtnl, NULL, m,
-                                  routing_policy_rule_remove_handler,
-                                  NULL, NULL, 0, __func__);
+        r = netlink_call_async(manager->rtnl, NULL, m,
+                               routing_policy_rule_remove_handler,
+                               NULL, manager);
         if (r < 0)
                 return log_error_errno(r, "Could not send rtnetlink message: %m");
 
+        manager->routing_policy_rule_remove_messages++;
+
         return 0;
 }
 
 static int routing_policy_rule_configure(
                 const RoutingPolicyRule *rule,
-                int family,
                 Link *link,
                 link_netlink_message_handler_t callback,
                 RoutingPolicyRule **ret) {
@@ -571,16 +575,16 @@ static int routing_policy_rule_configure(
         int r;
 
         assert(rule);
-        assert(IN_SET(family, AF_INET, AF_INET6));
+        assert(IN_SET(rule->family, AF_INET, AF_INET6));
         assert(link);
         assert(link->ifindex > 0);
         assert(link->manager);
         assert(link->manager->rtnl);
         assert(callback);
 
-        log_routing_policy_rule_debug(rule, family, "Configuring", link, link->manager);
+        log_routing_policy_rule_debug(rule, "Configuring", link, link->manager);
 
-        r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, family);
+        r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, rule->family);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not allocate RTM_NEWRULE message: %m");
 
@@ -588,17 +592,16 @@ static int routing_policy_rule_configure(
         if (r < 0)
                 return r;
 
+        r = routing_policy_rule_add(link->manager, rule, ret);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not add rule: %m");
+
         r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
                                link_netlink_destroy_callback, link);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
 
         link_ref(link);
-        link->routing_policy_rule_messages++;
-
-        r = routing_policy_rule_add(link->manager, rule, family, ret);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not add rule: %m");
 
         return r;
 }
@@ -680,9 +683,9 @@ static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_net
         assert(m);
         assert(link);
         assert(link->ifname);
-        assert(link->routing_policy_rule_messages > 0);
+        assert(link->static_routing_policy_rule_messages > 0);
 
-        link->routing_policy_rule_messages--;
+        link->static_routing_policy_rule_messages--;
 
         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
                 return 1;
@@ -694,29 +697,71 @@ static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_net
                 return 1;
         }
 
-        if (link->routing_policy_rule_messages == 0) {
+        if (link->static_routing_policy_rule_messages == 0) {
                 log_link_debug(link, "Routing policy rule configured");
-                link->routing_policy_rules_configured = true;
+                link->static_routing_policy_rules_configured = true;
                 link_check_ready(link);
         }
 
         return 1;
 }
 
-static int static_routing_policy_rule_configure(const RoutingPolicyRule *rule, Link *link) {
+static int link_request_routing_policy_rule(
+                Link *link,
+                RoutingPolicyRule *rule,
+                bool consume_object,
+                unsigned *message_counter,
+                link_netlink_message_handler_t netlink_handler,
+                Request **ret) {
+
+        assert(link);
+        assert(link->manager);
+        assert(rule);
+
+        log_routing_policy_rule_debug(rule, "Requesting", link, link->manager);
+        return link_queue_request(link, REQUEST_TYPE_ROUTING_POLICY_RULE, rule, consume_object,
+                                  message_counter, netlink_handler, ret);
+}
+
+static int link_request_static_routing_policy_rule(Link *link, RoutingPolicyRule *rule) {
         int r;
 
         if (IN_SET(rule->family, AF_INET, AF_INET6))
-                return routing_policy_rule_configure(rule, rule->family, link, static_routing_policy_rule_configure_handler, NULL);
+                return link_request_routing_policy_rule(link, rule, false,
+                                                        &link->static_routing_policy_rule_messages,
+                                                        static_routing_policy_rule_configure_handler,
+                                                        NULL);
 
         if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4)) {
-                r = routing_policy_rule_configure(rule, AF_INET, link, static_routing_policy_rule_configure_handler, NULL);
+                _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
+
+                r = routing_policy_rule_dup(rule, &tmp);
+                if (r < 0)
+                        return r;
+
+                tmp->family = AF_INET;
+
+                r = link_request_routing_policy_rule(link, TAKE_PTR(tmp), true,
+                                                     &link->static_routing_policy_rule_messages,
+                                                     static_routing_policy_rule_configure_handler,
+                                                     NULL);
                 if (r < 0)
                         return r;
         }
 
         if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) {
-                r = routing_policy_rule_configure(rule, AF_INET6, link, static_routing_policy_rule_configure_handler, NULL);
+                _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
+
+                r = routing_policy_rule_dup(rule, &tmp);
+                if (r < 0)
+                        return r;
+
+                tmp->family = AF_INET6;
+
+                r = link_request_routing_policy_rule(link, TAKE_PTR(tmp), true,
+                                                     &link->static_routing_policy_rule_messages,
+                                                     static_routing_policy_rule_configure_handler,
+                                                     NULL);
                 if (r < 0)
                         return r;
         }
@@ -724,36 +769,60 @@ static int static_routing_policy_rule_configure(const RoutingPolicyRule *rule, L
         return 0;
 }
 
-int link_set_routing_policy_rules(Link *link) {
+int link_request_static_routing_policy_rules(Link *link) {
         RoutingPolicyRule *rule;
         int r;
 
         assert(link);
         assert(link->network);
 
-        if (link->routing_policy_rule_messages != 0) {
-                log_link_debug(link, "Routing policy rules are configuring.");
-                return 0;
-        }
-
-        link->routing_policy_rules_configured = false;
+        link->static_routing_policy_rules_configured = false;
 
         HASHMAP_FOREACH(rule, link->network->rules_by_section) {
-                r = static_routing_policy_rule_configure(rule, link);
+                r = link_request_static_routing_policy_rule(link, rule);
                 if (r < 0)
-                        return log_link_warning_errno(link, r, "Could not set routing policy rule: %m");
+                        return log_link_warning_errno(link, r, "Could not request routing policy rule: %m");
         }
 
-        if (link->routing_policy_rule_messages == 0)
-                link->routing_policy_rules_configured = true;
-        else {
-                log_link_debug(link, "Setting routing policy rules");
+        if (link->static_routing_policy_rule_messages == 0) {
+                link->static_routing_policy_rules_configured = true;
+                link_check_ready(link);
+        } else {
+                log_link_debug(link, "Requesting routing policy rules");
                 link_set_state(link, LINK_STATE_CONFIGURING);
         }
 
         return 0;
 }
 
+int request_process_routing_policy_rule(Request *req) {
+        RoutingPolicyRule *ret = NULL;  /* avoid false maybe-uninitialized warning */
+        int r;
+
+        assert(req);
+        assert(req->link);
+        assert(req->rule);
+        assert(req->type == REQUEST_TYPE_ROUTING_POLICY_RULE);
+
+        if (!link_is_ready_to_configure(req->link, false))
+                return 0;
+
+        if (req->link->manager->routing_policy_rule_remove_messages > 0)
+                return 0;
+
+        r = routing_policy_rule_configure(req->rule, req->link, req->netlink_handler, &ret);
+        if (r < 0)
+                return r;
+
+        if (req->after_configure) {
+                r = req->after_configure(req, ret);
+                if (r < 0)
+                        return r;
+        }
+
+        return 1;
+}
+
 static const RoutingPolicyRule kernel_rules[] = {
         { .family = AF_INET,  .priority = 0,     .table = RT_TABLE_LOCAL,   .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
         { .family = AF_INET,  .priority = 32766, .table = RT_TABLE_MAIN,    .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
@@ -966,11 +1035,11 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
         switch (type) {
         case RTM_NEWRULE:
                 if (rule)
-                        log_routing_policy_rule_debug(tmp, tmp->family, "Received remembered", NULL, m);
+                        log_routing_policy_rule_debug(tmp, "Received remembered", NULL, m);
                 else if (!m->manage_foreign_routes)
-                        log_routing_policy_rule_debug(tmp, tmp->family, "Ignoring received foreign", NULL, m);
+                        log_routing_policy_rule_debug(tmp, "Ignoring received foreign", NULL, m);
                 else {
-                        log_routing_policy_rule_debug(tmp, tmp->family, "Remembering foreign", NULL, m);
+                        log_routing_policy_rule_debug(tmp, "Remembering foreign", NULL, m);
                         r = routing_policy_rule_consume_foreign(m, TAKE_PTR(tmp));
                         if (r < 0)
                                 log_warning_errno(r, "Could not remember foreign rule, ignoring: %m");
@@ -978,10 +1047,10 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
                 break;
         case RTM_DELRULE:
                 if (rule) {
-                        log_routing_policy_rule_debug(tmp, tmp->family, "Forgetting", NULL, m);
+                        log_routing_policy_rule_debug(tmp, "Forgetting", NULL, m);
                         routing_policy_rule_free(rule);
                 } else
-                        log_routing_policy_rule_debug(tmp, tmp->family, "Kernel removed unknown", NULL, m);
+                        log_routing_policy_rule_debug(tmp, "Kernel removed unknown", NULL, m);
                 break;
 
         default:
index dbda8c51b07dffc6ec1561afef96c01afc69096d..69b053565928d5ccd456516fa680d84afba52459 100644 (file)
@@ -4,16 +4,15 @@
 #include <inttypes.h>
 #include <linux/fib_rules.h>
 #include <stdbool.h>
-#include <stdio.h>
 
 #include "conf-parser.h"
 #include "in-addr-util.h"
 #include "networkd-util.h"
-#include "set.h"
 
-typedef struct Network Network;
 typedef struct Link Link;
 typedef struct Manager Manager;
+typedef struct Network Network;
+typedef struct Request Request;
 
 typedef struct RoutingPolicyRule {
         Manager *manager;
@@ -55,7 +54,8 @@ RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule);
 
 void network_drop_invalid_routing_policy_rules(Network *network);
 
-int link_set_routing_policy_rules(Link *link);
+int link_request_static_routing_policy_rules(Link *link);
+int request_process_routing_policy_rule(Request *req);
 
 int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
 int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except);