diff --git a/tests/common/snappi_tests/common_helpers.py b/tests/common/snappi_tests/common_helpers.py index 3f3e7a5eae8..6175b63c7f5 100644 --- a/tests/common/snappi_tests/common_helpers.py +++ b/tests/common/snappi_tests/common_helpers.py @@ -10,7 +10,10 @@ in .csv format etc. """ +from argparse import ArgumentParser from enum import Enum +from functools import lru_cache +import sys import ipaddr import json import re @@ -20,6 +23,7 @@ from random import getrandbits from tests.common.portstat_utilities import parse_portstat from collections import defaultdict +from tests.conftest import parse_override def increment_ip_address(ip, incr=1): @@ -1237,3 +1241,19 @@ def get_pfc_count(duthost, port): pfc_dict[duthost.hostname][port]['rx_pfc_'+str(m-1)] = int(pause_frame_count[m].replace(',', '')) return pfc_dict + + +def get_pfcQueueGroupSize(default=8): + testbed_name = get_testbed_from_args() + is_override, override_data = parse_override(testbed_name, 'pfcQueueGroupSize') + if is_override: + return override_data + return default + + +@lru_cache +def get_testbed_from_args(): + parser = ArgumentParser() + parser.add_argument("--testbed") + args, _ = parser.parse_known_args(sys.argv[1:]) + return args.testbed diff --git a/tests/common/snappi_tests/snappi_fixtures.py b/tests/common/snappi_tests/snappi_fixtures.py index 24b8b70a86c..255b9833235 100755 --- a/tests/common/snappi_tests/snappi_fixtures.py +++ b/tests/common/snappi_tests/snappi_fixtures.py @@ -12,7 +12,7 @@ from ipaddress import ip_address, IPv4Address, IPv6Address from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts # noqa: F401 from tests.common.snappi_tests.common_helpers import get_addrs_in_subnet, get_peer_snappi_chassis, \ - get_ipv6_addrs_in_subnet + get_ipv6_addrs_in_subnet, parse_override from tests.common.snappi_tests.snappi_helpers import SnappiFanoutManager, get_snappi_port_location from tests.common.snappi_tests.port import SnappiPortConfig, SnappiPortType from tests.common.helpers.assertions import pytest_assert @@ -1365,7 +1365,8 @@ def snappi_port_selection(get_snappi_ports, number_of_tx_rx_ports, mixed_speed=N Example: {'100':{'single-linecard-single-asic':{ports}, 'single-linecard-multiple-asic':{ports}}} ''' - tx_port_count, rx_port_count = number_of_tx_rx_ports + # Reverse this here since this is more like on the DUT perspective + rx_port_count, tx_port_count = number_of_tx_rx_ports tmp_snappi_port_list = get_snappi_ports if (not mixed_speed): @@ -1532,18 +1533,59 @@ def snappi_port_selection(get_snappi_ports, number_of_tx_rx_ports, mixed_speed=N @pytest.fixture(scope="function") -def tgen_port_info(request, snappi_port_selection): +def tgen_port_info(request: pytest.FixtureRequest, snappi_port_selection, get_snappi_ports, + number_of_tx_rx_ports, duthosts, snappi_api): + testbed = request.config.getoption("--testbed") + + is_override, _ = parse_override( + testbed, + 'multidut_port_info' + ) + + if is_override: + testbed_subtype, rdma_ports = next(iter(request.param.items())) + tx_port_count, rx_port_count = number_of_tx_rx_ports + + if len(get_snappi_ports) < tx_port_count + rx_port_count: + pytest.skip( + "Need Minimum of 2 ports defined in ansible/files/*links.csv" + " file, got:{}".format(len(get_snappi_ports))) + + if len(rdma_ports['tx_ports']) < tx_port_count: + pytest.skip( + "Doesn't have the required Tx ports defined for " + "testbed {}, subtype {} in variables.override.yml".format( + testbed, testbed_subtype)) + + if len(rdma_ports['rx_ports']) < rx_port_count: + pytest.skip( + "Doesn't have the required Rx ports defined for " + "testbed {}, subtype {} in variables.override.yml".format( + testbed, testbed_subtype)) + + snappi_ports = get_snappi_ports + if is_snappi_multidut(duthosts): + snappi_ports = get_snappi_ports_for_rdma( + get_snappi_ports, + rdma_ports, + tx_port_count, + rx_port_count, + testbed + ) + return snappi_dut_base_config(duthosts, snappi_ports, snappi_api, setup=True) + flatten_skeleton_parameter = request.param speed, category = flatten_skeleton_parameter.split("-") + if float(speed) not in snappi_port_selection or category not in snappi_port_selection[float(speed)]: pytest.skip(f"Unsupported combination for {flatten_skeleton_parameter}") - result = snappi_port_selection[float(speed)][category] + snappi_ports = snappi_port_selection[float(speed)][category] - if not result: + if not snappi_ports: pytest.skip(f"Unsupported combination for {flatten_skeleton_parameter}") - return result + return snappi_dut_base_config(duthosts, snappi_ports, snappi_api, setup=True) def flatten_list(lst): diff --git a/tests/common/snappi_tests/variables.py b/tests/common/snappi_tests/variables.py index e1b821141bb..a717aefefb3 100644 --- a/tests/common/snappi_tests/variables.py +++ b/tests/common/snappi_tests/variables.py @@ -1,4 +1,6 @@ -pfcQueueGroupSize = 8 # can have values 4 or 8 +from tests.common.snappi_tests.common_helpers import get_pfcQueueGroupSize + +pfcQueueGroupSize = get_pfcQueueGroupSize(default=8) # can have values 4 or 8 pfcQueueValueDict = {0: 0, 1: 1, 2: 0, diff --git a/tests/conftest.py b/tests/conftest.py index f49957928cb..455b33657c3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,5 @@ import concurrent.futures +from functools import lru_cache import os import json import logging @@ -6,6 +7,7 @@ import random from concurrent.futures import as_completed import re +import sys import pytest import yaml @@ -180,6 +182,8 @@ def pytest_addoption(parser): # keysight ixanvl options # ############################ parser.addoption("--testnum", action="store", default=None, type=str) + parser.addoption("--enable-snappi-dynamic-ports", action="store_true", default=False, + help="Force to use dynamic port allocation for snappi port selections") ################################## # advance-reboot,upgrade options # @@ -1935,12 +1939,40 @@ def format_portautoneg_test_id(param): metafunc.parametrize('vlan_name', ['no_vlan'], scope='module') +@lru_cache +def parse_override(testbed, field): + is_dynamic_only = "--enable-snappi-dynamic-ports" in sys.argv + + if is_dynamic_only and field != "pfcQueueGroupSize": + # Args "--enable-snappi-dynamic-ports" should not affect field `pfcQueueGroupSize` + return False, None + + override_file = "snappi_tests/variables.override.yml" + + with open(override_file, 'r') as f: + all_values = yaml.safe_load(f) + if testbed not in all_values or field not in all_values[testbed]: + return False, None + + return True, all_values[testbed][field] + + return False, None + + def generate_skeleton_port_info(request): """ Return minimal port_info parameters to populate later in the format of -. i.e ["400.0-single_linecard_single_asic", "400.0-multiple_linecard_multiple_asic",...] """ + is_override, override_data = parse_override( + request.config.getoption("--testbed"), + 'multidut_port_info' + ) + + if is_override: + return override_data + dut_info = get_snappi_testbed_metadata(request) or [] available_interfaces = {} matrix = {} diff --git a/tests/snappi_tests/pfc/test_lossless_response_to_external_pause_storms.py b/tests/snappi_tests/pfc/test_lossless_response_to_external_pause_storms.py index 83f0e8862ff..7b47f9456df 100644 --- a/tests/snappi_tests/pfc/test_lossless_response_to_external_pause_storms.py +++ b/tests/snappi_tests/pfc/test_lossless_response_to_external_pause_storms.py @@ -19,7 +19,7 @@ @pytest.fixture(autouse=True, scope='module') def number_of_tx_rx_ports(): - yield (1, 2) + yield (2, 1) def test_lossless_response_to_external_pause_storms_test(snappi_api, # noqa: F811 @@ -61,11 +61,7 @@ def test_lossless_response_to_external_pause_storms_test(snappi_api, Returns: N/A """ - multidut_port_info = tgen_port_info - logger.info('Ports:{}'.format(multidut_port_info)) - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config( - duthosts, multidut_port_info, snappi_api, setup=True) + testbed_config, port_config_list, snappi_ports = tgen_port_info all_prio_list = prio_dscp_map.keys() test_prio_list = lossless_prio_list diff --git a/tests/snappi_tests/variables.override.yml b/tests/snappi_tests/variables.override.yml new file mode 100644 index 00000000000..55c097d2650 --- /dev/null +++ b/tests/snappi_tests/variables.override.yml @@ -0,0 +1,34 @@ +vms-snappi-sonic-multidut: + multidut_port_info: + - multi-dut-single-asic: + rx_ports: + - hostname: sonic-s6100-dut1 + port_name: Ethernet72 + - host_name: sonic-s6100-dut2 + port_name: Ethernet76 + tx_ports: + - hostname: sonic-s6100-dut2 + port_name: Ethernet64 + - hostname: sonic-s6100-dut2 + port_name: Ethernet68 + - single-dut-single-asic: + rx_ports: + - hostname: sonic-s6100-dut1 + port_name: Ethernet72 + - hostname: sonic-s6100-dut1 + port_name: Ethernet76 + tx_ports: + - hostname: sonic-s6100-dut1 + port_name: Ethernet64 + - hostname: sonic-s6100-dut1 + port_name: Ethernet68 + mixed_speed_port_info: + vms-snappi-sonic-multidut: + - multidut-any-asic: + rx_ports: + - hostname: sonic-s6100-dut1 + port_name: Ethernet0 + tx_ports: + - hostname: sonic-s6100-dut2 + port_name: Ethernet0 + pfcQueueGroupSize: 8 diff --git a/tests/test_pretest.py b/tests/test_pretest.py index 540b999fcaf..cc672e70ec0 100644 --- a/tests/test_pretest.py +++ b/tests/test_pretest.py @@ -240,7 +240,7 @@ def test_update_snappi_testbed_metadata(duthosts, tbinfo, request): info = {tbname: metadata} try: if not os.path.exists(folder): - os.mkdir(folder) + os.makedirs(folder) with open(filepath, 'w') as yf: json.dump(info, yf, indent=4) except IOError as e: