diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 7675f266e5..56ae6939a3 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; - 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) { diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 6ad22bd5c8..3f6469442e 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 ded312b73e..7b7dd43987 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);