network: use request queue to configure routing policy rules

This commit is contained in:
Yu Watanabe
2021-05-12 11:26:06 +09:00
parent 7191a57a0e
commit 0e5ef6beb6
8 changed files with 144 additions and 63 deletions
+6 -3
View 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;
+2 -2
View 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;
+1
View File
@@ -62,6 +62,7 @@ struct Manager {
char* dynamic_hostname;
char* dynamic_timezone;
unsigned routing_policy_rule_remove_messages;
Set *rules;
Set *rules_foreign;
+6
View 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;
}
+7 -1
View 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;
-4
View 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)
+118 -49
View 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:
+4 -4
View 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);