1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-24 21:34:08 +03:00

network: dhcp-pd: allow to assign the same subnet prefix to multiple interfaces

There is no reason networkd refuses that. Especially, when multiple
downstream interfaces are connected to the same network, it is natural to
assign the same subnet prefix to them.

Prompted by #22571.
This commit is contained in:
Yu Watanabe 2022-02-20 11:46:16 +09:00
parent 38488babe7
commit 07b7337aff
3 changed files with 38 additions and 46 deletions

View File

@ -487,20 +487,13 @@ static int dhcp_pd_get_preferred_subnet_prefix(
"subnet id %" PRIu64 " is out of range. Only have %" PRIu64 " subnets.",
link->network->dhcp_pd_subnet_id, UINT64_C(1) << (64 - pd_prefix_len));
if (link_get_by_dhcp_pd_subnet_prefix(link->manager, &prefix, &assigned_link) >= 0 &&
assigned_link != link) {
_cleanup_free_ char *assigned_buf = NULL;
(void) in6_addr_to_string(&prefix, &assigned_buf);
return log_link_warning_errno(link, SYNTHETIC_ERRNO(EAGAIN),
"The requested prefix %s is already assigned to another link.",
strna(assigned_buf));
}
*ret = prefix;
return 0;
}
if (dhcp_pd_get_assigned_subnet_prefix(link, pd_prefix, pd_prefix_len, ret) >= 0)
return 0;
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. */
@ -517,11 +510,16 @@ static int dhcp_pd_get_preferred_subnet_prefix(
/* Check that the prefix is not assigned to another link. */
if (link_get_by_dhcp_pd_subnet_prefix(link->manager, &prefix, &assigned_link) < 0 ||
assigned_link == link) {
*ret = prefix;
return 0;
}
assigned_link == link)
break;
}
r = link_add_dhcp_pd_subnet_prefix(link, &prefix);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to save acquired free subnet prefix: %m");
*ret = prefix;
return 0;
}
static int dhcp_pd_assign_subnet_prefix(
@ -540,9 +538,9 @@ static int dhcp_pd_assign_subnet_prefix(
assert(link->network);
assert(pd_prefix);
if (dhcp_pd_get_assigned_subnet_prefix(link, pd_prefix, pd_prefix_len, &prefix) < 0 &&
dhcp_pd_get_preferred_subnet_prefix(link, pd_prefix, pd_prefix_len, &prefix) < 0)
return 0;
r = dhcp_pd_get_preferred_subnet_prefix(link, pd_prefix, pd_prefix_len, &prefix);
if (r < 0)
return r == -ERANGE ? 0 : r;
(void) in6_addr_prefix_to_string(&prefix, 64, &buf);
@ -570,12 +568,6 @@ static int dhcp_pd_assign_subnet_prefix(
"Failed to assign/update address for prefix %s: %m",
strna(buf));
r = link_add_dhcp_pd_subnet_prefix(link, &prefix);
if (r < 0)
return log_link_warning_errno(link, r,
"Failed to save assigned prefix %s: %m",
strna(buf));
log_link_debug(link, "Assigned prefix %s", strna(buf));
return 1;
}

View File

@ -10,7 +10,7 @@ DHCPPrefixDelegation=yes
[DHCPPrefixDelegation]
UplinkInterface=veth99
SubnetId=2
SubnetId=0
Announce=no
Token=eui64
Token=::1a:2b:3c:4d

View File

@ -5269,8 +5269,8 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
# Link Subnet IDs
# test1: 0x00
# dummy97: 0x01 (The link will appear later)
# dummy98: 0x02
# dummy99: auto -> 0x03 (No address assignment)
# dummy98: 0x00
# dummy99: auto -> 0x02 (No address assignment)
# veth97: 0x08
# veth98: 0x09
# veth99: 0x10
@ -5300,15 +5300,15 @@ class NetworkdDHCPPDTests(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]02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00: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]02:[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]00:[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')
self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02')
print('### ip -6 address show dev veth97 scope global')
output = check_output('ip -6 address show dev veth97 scope global')
@ -5368,12 +5368,12 @@ class NetworkdDHCPPDTests(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]02::/64 proto kernel metric [0-9]* expires')
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/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')
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto dhcp metric [0-9]* expires')
print('### ip -6 route show dev veth97')
output = check_output('ip -6 route show dev veth97')
@ -5420,25 +5420,25 @@ class NetworkdDHCPPDTests(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]02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00: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]02:[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]00:[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')
self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02')
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]02::/64 proto kernel metric [0-9]* expires')
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/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')
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto dhcp metric [0-9]* expires')
def verify_dhcp4_6rd(self, tunnel_name):
print('### ip -4 address show dev veth-peer scope global')
@ -5449,9 +5449,9 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
# Link Subnet IDs
# test1: 0x00
# dummy97: 0x01 (The link will appear later)
# dummy98: 0x02
# dummy99: auto -> 0x0[34] (No address assignment)
# 6rd-XXX: auto -> 0x0[34]
# dummy98: 0x00
# dummy99: auto -> 0x0[23] (No address assignment)
# 6rd-XXX: auto -> 0x0[23]
# veth97: 0x08
# veth98: 0x09
# veth99: 0x10
@ -5484,15 +5484,15 @@ class NetworkdDHCPPDTests(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 2001:db8:6464:[0-9a-f]+02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
# address in IA_PD (temporary)
self.wait_address('dummy98', 'inet6 2001:db8:6464:[0-9a-f]+02:[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 2001:db8:6464:[0-9a-f]+00:[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 2001:db8:6464:[0-9a-f]+0[34]')
self.assertNotRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+0[23]')
print('### ip -6 address show dev veth97 scope global')
output = check_output('ip -6 address show dev veth97 scope global')
@ -5552,12 +5552,12 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
print('### ip -6 route show dev dummy98')
output = check_output('ip -6 route show dev dummy98')
print(output)
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+02::/64 proto kernel metric [0-9]* expires')
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+00::/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, '2001:db8:6464:[0-9a-f]+0[34]::/64 proto dhcp metric [0-9]* expires')
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+0[23]::/64 proto dhcp metric [0-9]* expires')
print('### ip -6 route show dev veth97')
output = check_output('ip -6 route show dev veth97')
@ -5604,13 +5604,13 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
print('### ip -6 address show dev {}'.format(tunnel_name))
output = check_output('ip -6 address show dev {}'.format(tunnel_name))
print(output)
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+0[34]:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global dynamic')
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+0[23]:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global dynamic')
self.assertRegex(output, 'inet6 ::10.100.100.[0-9]+/96 scope global')
print('### ip -6 route show dev {}'.format(tunnel_name))
output = check_output('ip -6 route show dev {}'.format(tunnel_name))
print(output)
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+0[34]::/64 proto kernel metric [0-9]* expires')
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+0[23]::/64 proto kernel metric [0-9]* expires')
self.assertRegex(output, '::/96 proto kernel metric [0-9]*')
print('### ip -6 route show default')