From 727235006a7e8904f8493d32376cffa6969c5fa9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 20 Aug 2024 06:19:46 +0900 Subject: [PATCH] network/routing-policy-rule: remove rules that have conflicting flags The kernel does not distinguish rules with different flags in rule_exists(), but the flags of an existing rule cannot be updated. Let's remove rules that have conflicting flags, and configure new rules later with requested flags. --- src/network/networkd-routing-policy-rule.c | 48 +++++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 5ce384f872..460e621b2b 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -350,6 +350,20 @@ static bool routing_policy_rule_equal(const RoutingPolicyRule *a, const RoutingP return routing_policy_rule_compare_func_full(a, b, /* all = */ false) == 0; } +static bool routing_policy_rule_can_update(const RoutingPolicyRule *existing, const RoutingPolicyRule *requesting, int family) { + assert(existing); + assert(requesting); + + if (!routing_policy_rule_equal(existing, requesting, family, existing->priority)) + return false; + + /* These flags cannot be updated. */ + if ((existing->flags ^ requesting->flags) & (FIB_RULE_PERMANENT|FIB_RULE_INVERT)) + return false; + + return true; +} + static int routing_policy_rule_get(Manager *m, const RoutingPolicyRule *in, int family, RoutingPolicyRule **ret) { RoutingPolicyRule *rule; @@ -742,6 +756,23 @@ static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, Re return request_call_netlink_async(link->manager->rtnl, m, req); } +static void manager_unmark_routing_policy_rule(Manager *m, const RoutingPolicyRule *rule, int family) { + RoutingPolicyRule *existing; + + assert(m); + assert(rule); + assert(rule->family == AF_UNSPEC || rule->family == family); + assert(IN_SET(family, AF_INET, AF_INET6)); + + if (routing_policy_rule_get(m, rule, family, &existing) < 0) + return; + + if (!routing_policy_rule_can_update(existing, rule, rule->family)) + return; + + routing_policy_rule_unmark(existing); +} + static void manager_mark_routing_policy_rules(Manager *m, bool foreign, const Link *except) { RoutingPolicyRule *rule; Link *link; @@ -774,17 +805,12 @@ static void manager_mark_routing_policy_rules(Manager *m, bool foreign, const Li continue; HASHMAP_FOREACH(rule, link->network->rules_by_section) { - RoutingPolicyRule *existing; - - if (IN_SET(rule->family, AF_INET, AF_INET6)) { - if (routing_policy_rule_get(m, rule, rule->family, &existing) >= 0) - routing_policy_rule_unmark(existing); - } else { - if (routing_policy_rule_get(m, rule, AF_INET, &existing) >= 0) - routing_policy_rule_unmark(existing); - - if (routing_policy_rule_get(m, rule, AF_INET6, &existing) >= 0) - routing_policy_rule_unmark(existing); + if (IN_SET(rule->family, AF_INET, AF_INET6)) + manager_unmark_routing_policy_rule(m, rule, rule->family); + else { + assert(rule->address_family == ADDRESS_FAMILY_YES); + manager_unmark_routing_policy_rule(m, rule, AF_INET); + manager_unmark_routing_policy_rule(m, rule, AF_INET6); } } } -- 2.25.1