diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 3661498f39..ae0fc8403e 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -728,63 +728,6 @@ static void link_enter_configured(Link *link) { link_dirty(link); } -void link_check_ready(Link *link) { - Address *a; - Iterator i; - - assert(link); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return; - - if (!link->network) - return; - - if (!link->addresses_configured) - return; - - if (!link->neighbors_configured) - return; - - if (!link->static_routes_configured) - return; - - if (!link->routing_policy_rules_configured) - return; - - if (link_ipv4ll_enabled(link)) - if (!link->ipv4ll_address || - !link->ipv4ll_route) - return; - - if (!link->network->bridge) { - - if (link_ipv6ll_enabled(link)) - if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) > 0) - return; - - if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) && - !link->dhcp4_configured) || - (link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) && - !link->dhcp6_configured) || - (link_dhcp4_enabled(link) && link_dhcp6_enabled(link) && - !link->dhcp4_configured && !link->dhcp6_configured)) - return; - - if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured) - return; - } - - SET_FOREACH(a, link->addresses, i) - if (!address_is_ready(a)) - return; - - if (link->state != LINK_STATE_CONFIGURED) - link_enter_configured(link); - - return; -} - static int link_request_set_routing_policy_rule(Link *link) { RoutingPolicyRule *rule, *rrule = NULL; int r; @@ -898,6 +841,68 @@ static int link_request_set_routes(Link *link) { return 0; } +void link_check_ready(Link *link) { + Address *a; + Iterator i; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return; + + if (!link->network) + return; + + if (!link->addresses_configured) + return; + + if (!link->neighbors_configured) + return; + + SET_FOREACH(a, link->addresses, i) + if (!address_is_ready(a)) + return; + + if (!link->addresses_ready) { + link->addresses_ready = true; + link_request_set_routes(link); + } + + if (!link->static_routes_configured) + return; + + if (!link->routing_policy_rules_configured) + return; + + if (link_ipv4ll_enabled(link)) + if (!link->ipv4ll_address || + !link->ipv4ll_route) + return; + + if (!link->network->bridge) { + + if (link_ipv6ll_enabled(link)) + if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) > 0) + return; + + if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) && + !link->dhcp4_configured) || + (link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) && + !link->dhcp6_configured) || + (link_dhcp4_enabled(link) && link_dhcp6_enabled(link) && + !link->dhcp4_configured && !link->dhcp6_configured)) + return; + + if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured) + return; + } + + if (link->state != LINK_STATE_CONFIGURED) + link_enter_configured(link); + + return; +} + static int link_request_set_neighbors(Link *link) { Neighbor *neighbor; int r; @@ -952,7 +957,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) if (link->address_messages == 0) { log_link_debug(link, "Addresses set"); link->addresses_configured = true; - link_request_set_routes(link); + link_check_ready(link); } return 1; @@ -1082,6 +1087,7 @@ static int link_request_set_addresses(Link *link) { /* Reset all *_configured flags we are configuring. */ link->addresses_configured = false; + link->addresses_ready = false; link->neighbors_configured = false; link->static_routes_configured = false; link->routing_policy_rules_configured = false; @@ -1236,7 +1242,7 @@ static int link_request_set_addresses(Link *link) { if (link->address_messages == 0) { link->addresses_configured = true; - link_request_set_routes(link); + link_check_ready(link); } else log_link_debug(link, "Setting addresses"); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 00e68fdfaa..e417ea26ef 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -82,6 +82,7 @@ typedef struct Link { Set *routes_foreign; bool addresses_configured; + bool addresses_ready; sd_dhcp_client *dhcp_client; sd_dhcp_lease *dhcp_lease; diff --git a/test/test-network/conf/25-route-ipv6-src.network b/test/test-network/conf/25-route-ipv6-src.network new file mode 100644 index 0000000000..4e551c024a --- /dev/null +++ b/test/test-network/conf/25-route-ipv6-src.network @@ -0,0 +1,16 @@ +# This test cannot use a dummy interface: IPv6 addresses +# are added without having to go through tentative state + +[Match] +Name=bond199 + +[Network] +LinkLocalAddressing=ipv6 +Address=2001:1234:56:8f63::1/64 +Address=2001:1234:56:8f63::2/64 +IPv6AcceptRA=no + +[Route] +Destination=abcd::/16 +Gateway=2001:1234:56:8f63::1:1 +PreferredSource=2001:1234:56:8f63::2 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 5f57631cfb..33ec40b012 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -551,6 +551,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities): '25-link-section-unmanaged.network', '25-route-gateway.network', '25-route-gateway-on-link.network', + '25-route-ipv6-src.network', '25-route-reverse-order.network', '25-route-section.network', '25-route-tcp-window-settings.network', @@ -784,6 +785,22 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'scope') self.assertRegex(output, 'link') + def test_ip_route_ipv6_src_route(self): + # a dummy device does not make the addresses go through tentative state, so we + # reuse a bond from an earlier test, which does make the addresses go through + # tentative state, and do our test on that + self.copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev') + self.start_networkd() + + self.assertTrue(self.link_exits('dummy98')) + self.assertTrue(self.link_exits('bond199')) + + output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'abcd::/16') + self.assertRegex(output, 'src') + self.assertRegex(output, '2001:1234:56:8f63::2') + def test_ip_link_mac_address(self): self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev') self.start_networkd()