From 46f2eb517ccfcd03bfdafee8761bec655608c974 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 6 Oct 2023 14:11:07 +0900 Subject: [PATCH] test-network: add tests for DHCP IPv6 only mode For [DHCPv4] IPv6OnlyMode= and [DHCPServer] IPv6OnlyPreferredSec=. --- .../25-dhcp-client-ipv6-only-mode.network | 10 ++++ .../conf/25-dhcp-client-ipv6-only.network | 3 +- .../25-dhcp-server-ipv6-only-mode.network | 16 ++++++ test/test-network/systemd-networkd-tests.py | 49 ++++++++++++++++--- 4 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 test/test-network/conf/25-dhcp-client-ipv6-only-mode.network create mode 100644 test/test-network/conf/25-dhcp-server-ipv6-only-mode.network diff --git a/test/test-network/conf/25-dhcp-client-ipv6-only-mode.network b/test/test-network/conf/25-dhcp-client-ipv6-only-mode.network new file mode 100644 index 00000000000..21a6bc7eedd --- /dev/null +++ b/test/test-network/conf/25-dhcp-client-ipv6-only-mode.network @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + +[DHCPv4] +IPv6OnlyMode=yes diff --git a/test/test-network/conf/25-dhcp-client-ipv6-only.network b/test/test-network/conf/25-dhcp-client-ipv6-only.network index 017f76f4d58..4aba206cb4b 100644 --- a/test/test-network/conf/25-dhcp-client-ipv6-only.network +++ b/test/test-network/conf/25-dhcp-client-ipv6-only.network @@ -3,7 +3,8 @@ Name=veth99 [Network] -DHCP=ipv6 +# DHCPv4 is also enabled here, but will be stopped when an IPv6 address is acquired. +DHCP=yes IPv6Token=::1a:2b:3c:4d [Route] diff --git a/test/test-network/conf/25-dhcp-server-ipv6-only-mode.network b/test/test-network/conf/25-dhcp-server-ipv6-only-mode.network new file mode 100644 index 00000000000..cb19e74a698 --- /dev/null +++ b/test/test-network/conf/25-dhcp-server-ipv6-only-mode.network @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=veth-peer + +[Network] +IPv6AcceptRA=false +DHCPServer=yes + +[DHCPServer] +ServerAddress=192.168.5.1/24 +PoolOffset=10 +PoolSize=50 +Router=192.168.5.3 +DNS=_server_address 192.168.5.10 +NTP=_server_address 192.168.5.11 +IPv6OnlyPreferredSec=20s diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 1496a615fe4..f0b248917ce 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -770,7 +770,11 @@ def setUpModule(): save_timezone() create_service_dropin('systemd-networkd', networkd_bin, - ['[Service]', 'Restart=no', '[Unit]', 'StartLimitIntervalSec=0']) + ['[Service]', + 'Restart=no', + 'Environment=SYSTEMD_NETWORK_TEST_MODE=yes', + '[Unit]', + 'StartLimitIntervalSec=0']) create_service_dropin('systemd-resolved', resolved_bin) create_service_dropin('systemd-timesyncd', timesyncd_bin) @@ -5110,7 +5114,10 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth-peer:carrier']) # information request mode - start_dnsmasq('--dhcp-option=option6:dns-server,[2600::ee]', + # The name ipv6-only option may not be supported by older dnsmasq + # start_dnsmasq('--dhcp-option=option:ipv6-only,300') + start_dnsmasq('--dhcp-option=108,00:00:02:00', + '--dhcp-option=option6:dns-server,[2600::ee]', '--dhcp-option=option6:ntp-server,[2600::ff]', ra_mode='ra-stateless') self.wait_online(['veth99:routable', 'veth-peer:routable']) @@ -5140,7 +5147,8 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): # solicit mode stop_dnsmasq() - start_dnsmasq('--dhcp-option=option6:dns-server,[2600::ee]', + start_dnsmasq('--dhcp-option=108,00:00:02:00', + '--dhcp-option=option6:dns-server,[2600::ee]', '--dhcp-option=option6:ntp-server,[2600::ff]') networkctl_reconfigure('veth99') self.wait_online(['veth99:routable', 'veth-peer:routable']) @@ -5189,7 +5197,8 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): f.write('\n[DHCPv6]\nRapidCommit=no\n') stop_dnsmasq() - start_dnsmasq('--dhcp-option=option6:dns-server,[2600::ee]', + start_dnsmasq('--dhcp-option=108,00:00:02:00', + '--dhcp-option=option6:dns-server,[2600::ee]', '--dhcp-option=option6:ntp-server,[2600::ff]') networkctl_reload() @@ -5238,16 +5247,30 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): # Note that at this point the DHCPv6 client has not been started because no RA (with managed # bit set) has yet been received and the configuration does not include WithoutRA=true state = get_dhcp6_client_state('veth99') - print(f"State = {state}") + print(f"DHCPv6 client state = {state}") self.assertEqual(state, 'stopped') - start_dnsmasq() + state = get_dhcp4_client_state('veth99') + print(f"DHCPv4 client state = {state}") + self.assertEqual(state, 'selecting') + + start_dnsmasq('--dhcp-option=108,00:00:02:00') self.wait_online(['veth99:routable', 'veth-peer:routable']) state = get_dhcp6_client_state('veth99') - print(f"State = {state}") + print(f"DHCPv6 client state = {state}") self.assertEqual(state, 'bound') + # DHCPv4 client will stop after an DHCPOFFER message received, so we need to wait for a while. + for _ in range(100): + state = get_dhcp4_client_state('veth99') + if state == 'stopped': + break + time.sleep(.2) + + print(f"DHCPv4 client state = {state}") + self.assertEqual(state, 'stopped') + def test_dhcp_client_ipv6_only_with_custom_client_identifier(self): copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv6-only-custom-client-identifier.network') @@ -5493,6 +5516,18 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): print(f"State = {state}") self.assertEqual(state, 'bound') + def test_dhcp_client_ipv6_only_mode_without_ipv6_connectivity(self): + copy_network_unit('25-veth.netdev', + '25-dhcp-server-ipv6-only-mode.network', + '25-dhcp-client-ipv6-only-mode.network') + start_networkd() + self.wait_online(['veth99:routable', 'veth-peer:routable'], timeout='40s') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24', ipv='-4') + + state = get_dhcp4_client_state('veth99') + print(f"State = {state}") + self.assertEqual(state, 'bound') + def test_dhcp_client_ipv4_use_routes_gateway(self): first = True for (routes, gateway, dns_and_ntp_routes, classless) in itertools.product([True, False], repeat=4): -- 2.47.3