From 7ecf0c3e1795c08f3089752d7224fe097be4ea8e Mon Sep 17 00:00:00 2001 From: Tobias Jungel Date: Tue, 6 Nov 2018 13:28:12 +0100 Subject: [PATCH] networkd: don't remove route In case networkd is restarted this prevents a removal of an already existing route that would be configured using networkd. With the proposed changes the route will be kept on the interface without removing. This happens only on physical hosts or VMs since networkd handles interface configuration slightly different in containers. --- src/network/networkd-link.c | 28 +++++++++++++++++++++++++--- src/network/networkd-route.c | 10 ++++++++++ src/network/networkd-route.h | 1 + 3 files changed, 36 insertions(+), 3 deletions(-) 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);