Skip to content

Commit

Permalink
Add tor_mux_intfs fixture and use it in dual tor mock utility (#3094)
Browse files Browse the repository at this point in the history
The dual tor mock utilities needs to get the list of interfaces connected to mux
cable multiple times. Each time the config_facts module is executed to get the
running config. Then the list of interfaces is parsed from config facts. This is
inefficient and unnecessarily generated too much log while getting config facts.

This change introduced a common fixture tor_mux_intfs. The dual tor mock
utility script is updated to use this new fixture.

Another change is to use shell_cmds to run multiple commands in batch to save
test execution time.

Signed-off-by: Xin Wang <[email protected]>
  • Loading branch information
wangxin authored Mar 5, 2021
1 parent 6429d31 commit 60d73a0
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 29 deletions.
52 changes: 28 additions & 24 deletions tests/common/dualtor/dual_tor_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from ipaddress import ip_interface, IPv4Interface, IPv6Interface, \
ip_address, IPv4Address

from tests.common.dualtor.dual_tor_utils import tor_mux_intfs

__all__ = ['apply_active_state_to_orchagent', 'apply_dual_tor_neigh_entries', 'apply_dual_tor_peer_switch_route', 'apply_mock_dual_tor_kernel_configs',
'apply_mock_dual_tor_tables', 'apply_mux_cable_table_to_dut', 'apply_peer_switch_table_to_dut', 'apply_standby_state_to_orchagent', 'apply_tunnel_table_to_dut',
'mock_peer_switch_loopback_ip', 'mock_server_base_ip_addr']
Expand Down Expand Up @@ -38,7 +40,7 @@ def _apply_config_to_swss(dut, swss_config_str, swss_filename='swss_config_file'
dut.shell('docker exec swss sh -c "swssconfig {}"'.format(swss_filename))


def _apply_dual_tor_state_to_orchagent(dut, state):
def _apply_dual_tor_state_to_orchagent(dut, state, tor_mux_intfs):
'''
Helper function to configure active/standby state in orchagent
Expand All @@ -49,11 +51,9 @@ def _apply_dual_tor_state_to_orchagent(dut, state):

logger.info("Applying {} state to orchagent".format(state))

vlan_intfs = sorted(dut.get_vlan_intfs(), key=lambda intf: int(intf.replace('Ethernet', '')))

intf_configs = []

for intf in vlan_intfs:
for intf in tor_mux_intfs:
'''
For each VLAN interface, create one configuration to be applied to orchagent
Each interface configuration has the following structure:
Expand Down Expand Up @@ -92,18 +92,18 @@ def _apply_dual_tor_state_to_orchagent(dut, state):


@pytest.fixture(scope='module')
def apply_active_state_to_orchagent(rand_selected_dut):
def apply_active_state_to_orchagent(rand_selected_dut, tor_mux_intfs):
dut = rand_selected_dut

for func in _apply_dual_tor_state_to_orchagent(dut, 'active'):
for func in _apply_dual_tor_state_to_orchagent(dut, 'active', tor_mux_intfs):
yield func


@pytest.fixture(scope='module')
def apply_standby_state_to_orchagent(rand_selected_dut):
def apply_standby_state_to_orchagent(rand_selected_dut, tor_mux_intfs):
dut = rand_selected_dut

for func in _apply_dual_tor_state_to_orchagent(dut, 'standby'):
for func in _apply_dual_tor_state_to_orchagent(dut, 'standby', tor_mux_intfs):
yield func


Expand Down Expand Up @@ -165,7 +165,7 @@ def mock_server_base_ip_addr(rand_selected_dut):


@pytest.fixture(scope='module')
def apply_dual_tor_neigh_entries(rand_selected_dut, ptfadapter, tbinfo, mock_server_base_ip_addr):
def apply_dual_tor_neigh_entries(rand_selected_dut, ptfadapter, tbinfo, mock_server_base_ip_addr, tor_mux_intfs):
'''
Apply neighber table entries for servers
'''
Expand All @@ -177,10 +177,9 @@ def apply_dual_tor_neigh_entries(rand_selected_dut, ptfadapter, tbinfo, mock_ser

server_ip_to_mac_map = {}

vlan_intfs = sorted(dut.get_vlan_intfs(), key=lambda intf: int(intf.replace('Ethernet', '')))
dut_ptf_intf_map = dut.get_extended_minigraph_facts(tbinfo)['minigraph_ptf_indices']

for i, intf in enumerate(vlan_intfs):
for i, intf in enumerate(tor_mux_intfs):
# For each VLAN interface, get the corresponding PTF interface MAC
ptf_port_index = dut_ptf_intf_map[intf]
ptf_mac = ptfadapter.dataplane.ports[(0, ptf_port_index)].mac()
Expand All @@ -189,17 +188,21 @@ def apply_dual_tor_neigh_entries(rand_selected_dut, ptfadapter, tbinfo, mock_ser
vlan_interface = dut.get_running_config_facts()['VLAN_INTERFACE']
vlan = list(vlan_interface.keys())[0]

cmds = []
for ip, mac in server_ip_to_mac_map.items():
# Use `ip neigh replace` in case entries already exist for the target IP
# If there are no pre-existing entries, equivalent to `ip neigh add`
dut.shell('ip -4 neigh replace {} lladdr {} dev {}'.format(ip, mac, vlan))
cmds.append('ip -4 neigh replace {} lladdr {} dev {}'.format(ip, mac, vlan))
dut.shell_cmds(cmds=cmds)

yield

logger.info("Removing dual ToR neighbor entries")

cmds = []
for ip in server_ip_to_mac_map.keys():
dut.shell('ip -4 neigh del {} dev {}'.format(ip, vlan))
cmds.append('ip -4 neigh del {} dev {}'.format(ip, vlan))
dut.shell_cmds(cmds=cmds)


@pytest.fixture(scope='module')
Expand All @@ -210,7 +213,7 @@ def apply_dual_tor_peer_switch_route(rand_selected_dut, mock_peer_switch_loopbac
logger.info("Applying dual ToR peer switch loopback route")
dut = rand_selected_dut
bgp_neighbors = dut.bgp_facts()['ansible_facts']['bgp_neighbors'].keys()

ipv4_neighbors = []

for neighbor in bgp_neighbors:
Expand Down Expand Up @@ -250,7 +253,7 @@ def apply_peer_switch_table_to_dut(rand_selected_dut, mock_peer_switch_loopback_
dut.shell('redis-cli -n 4 HSET "{}" "{}" "{}"'.format(device_meta_key, 'subtype', 'dualToR'))
dut.shell('redis-cli -n 4 HSET "{}" "{}" "{}"'.format(device_meta_key, 'peer_switch', peer_switch_hostname))

yield
yield
logger.info("Removing peer switch table")

dut.shell('redis-cli -n 4 DEL "{}"'.format(peer_switch_key))
Expand Down Expand Up @@ -288,7 +291,7 @@ def apply_tunnel_table_to_dut(rand_selected_dut, mock_peer_switch_loopback_ip):


@pytest.fixture(scope='module')
def apply_mux_cable_table_to_dut(rand_selected_dut, mock_server_base_ip_addr):
def apply_mux_cable_table_to_dut(rand_selected_dut, mock_server_base_ip_addr, tor_mux_intfs):
'''
Adds the MUX_CABLE table to config DB
'''
Expand All @@ -297,25 +300,26 @@ def apply_mux_cable_table_to_dut(rand_selected_dut, mock_server_base_ip_addr):

server_ipv4_base_addr, server_ipv6_base_addr = mock_server_base_ip_addr

vlan_intfs = sorted(dut.get_vlan_intfs(), key=lambda intf: int(intf.replace('Ethernet', '')))

keys_inserted = []

for i, intf in enumerate(vlan_intfs):
cmds = []
for i, intf in enumerate(tor_mux_intfs):
server_ipv4 = str(server_ipv4_base_addr + i)
server_ipv6 = str(server_ipv6_base_addr + i)
key = 'MUX_CABLE|{}'.format(intf)
keys_inserted.append(key)

dut.shell('redis-cli -n 4 HSET "{}" "server_ipv4" "{}"'.format(key, server_ipv4))
dut.shell('redis-cli -n 4 HSET "{}" "server_ipv6" "{}"'.format(key, server_ipv6))
dut.shell('redis-cli -n 4 HSET "{}" "state" "auto"'.format(key))
cmds.append('redis-cli -n 4 HSET "{}" "server_ipv4" "{}"'.format(key, server_ipv4))
cmds.append('redis-cli -n 4 HSET "{}" "server_ipv6" "{}"'.format(key, server_ipv6))
cmds.append('redis-cli -n 4 HSET "{}" "state" "auto"'.format(key))
dut.shell_cmds(cmds=cmds)

yield
logger.info("Removing mux cable table")

cmds = []
for key in keys_inserted:
dut.shell('redis-cli -n 4 DEL "{}"'.format(key))
cmds.append('redis-cli -n 4 DEL "{}"'.format(key))
dut.shell_cmds(cmds=cmds)


@pytest.fixture(scope='module')
Expand Down
22 changes: 17 additions & 5 deletions tests/common/dualtor/dual_tor_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,31 @@
from tests.common.helpers.dut_ports import encode_dut_port_name
from tests.common.dualtor.constants import UPPER_TOR, LOWER_TOR

__all__ = ['tor_mux_intf', 'ptf_server_intf', 't1_upper_tor_intfs', 't1_lower_tor_intfs', 'upper_tor_host', 'lower_tor_host']
__all__ = ['tor_mux_intf', 'tor_mux_intfs', 'ptf_server_intf', 't1_upper_tor_intfs', 't1_lower_tor_intfs', 'upper_tor_host', 'lower_tor_host']

logger = logging.getLogger(__name__)


def get_tor_mux_intfs(duthost):
return sorted(duthost.get_vlan_intfs(), key=lambda intf: int(intf.replace('Ethernet', '')))


@pytest.fixture(scope='session')
def tor_mux_intf(duthosts):
def tor_mux_intfs(duthosts):
'''
Returns the server-facing interface on the ToR to be used for testing
Returns the server-facing interfaces on the ToR to be used for testing
'''
# The same ports on both ToRs should be connected to the same PTF port
dut = duthosts[0]
return sorted(dut.get_vlan_intfs(), key=lambda intf: int(intf.replace('Ethernet', '')))[0]
return get_tor_mux_intfs(duthosts[0])


@pytest.fixture(scope='session')
def tor_mux_intf(tor_mux_intfs):
'''
Returns the first server-facing interface on the ToR to be used for testing
'''
# The same ports on both ToRs should be connected to the same PTF port
return tor_mux_intfs[0]


@pytest.fixture(scope='session')
Expand Down

0 comments on commit 60d73a0

Please sign in to comment.