diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-05-07 15:57:13 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-05-12 11:26:06 +0900 |
commit | 0e5ef6beb6d6f650a4fc44d3127c3de03e1f44b0 (patch) | |
tree | 1381f86d3e715cb1cf8be7c3f84f45789e0d36a6 /src | |
parent | 7191a57a0e25f4d2ee7e44c5d91cb432b3be8fbc (diff) | |
download | systemd-0e5ef6beb6d6f650a4fc44d3127c3de03e1f44b0.tar.gz |
network: use request queue to configure routing policy rules
Diffstat (limited to 'src')
-rw-r--r-- | src/network/networkd-link.c | 9 | ||||
-rw-r--r-- | src/network/networkd-link.h | 4 | ||||
-rw-r--r-- | src/network/networkd-manager.h | 1 | ||||
-rw-r--r-- | src/network/networkd-queue.c | 6 | ||||
-rw-r--r-- | src/network/networkd-queue.h | 8 | ||||
-rw-r--r-- | src/network/networkd-route.c | 4 | ||||
-rw-r--r-- | src/network/networkd-routing-policy-rule.c | 167 | ||||
-rw-r--r-- | src/network/networkd-routing-policy-rule.h | 8 |
8 files changed, 144 insertions, 63 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 031a6692c2..c41baec215 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -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; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 38659e16a9..9fd95abc3f 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -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; diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 26e8802871..0d677dc05d 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -62,6 +62,7 @@ struct Manager { char* dynamic_hostname; char* dynamic_timezone; + unsigned routing_policy_rule_remove_messages; Set *rules; Set *rules_foreign; diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 24bb2c845d..e06a16bbb4 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -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; } diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 4558ae548f..e666d44678 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -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; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 07a70db536..f18bd12ccb 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -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) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 6a0e21d9f0..b44ee8b627 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -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: diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index dbda8c51b0..69b0535659 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -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); |