From 6c252588dffc2b79dbb96e84a789cdb7e8e49b8c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 3 Dec 2020 18:44:37 +0900 Subject: [PATCH 1/5] network: introduce route_type_is_reject() helper --- src/network/networkd-route.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index f477db1902..5018fe480b 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -575,6 +575,12 @@ static int route_add(Manager *manager, Link *link, const Route *in, const Multip return 0; } +static bool route_type_is_reject(const Route *route) { + assert(route); + + return IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW); +} + static int route_set_netlink_message(const Route *route, sd_netlink_message *req, Link *link) { unsigned flags; int r; @@ -660,7 +666,7 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *req if (r < 0) return log_link_error_errno(link, r, "Could not set route type: %m"); - if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) { + if (!route_type_is_reject(route)) { assert(link); /* Those routes must be attached to a specific link */ r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex); @@ -927,7 +933,7 @@ static int route_add_and_setup_timer(Link *link, const Route *route, const Multi assert(link); assert(route); - if (IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) + if (route_type_is_reject(route)) r = route_add(link->manager, NULL, route, NULL, &nr); else if (!m || m->ifindex == 0 || m->ifindex == link->ifindex) r = route_add(NULL, link, route, m, &nr); From 575f14eef010101c60e9d4d970e542c815be1994 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 3 Dec 2020 18:51:53 +0900 Subject: [PATCH 2/5] network: make IPv6 routes with reject type managed by Manager --- src/network/networkd-route.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 5018fe480b..280c1ee92c 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1582,6 +1582,12 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma } } + /* IPv6 routes with reject type are always assigned to the loopback interface. See kernel's + * fib6_nh_init() in net/ipv6/route.c. However, we'd like to manage them by Manager. Hence, set + * link to NULL here. */ + if (route_type_is_reject(tmp)) + link = NULL; + if (ordered_set_isempty(multipath_routes)) (void) process_route_one(m, link, type, tmp, NULL); else { From d9d6a10bce81681042225cef689ab6078f51b859 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 3 Dec 2020 19:00:56 +0900 Subject: [PATCH 3/5] network: set protocol to route assigned through DHCP6 or DHCP6-PD --- src/network/networkd-dhcp6.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 95025acbfd..6592cdbfe0 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -279,6 +279,7 @@ static int dhcp6_set_pd_route(Link *link, const union in_addr_union *prefix, con route->family = AF_INET6; route->dst = *prefix; route->dst_prefixlen = 64; + route->protocol = RTPROT_DHCP; r = route_configure(route, link, dhcp6_pd_route_handler, &ret); if (r < 0) @@ -826,6 +827,7 @@ static int dhcp6_set_unreachable_route(Link *link, const union in_addr_union *ad route->dst_prefixlen = prefixlen; route->table = link_get_dhcp_route_table(link); route->type = RTN_UNREACHABLE; + route->protocol = RTPROT_DHCP; r = route_configure(route, link, dhcp6_route_handler, &ret); if (r < 0) From 37b9c79e5d234ba5c0ce98a2a8cc8d18dd9bd572 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 3 Dec 2020 14:16:41 +0900 Subject: [PATCH 4/5] test-network: sleep 1s after reloading configs As interfaces will be reconfigured asynchronously after `networkctl reload`. So, right after `networkctl reload` is finished, interfaces may be still in 'configured' state with the old .network files. --- test/test-network/systemd-networkd-tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 3c288fc6ee..f759840d23 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -2242,6 +2242,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): copy_unit_to_networkd_unit_path('25-address-static.network') check_output(*networkctl_cmd, 'reload', env=env) + time.sleep(1) self.wait_online(['dummy98:routable']) # check all routes managed by Manager are removed @@ -2262,6 +2263,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): remove_unit_from_networkd_path(['25-address-static.network']) check_output(*networkctl_cmd, 'reload', env=env) + time.sleep(1) self.wait_online(['dummy98:routable']) # check all routes managed by Manager are reconfigured From 452d86a53246806feb92a4863e02668f079edafc Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 3 Dec 2020 19:09:55 +0900 Subject: [PATCH 5/5] test-network: add tests for IPv6 routes with reject type --- .../test-network/conf/25-route-static.network | 12 ++++ test/test-network/systemd-networkd-tests.py | 60 +++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/test/test-network/conf/25-route-static.network b/test/test-network/conf/25-route-static.network index bb485eb6b0..ea47a0c03b 100644 --- a/test/test-network/conf/25-route-static.network +++ b/test/test-network/conf/25-route-static.network @@ -48,6 +48,18 @@ Destination=202.54.1.3 Type=prohibit Destination=202.54.1.4 +[Route] +Type=blackhole +Destination=2001:1234:5678::2 + +[Route] +Type=unreachable +Destination=2001:1234:5678::3 + +[Route] +Type=prohibit +Destination=2001:1234:5678::4 + [Route] Type=local Destination=149.10.123.1 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index f759840d23..0a33ce7779 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -2216,6 +2216,21 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): print(output) self.assertRegex(output, 'prohibit 202.54.1.4 proto static') + print('### ip -6 route show type blackhole') + output = check_output('ip -6 route show type blackhole') + print(output) + self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output) + + print('### ip -6 route show type unreachable') + output = check_output('ip -6 route show type unreachable') + print(output) + self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output) + + print('### ip -6 route show type prohibit') + output = check_output('ip -6 route show type prohibit') + print(output) + self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output) + print('### ip route show 192.168.10.1') output = check_output('ip route show 192.168.10.1') print(output) @@ -2261,6 +2276,21 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): print(output) self.assertEqual(output, '') + print('### ip -6 route show type blackhole') + output = check_output('ip -6 route show type blackhole') + print(output) + self.assertEqual(output, '') + + print('### ip -6 route show type unreachable') + output = check_output('ip -6 route show type unreachable') + print(output) + self.assertEqual(output, '') + + print('### ip -6 route show type prohibit') + output = check_output('ip -6 route show type prohibit') + print(output) + self.assertEqual(output, '') + remove_unit_from_networkd_path(['25-address-static.network']) check_output(*networkctl_cmd, 'reload', env=env) time.sleep(1) @@ -2282,6 +2312,21 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): print(output) self.assertRegex(output, 'prohibit 202.54.1.4 proto static') + print('### ip -6 route show type blackhole') + output = check_output('ip -6 route show type blackhole') + print(output) + self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output) + + print('### ip -6 route show type unreachable') + output = check_output('ip -6 route show type unreachable') + print(output) + self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output) + + print('### ip -6 route show type prohibit') + output = check_output('ip -6 route show type prohibit') + print(output) + self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output) + rc = call("ip link del dummy98") self.assertEqual(rc, 0) time.sleep(2) @@ -2302,6 +2347,21 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): print(output) self.assertEqual(output, '') + print('### ip -6 route show type blackhole') + output = check_output('ip -6 route show type blackhole') + print(output) + self.assertEqual(output, '') + + print('### ip -6 route show type unreachable') + output = check_output('ip -6 route show type unreachable') + print(output) + self.assertEqual(output, '') + + print('### ip -6 route show type prohibit') + output = check_output('ip -6 route show type prohibit') + print(output) + self.assertEqual(output, '') + @expectedFailureIfRTA_VIAIsNotSupported() def test_route_via_ipv6(self): copy_unit_to_networkd_unit_path('25-route-via-ipv6.network', '12-dummy.netdev')