networkd-don-t-remove-route.patch 4.05 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
From 51e1e204251bfa3e6c7e53b98039510dfe29b769 Mon Sep 17 00:00:00 2001
From: Tobias Jungel <tobias.jungel@bisdn.de>
Date: Tue, 6 Nov 2018 13:28:12 +0100
Subject: 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.

Origin: upstream, https://github.com/systemd/systemd/commit/7ecf0c3e1795c08f3089752d7224fe097be4ea8e
Bug-Ubuntu: https://bugs.launchpad.net/bugs/1812760
Last-Update: 2019-01-23
---
 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 1639f7ebf19c..cae7519efe2c 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2535,6 +2535,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;
@@ -2562,9 +2578,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 70dca5219bae..0157979f40e9 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -227,6 +227,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 6db9d592ea53..0f54bd98fee8 100644
--- a/src/network/networkd-route.h
+++ b/src/network/networkd-route.h
@@ -69,6 +69,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);
 
-- 
2.17.1