From: Yu Watanabe Date: Wed, 28 Oct 2020 11:27:23 +0000 (+0900) Subject: network: drop unnecessary routing policy rules X-Git-Tag: v248-rc1~446^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0b81225e5791f660506f7db0ab88078cf296b771;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 7675f266e5e..56ae6939a3e 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -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; + + k = link_drop_foreign_routes(link); + if (k < 0 && r >= 0) + r = k; - return link_drop_foreign_routes(link); + 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) { diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 6ad22bd5c85..3f6469442e3 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -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 diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index ded312b73e7..7b7dd439872 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -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);