From f6032ff3e0970c93c97387e10c56a4be2a978948 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 1 Dec 2021 14:37:26 +0900 Subject: [PATCH 1/6] network: radv: use the uplink interface used in DHCPv6-PD --- man/systemd.network.xml | 8 +++++--- src/network/networkd-dhcp6.c | 2 +- src/network/networkd-dhcp6.h | 1 + src/network/networkd-radv.c | 10 ++++++++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index e90877ada8..fb2569a9dd 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2711,9 +2711,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..da5a22a7b5 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -1452,7 +1452,7 @@ 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) { +int dhcp6_pd_find_uplink(Link *link, Link **ret) { Link *l; assert(link); 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-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; } From 926fc8ee6360980682ffb50d2e3dcbe961316b74 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 1 Dec 2021 14:48:51 +0900 Subject: [PATCH 2/6] network: dhcp6: make UplinkInterface=:self take effect only when DHCPv6PrefixDelegation= is enabled --- man/systemd.network.xml | 11 ++++++----- src/network/networkd-dhcp6.c | 3 +++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index fb2569a9dd..1457b3e691 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. diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index da5a22a7b5..5c9c211662 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -70,6 +70,9 @@ 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 (!link_dhcp6_pd_is_enabled(link)) + return DHCP6_CLIENT_START_MODE_NO; + if (dhcp6_pd_resolve_uplink(link, &uplink) < 0) return DHCP6_CLIENT_START_MODE_NO; From a74229c58ed4e472875829589502119e4badc483 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 1 Dec 2021 19:24:22 +0900 Subject: [PATCH 3/6] network: dhcp6-pd: introduce dhcp6_pd_is_uplink() This also merges dhcp6_pd_resolve_uplink() with dhcp6_pd_find_uplink() --- src/network/networkd-dhcp6.c | 74 ++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 5c9c211662..3c3794ab87 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,14 +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 (!link_dhcp6_pd_is_enabled(link)) - 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; - 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 */ - 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) { @@ -613,12 +614,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) @@ -630,15 +629,6 @@ static int dhcp6_pd_distribute_prefix( 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) @@ -1456,27 +1446,37 @@ static bool dhcp6_pd_uplink_is_ready(Link *link) { } int dhcp6_pd_find_uplink(Link *link, Link **ret) { - Link *l; + 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; } From 1a4ca0e2f35d859f2d7f3bb8c94eefe2ad1c2ff4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 1 Dec 2021 19:43:40 +0900 Subject: [PATCH 4/6] network: dhcp6-pd: exclude all explicitly specified subnet IDs when searching free IDs When the upstream link gained a lease, then several downstream links may not appear yet. Previously, the explicitly specified subnet ID for a downstream link which appears later may be already assigned to an interface which does not request specific subnet ID. To avoid such situation, this makes all specified IDs are excluded when searching free IDs. As a side effect, we can avoid the second call of dhcp6_pd_distribute_prefix(). --- src/network/networkd-dhcp6.c | 29 +++++++++++------------------ src/network/networkd-manager.c | 3 ++- src/network/networkd-manager.h | 1 + src/network/networkd-network.c | 28 +++++++++++++++++++++++++++- src/network/networkd-network.h | 2 ++ 5 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 3c3794ab87..76f4e4109c 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -531,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; @@ -602,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; @@ -626,9 +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_assign_prefix(link, pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec); if (r < 0) { if (link == dhcp6_link) @@ -978,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; } 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); From 6c8d6bdd40d36d036521fc7a8b9c791551685e38 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 1 Dec 2021 15:08:00 +0900 Subject: [PATCH 5/6] test-network: add testcases for uplink interface detection for RADV with DHCPv6-PD --- .../conf/25-veth-downstream-veth97.netdev | 9 ++++++ ...etdev => 25-veth-downstream-veth98.netdev} | 0 .../dhcp6pd-downstream-veth97-peer.network | 11 +++++++ .../conf/dhcp6pd-downstream-veth97.network | 20 ++++++++++++ .../conf/dhcp6pd-downstream-veth98.network | 1 - test/test-network/systemd-networkd-tests.py | 31 +++++++++++++++++-- 6 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 test/test-network/conf/25-veth-downstream-veth97.netdev rename test/test-network/conf/{25-veth-downstream.netdev => 25-veth-downstream-veth98.netdev} (100%) create mode 100644 test/test-network/conf/dhcp6pd-downstream-veth97-peer.network create mode 100644 test/test-network/conf/dhcp6pd-downstream-veth97.network 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-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..af1e02e52f 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,7 +5050,7 @@ 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') @@ -5081,6 +5086,26 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities): # 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') + 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') print(output) From 6016f1cfbb32568452cae070e6271b8cc3319c16 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 1 Dec 2021 20:34:48 +0900 Subject: [PATCH 6/6] test-network: re-arrange DHCP6-PD subnet IDs to test searching free subnet ID --- .../conf/dhcp6pd-downstream-dummy97.network | 2 +- .../conf/dhcp6pd-downstream-dummy98.network | 2 +- test/test-network/systemd-networkd-tests.py | 64 ++++++++++++++----- 3 files changed, 51 insertions(+), 17 deletions(-) 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/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index af1e02e52f..b8655db370 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -5057,6 +5057,17 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities): 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) @@ -5082,9 +5093,15 @@ 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') @@ -5126,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) @@ -5148,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') @@ -5173,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 = [