mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 10:13:34 +08:00
test-network: add test cases for DHCPv6 prefix delegation
This commit is contained in:
parent
dc5cae6c9d
commit
caad88a22b
4
test/test-network/conf/13-dummy.netdev
Normal file
4
test/test-network/conf/13-dummy.netdev
Normal file
@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[NetDev]
|
||||
Name=dummy99
|
||||
Kind=dummy
|
9
test/test-network/conf/25-veth-downstream.netdev
Normal file
9
test/test-network/conf/25-veth-downstream.netdev
Normal file
@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[NetDev]
|
||||
Name=veth98
|
||||
Kind=veth
|
||||
MACAddress=12:34:56:78:9a:be
|
||||
|
||||
[Peer]
|
||||
Name=veth98-peer
|
||||
MACAddress=12:34:56:78:9a:bf
|
16
test/test-network/conf/dhcp6pd-downstream-dummy97.network
Normal file
16
test/test-network/conf/dhcp6pd-downstream-dummy97.network
Normal file
@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=dummy97
|
||||
|
||||
[Network]
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=no
|
||||
DHCPv6PrefixDelegation=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
SubnetId=6
|
||||
Announce=no
|
||||
Token=eui64
|
||||
Token=::1a:2b:3c:4d
|
16
test/test-network/conf/dhcp6pd-downstream-dummy98.network
Normal file
16
test/test-network/conf/dhcp6pd-downstream-dummy98.network
Normal file
@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=dummy98
|
||||
|
||||
[Network]
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=no
|
||||
DHCPv6PrefixDelegation=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
SubnetId=3
|
||||
Announce=no
|
||||
Token=eui64
|
||||
Token=::1a:2b:3c:4d
|
14
test/test-network/conf/dhcp6pd-downstream-dummy99.network
Normal file
14
test/test-network/conf/dhcp6pd-downstream-dummy99.network
Normal file
@ -0,0 +1,14 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=dummy99
|
||||
|
||||
[Network]
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=no
|
||||
DHCPv6PrefixDelegation=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
Assign=no
|
||||
Announce=no
|
16
test/test-network/conf/dhcp6pd-downstream-test1.network
Normal file
16
test/test-network/conf/dhcp6pd-downstream-test1.network
Normal file
@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=test1
|
||||
|
||||
[Network]
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=no
|
||||
DHCPv6PrefixDelegation=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
SubnetId=0
|
||||
Announce=no
|
||||
Token=eui64
|
||||
Token=::1a:2b:3c:4d
|
@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=veth98-peer
|
||||
|
||||
[Network]
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=yes
|
||||
|
||||
[IPv6AcceptRA]
|
||||
Token=eui64
|
||||
Token=::1a:2b:3c:4e
|
22
test/test-network/conf/dhcp6pd-downstream-veth98.network
Normal file
22
test/test-network/conf/dhcp6pd-downstream-veth98.network
Normal file
@ -0,0 +1,22 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=veth98
|
||||
|
||||
[Network]
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=no
|
||||
DHCPv6PrefixDelegation=yes
|
||||
IPv6SendRA=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
SubnetId=9
|
||||
Announce=yes
|
||||
Token=eui64
|
||||
Token=::1a:2b:3c:4d
|
||||
|
||||
[IPv6SendRA]
|
||||
UplinkInterface=:none
|
||||
EmitDNS=no
|
||||
EmitDomains=no
|
7
test/test-network/conf/dhcp6pd-server.network
Normal file
7
test/test-network/conf/dhcp6pd-server.network
Normal file
@ -0,0 +1,7 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=veth-peer
|
||||
|
||||
[Network]
|
||||
IPv6AcceptRA=no
|
||||
Address=3ffe:501:ffff:100::1/64
|
19
test/test-network/conf/dhcp6pd-upstream.network
Normal file
19
test/test-network/conf/dhcp6pd-upstream.network
Normal file
@ -0,0 +1,19 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=veth99
|
||||
|
||||
[Network]
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=ipv6
|
||||
DHCPv6PrefixDelegation=yes
|
||||
|
||||
[DHCPv6]
|
||||
WithoutRA=solicit
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
UplinkInterface=:self
|
||||
SubnetId=10
|
||||
Announce=no
|
||||
Token=eui64
|
||||
Token=::1a:2b:3c:4d
|
21
test/test-network/conf/isc-dhcpd-dhcp6pd.conf
Normal file
21
test/test-network/conf/isc-dhcpd-dhcp6pd.conf
Normal file
@ -0,0 +1,21 @@
|
||||
default-lease-time 2592000;
|
||||
preferred-lifetime 604800;
|
||||
|
||||
option dhcp-renewal-time 3600;
|
||||
option dhcp-rebinding-time 7200;
|
||||
|
||||
# Enable RFC 5007 support (same than for DHCPv4)
|
||||
allow leasequery;
|
||||
|
||||
option dhcp6.name-servers 3ffe:501:ffff:100:200:ff:fe00:3f3e;
|
||||
option dhcp6.domain-search "test.example.com","example.com";
|
||||
|
||||
option dhcp6.info-refresh-time 21600;
|
||||
|
||||
subnet6 3ffe:501:ffff:100::/64 {
|
||||
# Addresses available to clients
|
||||
range6 3ffe:501:ffff:100::10 3ffe:501:ffff:100::100;
|
||||
|
||||
# Some /64 prefixes available for Prefix Delegation (RFC 3633)
|
||||
prefix6 3ffe:501:ffff:200:: 3ffe:501:ffff:f00:: /56;
|
||||
}
|
@ -14,6 +14,7 @@ import sys
|
||||
import time
|
||||
import unittest
|
||||
from shutil import copytree
|
||||
from pathlib import Path
|
||||
|
||||
network_unit_file_path='/run/systemd/network'
|
||||
networkd_runtime_directory='/run/systemd/netif'
|
||||
@ -26,6 +27,9 @@ dnsmasq_pid_file='/run/networkd-ci/test-dnsmasq.pid'
|
||||
dnsmasq_log_file='/run/networkd-ci/test-dnsmasq.log'
|
||||
dnsmasq_lease_file='/run/networkd-ci/test-dnsmasq.lease'
|
||||
|
||||
isc_dhcpd_pid_file='/run/networkd-ci/test-isc-dhcpd.pid'
|
||||
isc_dhcpd_lease_file='/run/networkd-ci/test-isc-dhcpd.lease'
|
||||
|
||||
systemd_lib_paths=['/usr/lib/systemd', '/lib/systemd']
|
||||
which_paths=':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':'))
|
||||
|
||||
@ -531,6 +535,17 @@ def remove_dnsmasq_log_file():
|
||||
if os.path.exists(dnsmasq_log_file):
|
||||
os.remove(dnsmasq_log_file)
|
||||
|
||||
def start_isc_dhcpd(interface, conf_file):
|
||||
conf_file_path = os.path.join(networkd_ci_path, conf_file)
|
||||
isc_dhcpd_command = f'dhcpd -6 -cf {conf_file_path} -lf {isc_dhcpd_lease_file} -pf {isc_dhcpd_pid_file} {interface}'
|
||||
Path(isc_dhcpd_lease_file).touch()
|
||||
check_output(isc_dhcpd_command)
|
||||
|
||||
def stop_isc_dhcpd():
|
||||
stop_by_pid_file(isc_dhcpd_pid_file)
|
||||
if os.path.exists(isc_dhcpd_lease_file):
|
||||
os.remove(isc_dhcpd_lease_file)
|
||||
|
||||
def remove_networkd_state_files():
|
||||
if os.path.exists(os.path.join(networkd_runtime_directory, 'state')):
|
||||
os.remove(os.path.join(networkd_runtime_directory, 'state'))
|
||||
@ -4846,6 +4861,184 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
||||
print(output)
|
||||
self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
|
||||
|
||||
class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
|
||||
links = [
|
||||
'dummy97',
|
||||
'dummy98',
|
||||
'dummy99',
|
||||
'test1',
|
||||
'veth98',
|
||||
'veth99',
|
||||
]
|
||||
|
||||
units = [
|
||||
'11-dummy.netdev',
|
||||
'12-dummy.netdev',
|
||||
'13-dummy.netdev',
|
||||
'25-veth.netdev',
|
||||
'25-veth-downstream.netdev',
|
||||
'dhcp6pd-downstream-dummy97.network',
|
||||
'dhcp6pd-downstream-dummy98.network',
|
||||
'dhcp6pd-downstream-dummy99.network',
|
||||
'dhcp6pd-downstream-test1.network',
|
||||
'dhcp6pd-downstream-veth98.network',
|
||||
'dhcp6pd-downstream-veth98-peer.network',
|
||||
'dhcp6pd-server.network',
|
||||
'dhcp6pd-upstream.network',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
stop_isc_dhcpd()
|
||||
remove_links(self.links)
|
||||
stop_networkd(show_logs=False)
|
||||
|
||||
def tearDown(self):
|
||||
stop_isc_dhcpd()
|
||||
remove_links(self.links)
|
||||
remove_unit_from_networkd_path(self.units)
|
||||
stop_networkd(show_logs=True)
|
||||
|
||||
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',
|
||||
'11-dummy.netdev', 'dhcp6pd-downstream-test1.network',
|
||||
'dhcp6pd-downstream-dummy97.network',
|
||||
'12-dummy.netdev', 'dhcp6pd-downstream-dummy98.network',
|
||||
'13-dummy.netdev', 'dhcp6pd-downstream-dummy99.network')
|
||||
|
||||
start_networkd()
|
||||
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'])
|
||||
|
||||
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)
|
||||
|
||||
print('### ip -6 address show dev veth99 scope global')
|
||||
output = check_output('ip -6 address show dev veth99 scope global')
|
||||
print(output)
|
||||
# IA_NA
|
||||
self.assertRegex(output, 'inet6 3ffe:501:ffff:100::[0-9]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
|
||||
# address in IA_PD (Token=static)
|
||||
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]10: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]10:1034:56ff:fe78:9abc/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# address in IA_PD (temporary)
|
||||
# Note that the temporary addresses may appear after the link enters configured state
|
||||
self.wait_address('veth99', 'inet6 3ffe:501:ffff:[2-9a-f]10:[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 test1 scope global')
|
||||
output = check_output('ip -6 address show dev test1 scope global')
|
||||
print(output)
|
||||
# address in IA_PD (Token=static)
|
||||
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('test1', '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 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')
|
||||
# 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 veth98 scope global')
|
||||
output = check_output('ip -6 address show dev veth98 scope global')
|
||||
print(output)
|
||||
# address in IA_PD (Token=static)
|
||||
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09: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]09:1034:56ff:fe78:9abe/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# address in IA_PD (temporary)
|
||||
self.wait_address('veth98', '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 veth98-peer scope global')
|
||||
output = check_output('ip -6 address show dev veth98-peer scope global')
|
||||
print(output)
|
||||
# NDisc address (Token=static)
|
||||
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09: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]09:1034:56ff:fe78:9abf/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# 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)
|
||||
self.assertRegex(output, 'unreachable 3ffe:501:ffff:[2-9a-f]00::/56 dev lo proto dhcp')
|
||||
|
||||
print('### ip -6 route show dev veth99')
|
||||
output = check_output('ip -6 route show dev veth99')
|
||||
print(output)
|
||||
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]10::/64 proto kernel metric [0-9]* expires')
|
||||
|
||||
print('### ip -6 route show dev test1')
|
||||
output = check_output('ip -6 route show dev test1')
|
||||
print(output)
|
||||
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/64 proto kernel metric [0-9]* expires')
|
||||
|
||||
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')
|
||||
|
||||
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')
|
||||
|
||||
print('### ip -6 route show dev veth98')
|
||||
output = check_output('ip -6 route show dev veth98')
|
||||
print(output)
|
||||
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]09::/64 proto kernel metric [0-9]* expires')
|
||||
|
||||
print('### ip -6 route show dev veth98-peer')
|
||||
output = check_output('ip -6 route show dev veth98-peer')
|
||||
print(output)
|
||||
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]09::/64 proto ra metric [0-9]* expires')
|
||||
|
||||
# Test case for a downstream which appears later
|
||||
check_output('ip link add dummy97 type dummy')
|
||||
self.wait_online(['dummy97:routable'])
|
||||
|
||||
print('### ip -6 address show dev dummy97 scope global')
|
||||
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')
|
||||
# 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')
|
||||
|
||||
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')
|
||||
|
||||
# Test case for reconfigure
|
||||
check_output(*networkctl_cmd, 'reconfigure', 'dummy98', 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')
|
||||
# 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 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')
|
||||
|
||||
class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
|
||||
links = [
|
||||
'dummy98',
|
||||
|
Loading…
Reference in New Issue
Block a user