diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 6da881c1d3..b112b13eed 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2634,6 +2634,22 @@ static bool link_is_static_address_configured(Link *link, Address *address) { return false; } +static bool link_is_static_route_configured(Link *link, Route *route) { + Route *net_route; + + assert(link); + assert(route); + + if (!link->network) + return false; + + LIST_FOREACH(routes, net_route, link->network->static_routes) + if (route_equal(net_route, route)) + return true; + + return false; +} + static int link_drop_foreign_config(Link *link) { Address *address; Route *route; @@ -2661,9 +2677,15 @@ static int link_drop_foreign_config(Link *link) { if (route->protocol == RTPROT_KERNEL) continue; - r = route_remove(route, link, link_route_remove_handler); - if (r < 0) - return r; + if (link_is_static_route_configured(link, route)) { + r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL); + if (r < 0) + return r; + } else { + r = route_remove(route, link, link_route_remove_handler); + if (r < 0) + return r; + } } return 0; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 529d942f15..e8cde66bef 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -201,6 +201,16 @@ static const struct hash_ops route_hash_ops = { .compare = route_compare_func }; +bool route_equal(Route *r1, Route *r2) { + if (r1 == r2) + return true; + + if (!r1 || !r2) + return false; + + return route_compare_func(r1, r2) == 0; +} + int route_get(Link *link, int family, const union in_addr_union *dst, diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 7283f48304..fe000d61b8 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -52,6 +52,7 @@ int route_get(Link *link, int family, const union in_addr_union *dst, unsigned c int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret); int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret); void route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol, unsigned char type); +bool route_equal(Route *r1, Route *r2); int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);