From 47d9c8067135b97bc1fbc5450dc5fa9b8e65e345 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Mon, 28 Aug 2023 21:21:14 +0200 Subject: T5428: fix DHCP address renewal/release when running in VRF --- smoketest/scripts/cli/base_interfaces_test.py | 73 ++++++++++++++++++++++- smoketest/scripts/cli/test_interfaces_bonding.py | 1 + smoketest/scripts/cli/test_interfaces_bridge.py | 1 + smoketest/scripts/cli/test_interfaces_ethernet.py | 1 + 4 files changed, 75 insertions(+), 1 deletion(-) (limited to 'smoketest') diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py index 856471c94..499c5fa9b 100644 --- a/smoketest/scripts/cli/base_interfaces_test.py +++ b/smoketest/scripts/cli/base_interfaces_test.py @@ -33,9 +33,13 @@ from vyos.util import cmd from vyos.util import dict_search from vyos.util import process_named_running from vyos.util import get_interface_config +from vyos.util import get_interface_vrf from vyos.validate import is_intf_addr_assigned from vyos.validate import is_ipv6_link_local +dhclient_process_name = 'dhclient' +dhcp6c_process_name = 'dhcp6c' + def is_mirrored_to(interface, mirror_if, qdisc): """ Ask TC if we are mirroring traffic to a discrete interface. @@ -65,6 +69,7 @@ class BasicInterfaceTest: _test_ipv6_pd = False _test_ipv6_dhcpc6 = False _test_mirror = False + _test_vrf = False _base_path = [] _options = {} @@ -98,7 +103,7 @@ class BasicInterfaceTest: self.assertNotIn(intf, interfaces()) # No daemon that was started during a test should remain running - for daemon in ['dhcp6c', 'dhclient']: + for daemon in [dhclient_process_name, dhcp6c_process_name]: self.assertFalse(process_named_running(daemon)) def test_dhcp_disable_interface(self): @@ -126,6 +131,71 @@ class BasicInterfaceTest: flags = read_file(f'/sys/class/net/{interface}/flags') self.assertEqual(int(flags, 16) & 1, 0) + def test_dhcp_vrf(self): + if not self._test_dhcp or not self._test_vrf: + self.skipTest('not supported') + + vrf_name = 'purple4' + self.cli_set(['vrf', 'name', vrf_name, 'table', '65000']) + + for interface in self._interfaces: + for option in self._options.get(interface, []): + self.cli_set(self._base_path + [interface] + option.split()) + + self.cli_set(self._base_path + [interface, 'address', 'dhcp']) + self.cli_set(self._base_path + [interface, 'vrf', vrf_name]) + + self.cli_commit() + + # Validate interface state + for interface in self._interfaces: + tmp = get_interface_vrf(interface) + self.assertEqual(tmp, vrf_name) + + # Check if dhclient process runs + dhclient_pid = process_named_running(dhclient_process_name, cmdline=interface) + self.assertTrue(dhclient_pid) + # .. inside the appropriate VRF instance + vrf_pids = cmd(f'ip vrf pids {vrf_name}') + self.assertIn(str(dhclient_pid), vrf_pids) + # and the commandline has the appropriate options + cmdline = read_file(f'/proc/{dhclient_pid}/cmdline') + self.assertIn('-e\x00IF_METRIC=210', cmdline) # 210 is the default value + + self.cli_delete(['vrf', 'name', vrf_name]) + + def test_dhcpv6_vrf(self): + if not self._test_ipv6_dhcpc6 or not self._test_vrf: + self.skipTest('not supported') + + vrf_name = 'purple6' + self.cli_set(['vrf', 'name', vrf_name, 'table', '65001']) + + # When interface is configured as admin down, it must be admin down + # even when dhcpc starts on the given interface + for interface in self._interfaces: + for option in self._options.get(interface, []): + self.cli_set(self._base_path + [interface] + option.split()) + + self.cli_set(self._base_path + [interface, 'address', 'dhcpv6']) + self.cli_set(self._base_path + [interface, 'vrf', vrf_name]) + + self.cli_commit() + + # Validate interface state + for interface in self._interfaces: + tmp = get_interface_vrf(interface) + self.assertEqual(tmp, vrf_name) + + # Check if dhclient process runs + tmp = process_named_running(dhcp6c_process_name, cmdline=interface) + self.assertTrue(tmp) + # .. inside the appropriate VRF instance + vrf_pids = cmd(f'ip vrf pids {vrf_name}') + self.assertIn(str(tmp), vrf_pids) + + self.cli_delete(['vrf', 'name', vrf_name]) + def test_span_mirror(self): if not self._mirror_interfaces: self.skipTest('not supported') @@ -725,3 +795,4 @@ class BasicInterfaceTest: # as until commit() is called, nothing happens section = Section.section(delegatee) self.cli_delete(['interfaces', section, delegatee]) + diff --git a/smoketest/scripts/cli/test_interfaces_bonding.py b/smoketest/scripts/cli/test_interfaces_bonding.py index ab75cdcc9..5617c30b7 100755 --- a/smoketest/scripts/cli/test_interfaces_bonding.py +++ b/smoketest/scripts/cli/test_interfaces_bonding.py @@ -29,6 +29,7 @@ class BondingInterfaceTest(BasicInterfaceTest.TestCase): @classmethod def setUpClass(cls): cls._test_dhcp = True + cls._test_vrf = True cls._test_ip = True cls._test_ipv6 = True cls._test_ipv6_pd = True diff --git a/smoketest/scripts/cli/test_interfaces_bridge.py b/smoketest/scripts/cli/test_interfaces_bridge.py index 884fa5c6b..5a2eeb3df 100755 --- a/smoketest/scripts/cli/test_interfaces_bridge.py +++ b/smoketest/scripts/cli/test_interfaces_bridge.py @@ -33,6 +33,7 @@ class BridgeInterfaceTest(BasicInterfaceTest.TestCase): @classmethod def setUpClass(cls): cls._test_dhcp = True + cls._test_vrf = True cls._test_ip = True cls._test_ipv6 = True cls._test_ipv6_pd = True diff --git a/smoketest/scripts/cli/test_interfaces_ethernet.py b/smoketest/scripts/cli/test_interfaces_ethernet.py index b45b29917..5832c4177 100755 --- a/smoketest/scripts/cli/test_interfaces_ethernet.py +++ b/smoketest/scripts/cli/test_interfaces_ethernet.py @@ -38,6 +38,7 @@ class EthernetInterfaceTest(BasicInterfaceTest.TestCase): @classmethod def setUpClass(cls): cls._test_dhcp = True + cls._test_vrf = True cls._test_ip = True cls._test_ipv6 = True cls._test_ipv6_pd = True -- cgit v1.2.3