mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +03:00
Merge pull request #21585 from yuwata/network-radv-uplink-interface-auto-with-dhcp6-pd
network: cleanups for uplink interface handling for RADV and DHCP6-PD
This commit is contained in:
commit
bf1e65a4fd
@ -2106,11 +2106,12 @@ Table=1234</programlisting></para>
|
||||
<listitem>
|
||||
<para>Allows DHCPv6 client to start without router advertisements's managed or other
|
||||
address configuration flag. Takes one of <literal>no</literal>, <literal>solicit</literal>
|
||||
or <literal>information-request</literal>. When this is not specified and
|
||||
<varname>UplinkInterface=:self</varname> is specified, then <literal>solicit</literal> is
|
||||
implied. Otherwise, defaults to <literal>no</literal>, and the DHCPv6 client will be
|
||||
started when an RA is received. See also <varname>DHCPv6Client=</varname> setting in the
|
||||
[IPv6AcceptRA] section.</para>
|
||||
or <literal>information-request</literal>. If this is not specified,
|
||||
<literal>solicit</literal> is used when <varname>DHCPv6PrefixDelegation=</varname> is
|
||||
enabled and <varname>UplinkInterface=:self</varname> is specified in the
|
||||
[DHCPv6PrefixDelegation] section. Otherwise, defaults to <literal>no</literal>, and the
|
||||
DHCPv6 client will be started when an RA is received. See also
|
||||
<varname>DHCPv6Client=</varname> setting in the [IPv6AcceptRA] section.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
@ -2711,9 +2712,11 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
<listitem><para>Specifies the name or the index of the uplink interface, or one of the special
|
||||
values <literal>:none</literal> and <literal>:auto</literal>. 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 <literal>:auto</literal>, the link which has a default gateway
|
||||
with the highest priority will be automatically selected. When <literal>:none</literal>, no
|
||||
uplink interface will be selected. Defaults to <literal>:auto</literal>.</para></listitem>
|
||||
interface will be emitted. When <literal>:auto</literal>, the value specified to the same
|
||||
setting in the [DHCPv6PrefixDelegation] section will be used if
|
||||
<varname>DHCPv6PrefixDelegation=</varname> is enabled, otherwise the link which has a default
|
||||
gateway with the highest priority will be automatically selected. When <literal>:none</literal>,
|
||||
no uplink interface will be selected. Defaults to <literal>:auto</literal>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -52,6 +52,7 @@ struct Manager {
|
||||
Hashmap *netdevs;
|
||||
OrderedHashmap *networks;
|
||||
OrderedSet *address_pools;
|
||||
Set *dhcp6_pd_subnet_ids;
|
||||
|
||||
usec_t network_dirs_ts_usec;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
9
test/test-network/conf/25-veth-downstream-veth97.netdev
Normal file
9
test/test-network/conf/25-veth-downstream-veth97.netdev
Normal file
@ -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
|
@ -10,7 +10,7 @@ DHCPv6PrefixDelegation=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
SubnetId=6
|
||||
SubnetId=1
|
||||
Announce=no
|
||||
Token=eui64
|
||||
Token=::1a:2b:3c:4d
|
||||
|
@ -10,7 +10,7 @@ DHCPv6PrefixDelegation=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
SubnetId=3
|
||||
SubnetId=2
|
||||
Announce=no
|
||||
Token=eui64
|
||||
Token=::1a:2b:3c:4d
|
||||
|
@ -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
|
20
test/test-network/conf/dhcp6pd-downstream-veth97.network
Normal file
20
test/test-network/conf/dhcp6pd-downstream-veth97.network
Normal file
@ -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
|
@ -17,6 +17,5 @@ Token=eui64
|
||||
Token=::1a:2b:3c:4d
|
||||
|
||||
[IPv6SendRA]
|
||||
UplinkInterface=:none
|
||||
EmitDNS=no
|
||||
EmitDomains=no
|
||||
|
@ -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 = [
|
||||
|
Loading…
Reference in New Issue
Block a user