]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - test/test-network/systemd-networkd-tests.py
test-network: stop dnsmasq before removing links
[thirdparty/systemd.git] / test / test-network / systemd-networkd-tests.py
index 0dcd9cd496afca1f3d6327c96b8e9542ec148785..d809e72abc396942819a99219108bbfc2ae31ed9 100755 (executable)
@@ -142,8 +142,14 @@ class Utilities():
                 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
                     shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
 
-    def start_dnsmasq(self, additional_options='', lease_time='1h'):
-        dnsmasq_command = f'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range=2600::10,2600::20,{lease_time} --dhcp-range=192.168.5.10,192.168.5.200,{lease_time} -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options
+    def warn_about_firewalld(self):
+        rc = subprocess.call(['systemctl', '-q', 'is-active', 'firewalld.service'])
+        if rc == 0:
+            print('\nWARNING: firewalld.service is active. The test may fail.')
+
+    def start_dnsmasq(self, additional_options='', ipv4_range='192.168.5.10,192.168.5.200', ipv6_range='2600::10,2600::20', lease_time='1h'):
+        self.warn_about_firewalld()
+        dnsmasq_command = f'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range={ipv6_range},{lease_time} --dhcp-range={ipv4_range},{lease_time} -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options
         subprocess.check_call(dnsmasq_command, shell=True)
 
         time.sleep(10)
@@ -265,6 +271,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         'vtitun97',
         'vtitun98',
         'vtitun99',
+        'vxcan99',
         'vxlan99',
         'wg98',
         'wg99']
@@ -334,6 +341,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         '25-vti-tunnel-local-any.netdev',
         '25-vti-tunnel-remote-any.netdev',
         '25-vti-tunnel.netdev',
+        '25-vxcan.netdev',
         '25-vxlan.netdev',
         '25-wireguard-23-peers.netdev',
         '25-wireguard-23-peers.network',
@@ -410,8 +418,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.start_networkd(0)
 
         self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
-        self.check_link_exists('bridge99')
-        self.check_link_exists('test1')
 
         self.check_operstate('bridge99', '(?:off|no-carrier)', setup_state='configuring')
         self.check_operstate('test1', 'degraded')
@@ -458,7 +464,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
                                              '21-vlan.network', '21-vlan-test1.network')
         self.start_networkd(0)
 
-        self.wait_online(['test1', 'vlan99'])
+        self.wait_online(['test1:degraded', 'vlan99:routable'])
 
         output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
@@ -570,12 +576,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         print(output)
         self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
 
-    def test_dummy(self):
-        self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
-        self.start_networkd(0)
-
-        self.wait_online(['test1:off'])
-
     def test_tun(self):
         self.copy_unit_to_networkd_unit_path('25-tun.netdev')
         self.start_networkd(0)
@@ -600,10 +600,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
     @expectedFailureIfModuleIsNotAvailable('vrf')
     def test_vrf(self):
-        self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
+        self.copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
         self.start_networkd(0)
 
-        self.wait_online(['vrf99:off'])
+        self.wait_online(['vrf99:carrier'])
 
     @expectedFailureIfModuleIsNotAvailable('vcan')
     def test_vcan(self):
@@ -612,6 +612,13 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
         self.wait_online(['vcan99:carrier'])
 
+    @expectedFailureIfModuleIsNotAvailable('vxcan')
+    def test_vxcan(self):
+        self.copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
+        self.start_networkd(0)
+
+        self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
+
     @expectedFailureIfModuleIsNotAvailable('wireguard')
     def test_wireguard(self):
         self.copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
@@ -644,10 +651,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
             self.assertRegex(output, 'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
 
     def test_geneve(self):
-        self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
+        self.copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
         self.start_networkd(0)
 
-        self.wait_online(['geneve99:off'])
+        self.wait_online(['geneve99:degraded'])
 
         output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99'], universal_newlines=True).rstrip()
         print(output)
@@ -842,9 +849,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.start_networkd(0)
         self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
 
-        self.check_link_exists('dummy98')
-        self.check_link_exists('isataptun99')
-
         output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "isatap ")
@@ -884,10 +888,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'oseq')
 
     def test_tunnel_independent(self):
-        self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
+        self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
         self.start_networkd(0)
 
-        self.wait_online(['ipiptun99:off'])
+        self.wait_online(['ipiptun99:carrier'])
 
     @expectedFailureIfModuleIsNotAvailable('fou')
     def test_fou(self):
@@ -1400,8 +1404,6 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.start_networkd(0)
         self.wait_online(['dummy98:degraded'])
 
-        self.check_link_exists('dummy98')
-
         self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
         self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
         self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
@@ -1420,8 +1422,6 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.start_networkd(0)
         self.wait_online(['dummy98:routable'])
 
-        self.check_link_exists('dummy98')
-
         output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
@@ -1439,8 +1439,6 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.start_networkd(0)
         self.wait_online(['dummy98:routable'])
 
-        self.check_link_exists('dummy98')
-
         output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
@@ -1808,6 +1806,7 @@ class NetworkdNetworkRATests(unittest.TestCase, Utilities):
         self.remove_unit_from_networkd_path(self.units)
 
     def test_ipv6_prefix_delegation(self):
+        self.warn_about_firewalld()
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
         self.start_networkd()
 
@@ -1839,6 +1838,7 @@ class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
         self.remove_unit_from_networkd_path(self.units)
 
     def test_dhcp_server(self):
+        self.warn_about_firewalld()
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
         self.start_networkd()
 
@@ -1864,6 +1864,7 @@ class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'Search Domains: one')
 
     def test_emit_router_timezone(self):
+        self.warn_about_firewalld()
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
         self.start_networkd()
 
@@ -1905,15 +1906,15 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         'static.network']
 
     def setUp(self):
-        self.link_remove(self.links)
         self.stop_dnsmasq(dnsmasq_pid_file)
+        self.link_remove(self.links)
 
     def tearDown(self):
-        self.link_remove(self.links)
-        self.remove_unit_from_networkd_path(self.units)
         self.stop_dnsmasq(dnsmasq_pid_file)
         self.remove_lease_file()
         self.remove_log_file()
+        self.link_remove(self.links)
+        self.remove_unit_from_networkd_path(self.units)
 
     def test_dhcp_client_ipv6_only(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
@@ -2250,6 +2251,54 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet .* scope link')
 
+    def test_dhcp_client_route_remove_on_renew(self):
+        self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
+                                             'dhcp-client-ipv4-only-ipv6-disabled.network')
+        self.start_networkd(0)
+        self.wait_online(['veth-peer:carrier'])
+        self.start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
+        self.wait_online(['veth99:routable', 'veth-peer:routable'])
+
+        # test for issue #12490
+
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
+        print(output)
+        self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
+        address1=None
+        for line in output.splitlines():
+            if 'brd 192.168.5.255 scope global dynamic veth99' in line:
+                address1 = line.split()[1].split('/')[0]
+                break
+
+        output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
+        print(output)
+        self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
+        self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
+
+        self.stop_dnsmasq(dnsmasq_pid_file)
+        self.start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
+
+        print('Wait for the dynamic address to be expired')
+        time.sleep(130)
+
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
+        print(output)
+        self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
+        address2=None
+        for line in output.splitlines():
+            if 'brd 192.168.5.255 scope global dynamic veth99' in line:
+                address2 = line.split()[1].split('/')[0]
+                break
+
+        self.assertNotEqual(address1, address2)
+
+        output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
+        print(output)
+        self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
+        self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
+        self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
+        self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
+
 if __name__ == '__main__':
     unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
                                                      verbosity=3))