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',
ipv4_router='192.0.2.1',
)
- copy_network_unit('25-dhcp-client-simple.network')
start_networkd()
self.wait_online('client:routable')
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):