Skip to content

Commit

Permalink
smoketest: T5428: check for process running in designated VRF
Browse files Browse the repository at this point in the history
Start IPv4/IPv6 DHCP clients on an interface bound to a given VRF. Verify that
the client process runs in the VRF context.
  • Loading branch information
c-po committed Aug 6, 2023
1 parent d1c4294 commit 710dac5
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 3 deletions.
105 changes: 102 additions & 3 deletions smoketest/scripts/cli/base_interfaces_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@
from vyos.utils.dict import dict_search
from vyos.utils.process import process_named_running
from vyos.utils.network import get_interface_config
from vyos.utils.network import get_interface_vrf
from vyos.utils.process import cmd
from vyos.utils.network import is_intf_addr_assigned
from vyos.utils.network import is_ipv6_link_local
from vyos.xml_ref import cli_defined

dhclient_base_dir = directories['isc_dhclient_dir']
dhclient_process_name = 'dhclient'
dhcp6c_base_dir = directories['dhcp6_client_dir']
dhcp6c_process_name = 'dhcp6c'

def is_mirrored_to(interface, mirror_if, qdisc):
"""
Expand Down Expand Up @@ -69,6 +73,7 @@ class TestCase(VyOSUnitTestSHIM.TestCase):
_test_ipv6_pd = False
_test_ipv6_dhcpc6 = False
_test_mirror = False
_test_vrf = False
_base_path = []

_options = {}
Expand Down Expand Up @@ -96,6 +101,7 @@ def setUpClass(cls):
cls._test_ipv6_dhcpc6 = cli_defined(cls._base_path, 'dhcpv6-options')
cls._test_ipv6_pd = cli_defined(cls._base_path + ['dhcpv6-options'], 'pd')
cls._test_mtu = cli_defined(cls._base_path, 'mtu')
cls._test_vrf = cli_defined(cls._base_path, 'vrf')

# Setup mirror interfaces for SPAN (Switch Port Analyzer)
for span in cls._mirror_interfaces:
Expand Down Expand Up @@ -154,6 +160,99 @@ def test_dhcp_disable_interface(self):
flags = read_file(f'/sys/class/net/{interface}/flags')
self.assertEqual(int(flags, 16) & 1, 0)

def test_dhcp_client_options(self):
if not self._test_dhcp or not self._test_vrf:
self.skipTest('not supported')

distance = '100'

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, 'dhcp-options', 'default-route-distance', distance])

self.cli_commit()

for interface in self._interfaces:
# Check if dhclient process runs
dhclient_pid = process_named_running(dhclient_process_name, cmdline=interface)
self.assertTrue(dhclient_pid)

dhclient_config = read_file(f'{dhclient_base_dir}/dhclient_{interface}.conf')
self.assertIn('request subnet-mask, broadcast-address, routers, domain-name-servers', dhclient_config)
self.assertIn('require subnet-mask;', dhclient_config)

# and the commandline has the appropriate options
cmdline = read_file(f'/proc/{dhclient_pid}/cmdline')
self.assertIn(f'-e\x00IF_METRIC={distance}', cmdline)

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')
Expand Down Expand Up @@ -817,7 +916,7 @@ def test_dhcpv6_client_options(self):
duid_base += 1

# Better ask the process about it's commandline in the future
pid = process_named_running('dhcp6c', cmdline=interface)
pid = process_named_running(dhcp6c_process_name, cmdline=interface)
self.assertTrue(pid)

dhcp6c_options = read_file(f'/proc/{pid}/cmdline')
Expand Down Expand Up @@ -876,7 +975,7 @@ def test_dhcpv6pd_auto_sla_id(self):
address = str(int(address) + 1)

# Check for running process
self.assertTrue(process_named_running('dhcp6c', cmdline=interface))
self.assertTrue(process_named_running(dhcp6c_process_name, cmdline=interface))

for delegatee in delegatees:
# we can already cleanup the test delegatee interface here
Expand Down Expand Up @@ -942,7 +1041,7 @@ def test_dhcpv6pd_manual_sla_id(self):
address = str(int(address) + 1)

# Check for running process
self.assertTrue(process_named_running('dhcp6c', cmdline=interface))
self.assertTrue(process_named_running(dhcp6c_process_name, cmdline=interface))

for delegatee in delegatees:
# we can already cleanup the test delegatee interface here
Expand Down
File renamed without changes.
File renamed without changes.

0 comments on commit 710dac5

Please sign in to comment.