diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 7cafe1f6a3..0c43965ea6 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -222,20 +222,33 @@ static int ndisc_request_route(Route *route, Link *link) { /* Note, here do not call route_remove_and_cancel() with 'route' directly, otherwise * existing route(s) may be removed needlessly. */ - if (route_get(link->manager, route, &existing) >= 0) { - /* Found an existing route that may conflict with this route. */ + /* First, check if a conflicting route is already requested. If there is an existing route, + * and also an existing pending request, then the source may be updated by the request. So, + * we first need to check the source of the requested route. */ + if (route_get_request(link->manager, route, &req) >= 0) { + existing = ASSERT_PTR(req->userdata); if (!route_can_update(existing, route)) { - log_link_debug(link, "Found an existing route that conflicts with new route based on a received RA, removing."); + if (existing->source == NETWORK_CONFIG_SOURCE_STATIC) { + log_link_debug(link, "Found a pending route request that conflicts with new request based on a received RA, ignoring request."); + return 0; + } + + log_link_debug(link, "Found a pending route request that conflicts with new request based on a received RA, cancelling."); r = route_remove_and_cancel(existing, link->manager); if (r < 0) return r; } } - if (route_get_request(link->manager, route, &req) >= 0) { - existing = ASSERT_PTR(req->userdata); + /* Then, check if a conflicting route exists. */ + if (route_get(link->manager, route, &existing) >= 0) { if (!route_can_update(existing, route)) { - log_link_debug(link, "Found a pending route request that conflicts with new request based on a received RA, cancelling."); + if (existing->source == NETWORK_CONFIG_SOURCE_STATIC) { + log_link_debug(link, "Found an existing route that conflicts with new route based on a received RA, ignoring request."); + return 0; + } + + log_link_debug(link, "Found an existing route that conflicts with new route based on a received RA, removing."); r = route_remove_and_cancel(existing, link->manager); if (r < 0) return r;