]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test-network: improve reliability of test case of DHCPRELEASE message
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 12 Mar 2026 07:48:29 +0000 (16:48 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 12 Mar 2026 19:53:20 +0000 (04:53 +0900)
test/test-network/systemd-networkd-tests.py

index 835f31656e839031f07940dfabab17494cb49b6c..b1754cd80d25b320bae455b95915278dc76cd4cb 100755 (executable)
@@ -7992,27 +7992,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
 
         self.teardown_nftset('addr4', 'network4', 'ifindex')
 
-    def test_dhcp_client_send_release(self):
-        check_output('ip netns add ns-bridge')
-        check_output('ip netns exec ns-bridge ip link add bridge99 type bridge')
-        check_output('ip netns exec ns-bridge ip link set bridge99 address 12:34:56:78:90:ab')
-        check_output('ip netns exec ns-bridge ip link set bridge99 up')
-
-        check_output('ip link add client type veth peer clientp')
-        check_output('ip link set clientp netns ns-bridge')
-        check_output('ip netns exec ns-bridge ip link set clientp master bridge99')
-        check_output('ip netns exec ns-bridge ip link set clientp up')
-
-        check_output('ip link add server type veth peer serverp')
-        check_output('ip link set serverp netns ns-bridge')
-        check_output('ip netns exec ns-bridge ip link set serverp master bridge99')
-        check_output('ip netns exec ns-bridge ip link set serverp up')
-
-        check_output('ip netns add ns-server')
-        check_output('ip link set server netns ns-server')
-        check_output('ip netns exec ns-server ip link set server up')
-        check_output('ip netns exec ns-server ip address add 192.0.2.1/24 dev server')
-
+    def _test_dhcp_client_send_release_one(self) -> bool:
         start_dnsmasq(
             namespace='ns-server',
             interface='server',
@@ -8020,7 +8000,6 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
             ipv4_router='192.0.2.1',
         )
 
-        copy_network_unit('25-dhcp-client-simple.network')
         start_networkd()
         self.wait_online('client:routable')
 
@@ -8038,15 +8017,63 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
 
         networkctl('down', 'client')
 
-        print('## dnsmasq log')
+        success = False
         for _ in range(20):
             time.sleep(0.5)
             output = read_dnsmasq_log_file()
             if 'DHCPRELEASE' in output:
-                print(output)
+                success = True
+                break
+
+        print('## dnsmasq log')
+        print(output)
+
+        return success
+
+    def test_dhcp_client_send_release(self):
+        check_output('ip netns add ns-bridge')
+        check_output('ip netns exec ns-bridge ip link add bridge99 type bridge')
+        check_output('ip netns exec ns-bridge ip link set bridge99 address 12:34:56:78:90:ab')
+        check_output('ip netns exec ns-bridge ip link set bridge99 up')
+
+        check_output('ip link add client type veth peer clientp')
+        check_output('ip link set clientp netns ns-bridge')
+        check_output('ip netns exec ns-bridge ip link set clientp master bridge99')
+        check_output('ip netns exec ns-bridge ip link set clientp up')
+
+        check_output('ip link add server type veth peer serverp')
+        check_output('ip link set serverp netns ns-bridge')
+        check_output('ip netns exec ns-bridge ip link set serverp master bridge99')
+        check_output('ip netns exec ns-bridge ip link set serverp up')
+
+        check_output('ip netns add ns-server')
+        check_output('ip link set server netns ns-server')
+        check_output('ip netns exec ns-server ip link set server up')
+        check_output('ip netns exec ns-server ip address add 192.0.2.1/24 dev server')
+
+        copy_network_unit('25-dhcp-client-simple.network')
+
+        '''
+        Sending DHCPRELEASE is best-effort. Even if send() succeeds, the packet may be dropped later in the
+        networking stack (e.g. due to unresolved neighbor state or interface teardown). Userspace cannot
+        reliably determine whether the packet was eventually transmitted or dropped.
+
+        Hence, the test below may be flaky. In most cases, neighbor resolution completes quickly enough and
+        the packet is transmitted before the interface is brought down. Running the test multiple times
+        should make it sufficiently reliable.
+        '''
+
+        first = True
+        for _ in range(5):
+            if not first:
+                stop_dnsmasq()
+                stop_networkd(show_logs=False)
+
+            first = False
+
+            if self._test_dhcp_client_send_release_one():
                 break
         else:
-            print(output)
             self.fail('Timed out waiting for DHCPRELEASE in dnsmasq log')
 
     def test_dhcp_client_ipv4_dbus_status(self):