summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-05-07 15:57:13 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-05-12 11:26:06 +0900
commit0e5ef6beb6d6f650a4fc44d3127c3de03e1f44b0 (patch)
tree1381f86d3e715cb1cf8be7c3f84f45789e0d36a6 /src
parent7191a57a0e25f4d2ee7e44c5d91cb432b3be8fbc (diff)
downloadsystemd-0e5ef6beb6d6f650a4fc44d3127c3de03e1f44b0.tar.gz
network: use request queue to configure routing policy rules
Diffstat (limited to 'src')
-rw-r--r--src/network/networkd-link.c9
-rw-r--r--src/network/networkd-link.h4
-rw-r--r--src/network/networkd-manager.h1
-rw-r--r--src/network/networkd-queue.c6
-rw-r--r--src/network/networkd-queue.h8
-rw-r--r--src/network/networkd-route.c4
-rw-r--r--src/network/networkd-routing-policy-rule.c167
-rw-r--r--src/network/networkd-routing-policy-rule.h8
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);