From: Yu Watanabe Date: Mon, 6 Dec 2021 00:03:54 +0000 (+0900) Subject: test-network: add test for 6rd X-Git-Tag: v250-rc1~34^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=84cc85f9837dbe3df93979c6a824aff784a398be;p=thirdparty%2Fsystemd.git test-network: add test for 6rd --- diff --git a/test/test-network/conf/dhcp4-6rd-server.network b/test/test-network/conf/dhcp4-6rd-server.network new file mode 100644 index 00000000000..91dc71a2552 --- /dev/null +++ b/test/test-network/conf/dhcp4-6rd-server.network @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=veth-peer + +[Network] +IPv6AcceptRA=no +Address=10.0.0.1/8 diff --git a/test/test-network/conf/dhcp4-6rd-upstream.network b/test/test-network/conf/dhcp4-6rd-upstream.network new file mode 100644 index 00000000000..e146337c5e4 --- /dev/null +++ b/test/test-network/conf/dhcp4-6rd-upstream.network @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=veth99 + +[Network] +IPv6PrivacyExtensions=yes +IPv6AcceptRA=no +DHCP=ipv4 +DHCPPrefixDelegation=yes + +[DHCPv4] +Use6RD=yes + +[DHCPPrefixDelegation] +UplinkInterface=:self +SubnetId=10 +Announce=no +Token=eui64 +Token=::1a:2b:3c:4d diff --git a/test/test-network/conf/isc-dhcpd-6rd.conf b/test/test-network/conf/isc-dhcpd-6rd.conf new file mode 100644 index 00000000000..0b32f4b696b --- /dev/null +++ b/test/test-network/conf/isc-dhcpd-6rd.conf @@ -0,0 +1,22 @@ +default-lease-time 2592000; +preferred-lifetime 604800; + +default-lease-time 600; +max-lease-time 7200; + +option domain-name-servers 10.0.0.2; +option domain-search "test.example.com","example.com"; + +# ipv4masklen = 8 +# 6rd prefix = 2001:db8::/32 +# BR address = 10.0.0.1 +option option-6rd code 212 = { + integer 8, integer 8, ip6-address, array of ip-address +}; + +option option-6rd 8 32 2001:db8:: 10.0.0.1; + +subnet 10.0.0.0 netmask 255.0.0.0 { + # Addresses available to clients + range 10.100.100.100 10.100.100.199; +} diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index f6c91ea9695..57acd27f849 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -5020,6 +5020,8 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities): 'dhcp-pd-downstream-veth97-peer.network', 'dhcp-pd-downstream-veth98.network', 'dhcp-pd-downstream-veth98-peer.network', + 'dhcp4-6rd-server.network', + 'dhcp4-6rd-upstream.network', 'dhcp6pd-server.network', 'dhcp6pd-upstream.network', ] @@ -5229,6 +5231,241 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities): print(output) self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto dhcp metric [0-9]* expires') + def test_dhcp4_6rd(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp4-6rd-server.network', 'dhcp4-6rd-upstream.network', + '25-veth-downstream-veth97.netdev', 'dhcp-pd-downstream-veth97.network', 'dhcp-pd-downstream-veth97-peer.network', + '25-veth-downstream-veth98.netdev', 'dhcp-pd-downstream-veth98.network', 'dhcp-pd-downstream-veth98-peer.network', + '11-dummy.netdev', 'dhcp-pd-downstream-test1.network', + 'dhcp-pd-downstream-dummy97.network', + '12-dummy.netdev', 'dhcp-pd-downstream-dummy98.network', + '13-dummy.netdev', 'dhcp-pd-downstream-dummy99.network') + + start_networkd() + self.wait_online(['veth-peer:routable']) + start_isc_dhcpd('veth-peer', 'isc-dhcpd-6rd.conf', ip='-4') + self.wait_online(['veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded', + 'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable']) + + print('### ip -4 address show dev veth-peer scope global') + output = check_output('ip -4 address show dev veth-peer scope global') + print(output) + self.assertIn('inet 10.0.0.1/8 brd 10.255.255.255 scope global veth-peer', 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 -4 address show dev veth99 scope global') + output = check_output('ip -4 address show dev veth99 scope global') + print(output) + self.assertRegex(output, 'inet 10.100.100.[0-9]*/8 (metric 1024 |)brd 10.255.255.255 scope global dynamic veth99') + + print('### ip -6 address show dev veth99 scope global') + output = check_output('ip -6 address show dev veth99 scope global') + print(output) + # address in IA_PD (Token=static) + self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+10:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') + # address in IA_PD (Token=eui64) + self.assertRegex(output, 'inet6 2001:db8:6464:[0-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 2001:db8:6464:[0-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 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('test1', '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 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 2001:db8:6464:[0-9a-f]+02: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') + + 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]+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 2001:db8:6464:[0-9a-f]+08:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') + # address in IA_PD (Token=eui64) + self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1034:56ff:fe78:9ace/64 (metric 256 |)scope global dynamic mngtmpaddr') + # address in IA_PD (temporary) + self.wait_address('veth97', 'inet6 2001:db8:6464:[0-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 2001:db8:6464:[0-9a-f]+08:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr') + # NDisc address (Token=eui64) + self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1034:56ff:fe78:9acf/64 (metric 256 |)scope global dynamic mngtmpaddr') + # NDisc address (temporary) + self.wait_address('veth97-peer', 'inet6 2001:db8:6464:[0-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) + # address in IA_PD (Token=static) + self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') + # address in IA_PD (Token=eui64) + self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1034:56ff:fe78:9abe/64 (metric 256 |)scope global dynamic mngtmpaddr') + # address in IA_PD (temporary) + self.wait_address('veth98', 'inet6 2001:db8:6464:[0-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 2001:db8:6464:[0-9a-f]+09:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr') + # NDisc address (Token=eui64) + self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1034:56ff:fe78:9abf/64 (metric 256 |)scope global dynamic mngtmpaddr') + # NDisc address (temporary) + self.wait_address('veth98-peer', 'inet6 2001:db8:6464:[0-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 route show type unreachable') + output = check_output('ip -6 route show type unreachable') + print(output) + self.assertRegex(output, 'unreachable 2001:db8:6464:[0-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, '2001:db8:6464:[0-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, '2001:db8:6464:[0-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, '2001:db8:6464:[0-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, '2001:db8:6464:[0-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, '2001:db8:6464:[0-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, '2001:db8:6464:[0-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') + print(output) + self.assertRegex(output, '2001:db8:6464:[0-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, '2001:db8:6464:[0-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 2001:db8:6464:[0-9a-f]+01:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') + # address in IA_PD (temporary) + self.wait_address('dummy97', 'inet6 2001:db8:6464:[0-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, '2001:db8:6464:[0-9a-f]+01::/64 proto kernel metric [0-9]* expires') + + # Test case for reconfigure + 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 2001:db8:6464:[0-9a-f]+02: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') + + 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]+03') + + 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') + + 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]+03::/64 proto dhcp metric [0-9]* expires') + + tunnel_name = None + for name in os.listdir('/sys/class/net/'): + if name.startswith('6rd-'): + tunnel_name = name + break + + self.wait_online(['{}:routable'.format(tunnel_name)]) + + print('### ip -d link show dev {}'.format(tunnel_name)) + output = check_output('ip -d link show dev {}'.format(tunnel_name)) + print(output) + self.assertIn('link/sit 10.100.100.', output) + self.assertIn('local 10.100.100.', output) + self.assertIn('dev veth99', output) + self.assertIn('ttl 64', output) + self.assertIn('6rd-prefix 2001:db8::/32', output) + self.assertIn('6rd-relay_prefix 10.0.0.0/8', output) + + 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]+00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/56 (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]+00::/56 proto kernel metric [0-9]* expires') + self.assertRegex(output, '::/96 proto kernel metric [0-9]*') + + print('### ip -6 route show default') + output = check_output('ip -6 route show default') + print(output) + self.assertIn('default', output) + self.assertIn('via ::10.0.0.1 dev {}'.format(tunnel_name), output) + class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities): links = [ 'dummy98',