network: drop unnecessary routing policy rules

networkd already drop foreign address, routes, and nexthops on startup,
except those created by kernel. However, previously, routing policy
rules were not. The logic of serialization/deserialization of rules only
works for rules created by previous invocation of networkd, and does not
work for one created by other tools like `ip rule`.

This makes networkd drop foreign routing policy rules except created by
kernel on startup. Also, remove rules created by networkd when the
corresponding links are dropped or networkd is stopping.
This commit is contained in:
Yu Watanabe 2020-10-28 20:27:23 +09:00
parent e737dce544
commit 0b81225e57
3 changed files with 68 additions and 19 deletions

View File

@ -1973,37 +1973,51 @@ static int link_enter_join_netdev(Link *link) {
}
static int link_drop_foreign_config(Link *link) {
int r;
int k, r;
assert(link);
assert(link->manager);
r = link_drop_foreign_addresses(link);
if (r < 0)
return r;
r = link_drop_foreign_neighbors(link);
if (r < 0)
return r;
k = link_drop_foreign_neighbors(link);
if (k < 0 && r >= 0)
r = k;
return link_drop_foreign_routes(link);
k = link_drop_foreign_routes(link);
if (k < 0 && r >= 0)
r = k;
k = manager_drop_foreign_routing_policy_rules(link->manager);
if (k < 0 && r >= 0)
r = k;
return r;
}
static int link_drop_config(Link *link) {
int r;
int k, r;
assert(link);
assert(link->manager);
r = link_drop_addresses(link);
if (r < 0)
return r;
r = link_drop_neighbors(link);
if (r < 0)
return r;
k = link_drop_neighbors(link);
if (k < 0 && r >= 0)
r = k;
r = link_drop_routes(link);
if (r < 0)
return r;
k = link_drop_routes(link);
if (k < 0 && r >= 0)
r = k;
k = manager_drop_routing_policy_rules(link->manager, link);
if (k < 0 && r >= 0)
r = k;
ndisc_flush(link);
return 0;
return r;
}
int link_configure(Link *link) {

View File

@ -640,7 +640,7 @@ static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link) {
return 0;
}
static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule *rule) {
static bool links_have_routing_policy_rule(const Manager *m, const RoutingPolicyRule *rule, const Link *except) {
Link *link;
assert(m);
@ -649,6 +649,9 @@ static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule
HASHMAP_FOREACH(link, m->links) {
RoutingPolicyRule *link_rule;
if (link == except)
continue;
if (!link->network)
continue;
@ -660,6 +663,31 @@ static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule
return false;
}
int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except) {
RoutingPolicyRule *rule;
int k, r = 0;
Set *rules;
assert(m);
rules = foreign ? m->rules_foreign : m->rules;
SET_FOREACH(rule, rules) {
/* Do not touch rules managed by kernel. */
if (rule->protocol == RTPROT_KERNEL)
continue;
/* The rule will be configured later, or already configured by a link. */
if (links_have_routing_policy_rule(m, rule, except))
continue;
k = routing_policy_rule_remove(rule, m);
if (k < 0 && r >= 0)
r = k;
}
return r;
}
static void routing_policy_rule_purge(Manager *m) {
RoutingPolicyRule *rule;
int r;
@ -673,7 +701,7 @@ static void routing_policy_rule_purge(Manager *m) {
if (!existing)
continue; /* Saved rule does not exist anymore. */
if (manager_links_have_routing_policy_rule(m, existing))
if (links_have_routing_policy_rule(m, existing, NULL))
continue; /* Existing links have the saved rule. */
/* Existing links do not have the saved rule. Let's drop the rule now, and re-configure it

View File

@ -58,6 +58,13 @@ void network_drop_invalid_routing_policy_rules(Network *network);
int link_set_routing_policy_rules(Link *link);
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);
static inline int manager_drop_foreign_routing_policy_rules(Manager *m) {
return manager_drop_routing_policy_rules_internal(m, true, NULL);
}
static inline int manager_drop_routing_policy_rules(Manager *m, const Link *except) {
return manager_drop_routing_policy_rules_internal(m, false, except);
}
int routing_policy_serialize_rules(Set *rules, FILE *f);
int routing_policy_load_rules(const char *state_file, Set **rules);