diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 731dbf4e61..50367ecdcd 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2106,11 +2106,12 @@ Table=1234 Allows DHCPv6 client to start without router advertisements's managed or other address configuration flag. Takes one of no, solicit - or information-request. When this is not specified and - UplinkInterface=:self is specified, then solicit is - implied. Otherwise, defaults to no, and the DHCPv6 client will be - started when an RA is received. See also DHCPv6Client= setting in the - [IPv6AcceptRA] section. + or information-request. If this is not specified, + solicit is used when DHCPv6PrefixDelegation= is + enabled and UplinkInterface=:self is specified in the + [DHCPv6PrefixDelegation] section. Otherwise, defaults to no, and the + DHCPv6 client will be started when an RA is received. See also + DHCPv6Client= setting in the [IPv6AcceptRA] section. @@ -2711,9 +2712,11 @@ Token=prefixstable:2002:da8:1:: Specifies the name or the index of the uplink interface, or one of the special values :none and :auto. When emitting DNS servers or search domains is enabled but no servers are specified, the servers configured in the uplink - interface will be emitted. When :auto, the link which has a default gateway - with the highest priority will be automatically selected. When :none, no - uplink interface will be selected. Defaults to :auto. + interface will be emitted. When :auto, the value specified to the same + setting in the [DHCPv6PrefixDelegation] section will be used if + DHCPv6PrefixDelegation= is enabled, otherwise the link which has a default + gateway with the highest priority will be automatically selected. When :none, + no uplink interface will be selected. Defaults to :auto. diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 8d48aa9f88..76f4e4109c 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -42,25 +42,28 @@ bool link_dhcp6_pd_is_enabled(Link *link) { return link->network->dhcp6_pd; } -static int dhcp6_pd_resolve_uplink(Link *link, Link **ret) { +static bool dhcp6_pd_is_uplink(Link *link, Link *target, bool accept_auto) { + assert(link); + assert(target); + + if (!link_dhcp6_pd_is_enabled(link)) + return false; + if (link->network->dhcp6_pd_uplink_name) - return link_get_by_name(link->manager, link->network->dhcp6_pd_uplink_name, ret); + return streq_ptr(target->ifname, link->network->dhcp6_pd_uplink_name) || + strv_contains(target->alternative_names, link->network->dhcp6_pd_uplink_name); if (link->network->dhcp6_pd_uplink_index > 0) - return link_get_by_index(link->manager, link->network->dhcp6_pd_uplink_index, ret); + return target->ifindex == link->network->dhcp6_pd_uplink_index; - if (link->network->dhcp6_pd_uplink_index == UPLINK_INDEX_SELF) { - *ret = link; - return 0; - } + if (link->network->dhcp6_pd_uplink_index == UPLINK_INDEX_SELF) + return link == target; assert(link->network->dhcp6_pd_uplink_index == UPLINK_INDEX_AUTO); - return -ENOENT; + return accept_auto; } static DHCP6ClientStartMode link_get_dhcp6_client_start_mode(Link *link) { - Link *uplink; - assert(link); if (!link->network) @@ -70,11 +73,12 @@ static DHCP6ClientStartMode link_get_dhcp6_client_start_mode(Link *link) { if (link->network->dhcp6_client_start_mode >= 0) return link->network->dhcp6_client_start_mode; - if (dhcp6_pd_resolve_uplink(link, &uplink) < 0) - return DHCP6_CLIENT_START_MODE_NO; + /* When this interface itself is an uplink interface, then start dhcp6 client in managed mode. */ + if (dhcp6_pd_is_uplink(link, link, /* accept_auto = */ false)) + return DHCP6_CLIENT_START_MODE_SOLICIT; - /* When this interface itself is an uplink interface, then start dhcp6 client in managed mode */ - return uplink == link ? DHCP6_CLIENT_START_MODE_SOLICIT : DHCP6_CLIENT_START_MODE_NO; + /* Otherwise, start dhcp6 client when RA is received. */ + return DHCP6_CLIENT_START_MODE_NO; } static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) { @@ -527,13 +531,20 @@ static int dhcp6_pd_get_preferred_prefix( } for (uint64_t n = 0; ; n++) { + /* If we do not have an allocation preference just iterate + * through the address space and return the first free prefix. */ + r = dhcp6_pd_calculate_prefix(pd_prefix, pd_prefix_len, n, &prefix); if (r < 0) return log_link_warning_errno(link, r, "Couldn't find a suitable prefix. Ran out of address space."); - /* If we do not have an allocation preference just iterate - * through the address space and return the first free prefix. */ + /* Do not use explicitly requested subnet IDs. Note that the corresponding link may not + * appear yet. So, we need to check the ID is not used in any .network files. */ + if (set_contains(link->manager->dhcp6_pd_subnet_ids, &n)) + continue; + + /* Check that the prefix is not assigned to another link. */ if (link_get_by_dhcp6_pd_prefix(link->manager, &prefix, &assigned_link) < 0 || assigned_link == link) { *ret = prefix; @@ -598,8 +609,7 @@ static int dhcp6_pd_distribute_prefix( const struct in6_addr *pd_prefix, uint8_t pd_prefix_len, usec_t lifetime_preferred_usec, - usec_t lifetime_valid_usec, - bool assign_preferred_subnet_id) { + usec_t lifetime_valid_usec) { Link *link; int r; @@ -610,12 +620,10 @@ static int dhcp6_pd_distribute_prefix( assert(pd_prefix_len <= 64); HASHMAP_FOREACH(link, dhcp6_link->manager->links_by_index) { - Link *uplink; - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) continue; - if (!link_dhcp6_pd_is_enabled(link)) + if (!dhcp6_pd_is_uplink(link, dhcp6_link, /* accept_auto = */ true)) continue; if (link->network->dhcp6_pd_announce && !link->radv) @@ -624,18 +632,6 @@ static int dhcp6_pd_distribute_prefix( if (link == dhcp6_link && !link->network->dhcp6_pd_assign) continue; - if (assign_preferred_subnet_id != link_has_preferred_subnet_id(link)) - continue; - - r = dhcp6_pd_resolve_uplink(link, &uplink); - if (r != -ENOENT) { - if (r < 0) /* The uplink interface does not exist yet. */ - continue; - - if (uplink != dhcp6_link) - continue; - } - r = dhcp6_pd_assign_prefix(link, pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec); if (r < 0) { if (link == dhcp6_link) @@ -985,17 +981,7 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { &pd_prefix, pd_prefix_len, lifetime_preferred_usec, - lifetime_valid_usec, - true); - if (r < 0) - return r; - - r = dhcp6_pd_distribute_prefix(dhcp6_link, - &pd_prefix, - pd_prefix_len, - lifetime_preferred_usec, - lifetime_valid_usec, - false); + lifetime_valid_usec); if (r < 0) return r; } @@ -1452,28 +1438,38 @@ static bool dhcp6_pd_uplink_is_ready(Link *link) { return dhcp6_lease_has_pd_prefix(link->dhcp6_lease); } -static int dhcp6_pd_find_uplink(Link *link, Link **ret) { - Link *l; +int dhcp6_pd_find_uplink(Link *link, Link **ret) { + Link *uplink = NULL; + int r = 0; assert(link); assert(link->manager); - assert(link->network); + assert(link_dhcp6_pd_is_enabled(link)); assert(ret); - if (dhcp6_pd_resolve_uplink(link, &l) >= 0) { - if (!dhcp6_pd_uplink_is_ready(l)) + if (link->network->dhcp6_pd_uplink_name) + r = link_get_by_name(link->manager, link->network->dhcp6_pd_uplink_name, &uplink); + else if (link->network->dhcp6_pd_uplink_index > 0) + r = link_get_by_index(link->manager, link->network->dhcp6_pd_uplink_index, &uplink); + else if (link->network->dhcp6_pd_uplink_index == UPLINK_INDEX_SELF) + uplink = link; + if (r < 0) + return r; + + if (uplink) { + if (!dhcp6_pd_uplink_is_ready(uplink)) return -EBUSY; - *ret = l; + *ret = uplink; return 0; } - HASHMAP_FOREACH(l, link->manager->links_by_index) { - if (!dhcp6_pd_uplink_is_ready(l)) + HASHMAP_FOREACH(uplink, link->manager->links_by_index) { + if (!dhcp6_pd_uplink_is_ready(uplink)) continue; /* Assume that there exists at most one link which acquired delegated prefixes. */ - *ret = l; + *ret = uplink; return 0; } diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h index 4a522aebcf..9c5aff6af7 100644 --- a/src/network/networkd-dhcp6.h +++ b/src/network/networkd-dhcp6.h @@ -18,6 +18,7 @@ typedef struct Request Request; bool link_dhcp6_with_address_enabled(Link *link); bool link_dhcp6_pd_is_enabled(Link *link); +int dhcp6_pd_find_uplink(Link *link, Link **ret); int dhcp6_pd_remove(Link *link, bool only_marked); int dhcp6_update_mac(Link *link); int dhcp6_start(Link *link); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 2141e20622..a122e08800 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -502,6 +502,7 @@ Manager* manager_free(Manager *m) { m->links_by_dhcp6_pd_prefix = hashmap_free(m->links_by_dhcp6_pd_prefix); m->links_by_index = hashmap_free_with_destructor(m->links_by_index, link_unref); + m->dhcp6_pd_subnet_ids = set_free(m->dhcp6_pd_subnet_ids); m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref); m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref); @@ -585,7 +586,7 @@ int manager_load_config(Manager *m) { if (r < 0) return r; - return 0; + return manager_build_dhcp6_pd_subnet_ids(m); } bool manager_should_reload(Manager *m) { diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 42b77ee0f5..ae9d5adf1b 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -52,6 +52,7 @@ struct Manager { Hashmap *netdevs; OrderedHashmap *networks; OrderedSet *address_pools; + Set *dhcp6_pd_subnet_ids; usec_t network_dirs_ts_usec; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index c97998848c..443222f610 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -643,7 +643,7 @@ int network_reload(Manager *manager) { ordered_hashmap_free_with_destructor(manager->networks, network_unref); manager->networks = new_networks; - return 0; + return manager_build_dhcp6_pd_subnet_ids(manager); failure: ordered_hashmap_free_with_destructor(new_networks, network_unref); @@ -651,6 +651,32 @@ failure: return r; } +int manager_build_dhcp6_pd_subnet_ids(Manager *manager) { + Network *n; + int r; + + assert(manager); + + set_clear(manager->dhcp6_pd_subnet_ids); + + ORDERED_HASHMAP_FOREACH(n, manager->networks) { + if (n->unmanaged) + continue; + + if (!n->dhcp6_pd) + continue; + + if (n->dhcp6_pd_subnet_id < 0) + continue; + + r = set_ensure_put(&manager->dhcp6_pd_subnet_ids, &uint64_hash_ops, &n->dhcp6_pd_subnet_id); + if (r < 0) + return r; + } + + return 0; +} + static Network *network_free(Network *network) { if (!network) return NULL; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 942210470c..2fdd4994c4 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -365,6 +365,8 @@ int network_reload(Manager *manager); int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename); int network_verify(Network *network); +int manager_build_dhcp6_pd_subnet_ids(Manager *manager); + int network_get_by_name(Manager *manager, const char *name, Network **ret); void network_apply_anonymize_if_set(Network *network); diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index c98528aee9..a137270cfa 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -410,6 +410,8 @@ set_domains: } static int radv_find_uplink(Link *link, Link **ret) { + int r; + assert(link); if (link->network->router_uplink_name) @@ -419,8 +421,12 @@ static int radv_find_uplink(Link *link, Link **ret) { return link_get_by_index(link->manager, link->network->router_uplink_index, ret); if (link->network->router_uplink_index == UPLINK_INDEX_AUTO) { - /* It is not necessary to propagate error in automatic selection. */ - if (manager_find_uplink(link->manager, AF_INET6, link, ret) < 0) + if (link_dhcp6_pd_is_enabled(link)) + r = dhcp6_pd_find_uplink(link, ret); /* When DHCPv6PD is enabled, use its uplink. */ + else + r = manager_find_uplink(link->manager, AF_INET6, link, ret); + if (r < 0) + /* It is not necessary to propagate error in automatic selection. */ *ret = NULL; return 0; } diff --git a/test/test-network/conf/25-veth-downstream-veth97.netdev b/test/test-network/conf/25-veth-downstream-veth97.netdev new file mode 100644 index 0000000000..5ba18ce9ef --- /dev/null +++ b/test/test-network/conf/25-veth-downstream-veth97.netdev @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[NetDev] +Name=veth97 +Kind=veth +MACAddress=12:34:56:78:9a:ce + +[Peer] +Name=veth97-peer +MACAddress=12:34:56:78:9a:cf diff --git a/test/test-network/conf/25-veth-downstream.netdev b/test/test-network/conf/25-veth-downstream-veth98.netdev similarity index 100% rename from test/test-network/conf/25-veth-downstream.netdev rename to test/test-network/conf/25-veth-downstream-veth98.netdev diff --git a/test/test-network/conf/dhcp6pd-downstream-dummy97.network b/test/test-network/conf/dhcp6pd-downstream-dummy97.network index 01174f3bb0..b53bc3cc4d 100644 --- a/test/test-network/conf/dhcp6pd-downstream-dummy97.network +++ b/test/test-network/conf/dhcp6pd-downstream-dummy97.network @@ -10,7 +10,7 @@ DHCPv6PrefixDelegation=yes [DHCPv6PrefixDelegation] UplinkInterface=veth99 -SubnetId=6 +SubnetId=1 Announce=no Token=eui64 Token=::1a:2b:3c:4d diff --git a/test/test-network/conf/dhcp6pd-downstream-dummy98.network b/test/test-network/conf/dhcp6pd-downstream-dummy98.network index 8260e0cc7c..ea66d49a2f 100644 --- a/test/test-network/conf/dhcp6pd-downstream-dummy98.network +++ b/test/test-network/conf/dhcp6pd-downstream-dummy98.network @@ -10,7 +10,7 @@ DHCPv6PrefixDelegation=yes [DHCPv6PrefixDelegation] UplinkInterface=veth99 -SubnetId=3 +SubnetId=2 Announce=no Token=eui64 Token=::1a:2b:3c:4d diff --git a/test/test-network/conf/dhcp6pd-downstream-veth97-peer.network b/test/test-network/conf/dhcp6pd-downstream-veth97-peer.network new file mode 100644 index 0000000000..555fefa497 --- /dev/null +++ b/test/test-network/conf/dhcp6pd-downstream-veth97-peer.network @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=veth97-peer + +[Network] +IPv6PrivacyExtensions=yes +IPv6AcceptRA=yes + +[IPv6AcceptRA] +Token=eui64 +Token=::1a:2b:3c:4e diff --git a/test/test-network/conf/dhcp6pd-downstream-veth97.network b/test/test-network/conf/dhcp6pd-downstream-veth97.network new file mode 100644 index 0000000000..5c41ea9837 --- /dev/null +++ b/test/test-network/conf/dhcp6pd-downstream-veth97.network @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=veth97 + +[Network] +IPv6PrivacyExtensions=yes +IPv6AcceptRA=no +DHCP=no +DHCPv6PrefixDelegation=yes +IPv6SendRA=yes + +[DHCPv6PrefixDelegation] +SubnetId=8 +Announce=yes +Token=eui64 +Token=::1a:2b:3c:4d + +[IPv6SendRA] +EmitDNS=no +EmitDomains=no diff --git a/test/test-network/conf/dhcp6pd-downstream-veth98.network b/test/test-network/conf/dhcp6pd-downstream-veth98.network index 14c543d1bc..a977099389 100644 --- a/test/test-network/conf/dhcp6pd-downstream-veth98.network +++ b/test/test-network/conf/dhcp6pd-downstream-veth98.network @@ -17,6 +17,5 @@ Token=eui64 Token=::1a:2b:3c:4d [IPv6SendRA] -UplinkInterface=:none EmitDNS=no EmitDomains=no diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 2c70a05719..b8655db370 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -5002,6 +5002,7 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities): 'dummy98', 'dummy99', 'test1', + 'veth97', 'veth98', 'veth99', ] @@ -5011,11 +5012,14 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities): '12-dummy.netdev', '13-dummy.netdev', '25-veth.netdev', - '25-veth-downstream.netdev', + '25-veth-downstream-veth97.netdev', + '25-veth-downstream-veth98.netdev', 'dhcp6pd-downstream-dummy97.network', 'dhcp6pd-downstream-dummy98.network', 'dhcp6pd-downstream-dummy99.network', 'dhcp6pd-downstream-test1.network', + 'dhcp6pd-downstream-veth97.network', + 'dhcp6pd-downstream-veth97-peer.network', 'dhcp6pd-downstream-veth98.network', 'dhcp6pd-downstream-veth98-peer.network', 'dhcp6pd-server.network', @@ -5035,7 +5039,8 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities): def test_dhcp6pd(self): copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp6pd-server.network', 'dhcp6pd-upstream.network', - '25-veth-downstream.netdev', 'dhcp6pd-downstream-veth98.network', 'dhcp6pd-downstream-veth98-peer.network', + '25-veth-downstream-veth97.netdev', 'dhcp6pd-downstream-veth97.network', 'dhcp6pd-downstream-veth97-peer.network', + '25-veth-downstream-veth98.netdev', 'dhcp6pd-downstream-veth98.network', 'dhcp6pd-downstream-veth98-peer.network', '11-dummy.netdev', 'dhcp6pd-downstream-test1.network', 'dhcp6pd-downstream-dummy97.network', '12-dummy.netdev', 'dhcp6pd-downstream-dummy98.network', @@ -5045,13 +5050,24 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities): self.wait_online(['veth-peer:carrier']) start_isc_dhcpd('veth-peer', 'isc-dhcpd-dhcp6pd.conf') self.wait_online(['veth-peer:routable', 'veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded', - 'veth98:routable', 'veth98-peer:routable']) + 'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable']) print('### ip -6 address show dev veth-peer scope global') output = check_output('ip -6 address show dev veth-peer scope global') print(output) self.assertIn('inet6 3ffe:501:ffff:100::1/64 scope global', output) + ''' + Link Subnet IDs + test1: 0x00 + dummy97: 0x01 (The link will appear later) + dummy98: 0x02 + dummy99: auto -> 0x03 (No address assignment) + veth97: 0x08 + veth98: 0x09 + veth99: 0x10 + ''' + print('### ip -6 address show dev veth99 scope global') output = check_output('ip -6 address show dev veth99 scope global') print(output) @@ -5077,9 +5093,35 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities): output = check_output('ip -6 address show dev dummy98 scope global') print(output) # address in IA_PD (Token=static) - self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]03:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') + self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') # address in IA_PD (temporary) - self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]03:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') + self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]02:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') + + print('### ip -6 address show dev dummy99 scope global') + output = check_output('ip -6 address show dev dummy99 scope global') + print(output) + # Assign=no + self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]03') + + print('### ip -6 address show dev veth97 scope global') + output = check_output('ip -6 address show dev veth97 scope global') + print(output) + # address in IA_PD (Token=static) + self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') + # address in IA_PD (Token=eui64) + self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1034:56ff:fe78:9ace/64 (metric 256 |)scope global dynamic mngtmpaddr') + # address in IA_PD (temporary) + self.wait_address('veth97', 'inet6 3ffe:501:ffff:[2-9a-f]08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') + + print('### ip -6 address show dev veth97-peer scope global') + output = check_output('ip -6 address show dev veth97-peer scope global') + print(output) + # NDisc address (Token=static) + self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr') + # NDisc address (Token=eui64) + self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1034:56ff:fe78:9acf/64 (metric 256 |)scope global dynamic mngtmpaddr') + # NDisc address (temporary) + self.wait_address('veth97-peer', 'inet6 3ffe:501:ffff:[2-9a-f]08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') print('### ip -6 address show dev veth98 scope global') output = check_output('ip -6 address show dev veth98 scope global') @@ -5101,10 +5143,6 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities): # NDisc address (temporary) self.wait_address('veth98-peer', 'inet6 3ffe:501:ffff:[2-9a-f]09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') - print('### ip -6 address show dev dummy99 scope global') - output = check_output('ip -6 address show dev dummy98 scope global') - print(output) - print('### ip -6 route show type unreachable') output = check_output('ip -6 route show type unreachable') print(output) @@ -5123,12 +5161,22 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities): print('### ip -6 route show dev dummy98') output = check_output('ip -6 route show dev dummy98') print(output) - self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto kernel metric [0-9]* expires') + self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto kernel metric [0-9]* expires') print('### ip -6 route show dev dummy99') output = check_output('ip -6 route show dev dummy99') print(output) - self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]01::/64 proto dhcp metric [0-9]* expires') + self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto dhcp metric [0-9]* expires') + + print('### ip -6 route show dev veth97') + output = check_output('ip -6 route show dev veth97') + print(output) + self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]08::/64 proto kernel metric [0-9]* expires') + + print('### ip -6 route show dev veth97-peer') + output = check_output('ip -6 route show dev veth97-peer') + print(output) + self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]08::/64 proto ra metric [0-9]* expires') print('### ip -6 route show dev veth98') output = check_output('ip -6 route show dev veth98') @@ -5148,31 +5196,42 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities): output = check_output('ip -6 address show dev dummy97 scope global') print(output) # address in IA_PD (Token=static) - self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]06:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') + self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]01:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') # address in IA_PD (temporary) - self.wait_address('dummy97', 'inet6 3ffe:501:ffff:[2-9a-f]06:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') + self.wait_address('dummy97', 'inet6 3ffe:501:ffff:[2-9a-f]01:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') print('### ip -6 route show dev dummy97') output = check_output('ip -6 route show dev dummy97') print(output) - self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]06::/64 proto kernel metric [0-9]* expires') + self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]01::/64 proto kernel metric [0-9]* expires') # Test case for reconfigure - check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env) + check_output(*networkctl_cmd, 'reconfigure', 'dummy98', 'dummy99', env=env) self.wait_online(['dummy98:routable']) print('### ip -6 address show dev dummy98 scope global') output = check_output('ip -6 address show dev dummy98 scope global') print(output) # address in IA_PD (Token=static) - self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]03:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') + self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') # address in IA_PD (temporary) - self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]03:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') + self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]02:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') + + print('### ip -6 address show dev dummy99 scope global') + output = check_output('ip -6 address show dev dummy99 scope global') + print(output) + # Assign=no + self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]03') print('### ip -6 route show dev dummy98') output = check_output('ip -6 route show dev dummy98') print(output) - self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto kernel metric [0-9]* expires') + self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto kernel metric [0-9]* expires') + + print('### ip -6 route show dev dummy99') + output = check_output('ip -6 route show dev dummy99') + print(output) + self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto dhcp metric [0-9]* expires') class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities): links = [