network: use request queue to configure routing policy rules
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -62,6 +62,7 @@ struct Manager {
|
||||
char* dynamic_hostname;
|
||||
char* dynamic_timezone;
|
||||
|
||||
unsigned routing_policy_rule_remove_messages;
|
||||
Set *rules;
|
||||
Set *rules_foreign;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,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);
|
||||
|
||||
Reference in New Issue
Block a user