diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 98c629f161..73dcf67a38 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -58,7 +58,11 @@ static void request_hash_func(const Request *req, struct siphash *state) { siphash24_compress_typesafe(req->type, state); - if (!IN_SET(req->type, REQUEST_TYPE_NEXTHOP, REQUEST_TYPE_ROUTE)) { + if (!IN_SET(req->type, + REQUEST_TYPE_NEXTHOP, + REQUEST_TYPE_ROUTE, + REQUEST_TYPE_ROUTING_POLICY_RULE)) { + siphash24_compress_boolean(req->link, state); if (req->link) siphash24_compress_typesafe(req->link->ifindex, state); @@ -81,7 +85,11 @@ static int request_compare_func(const struct Request *a, const struct Request *b if (r != 0) return r; - if (!IN_SET(a->type, REQUEST_TYPE_NEXTHOP, REQUEST_TYPE_ROUTE)) { + if (!IN_SET(a->type, + REQUEST_TYPE_NEXTHOP, + REQUEST_TYPE_ROUTE, + REQUEST_TYPE_ROUTING_POLICY_RULE)) { + r = CMP(!!a->link, !!b->link); if (r != 0) return r; diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 2c3e56b390..95261fc258 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -378,6 +378,47 @@ static int routing_policy_rule_get(Manager *m, const RoutingPolicyRule *in, int return -ENOENT; } +static int routing_policy_rule_get_request(Manager *m, const RoutingPolicyRule *in, int family, Request **ret) { + Request *req; + + assert(m); + assert(in); + assert(in->family == AF_UNSPEC || in->family == family); + assert(IN_SET(family, AF_INET, AF_INET6)); + + if (in->priority_set && in->family != AF_UNSPEC) { + req = ordered_set_get( + m->request_queue, + &(Request) { + .type = REQUEST_TYPE_ROUTING_POLICY_RULE, + .userdata = (void*) in, + .hash_func = (hash_func_t) routing_policy_rule_hash_func, + .compare_func = (compare_func_t) routing_policy_rule_compare_func, + }); + if (!req) + return -ENOENT; + + if (ret) + *ret = req; + return 0; + } + + ORDERED_SET_FOREACH(req, m->request_queue) { + + if (req->type != REQUEST_TYPE_ROUTING_POLICY_RULE) + continue; + + RoutingPolicyRule *rule = ASSERT_PTR(req->userdata); + if (routing_policy_rule_equal(in, rule, family, rule->priority)) { + if (ret) + *ret = req; + return 0; + } + } + + return -ENOENT; +} + static int routing_policy_rule_attach(Manager *m, RoutingPolicyRule *rule) { int r; @@ -801,6 +842,9 @@ static int link_request_routing_policy_rule(Link *link, const RoutingPolicyRule assert(rule->family == AF_UNSPEC || rule->family == family); assert(IN_SET(family, AF_INET, AF_INET6)); + if (routing_policy_rule_get_request(link->manager, rule, family, NULL) >= 0) + return 0; /* already requested, skipping. */ + if (routing_policy_rule_get(link->manager, rule, family, &existing) < 0) { _cleanup_(routing_policy_rule_unrefp) RoutingPolicyRule *tmp = NULL;