From 5ce3bd011246a127c414f6971a9ad8dc24029376 Mon Sep 17 00:00:00 2001 From: Amit Pawar Date: Sun, 28 Jul 2024 11:31:38 -0400 Subject: [PATCH 01/12] Snappi-PR-13655 New Testcases Infra --- .../snappi_tests/snappi_systest_params.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 tests/common/snappi_tests/snappi_systest_params.py diff --git a/tests/common/snappi_tests/snappi_systest_params.py b/tests/common/snappi_tests/snappi_systest_params.py new file mode 100644 index 00000000000..4ce6c49a351 --- /dev/null +++ b/tests/common/snappi_tests/snappi_systest_params.py @@ -0,0 +1,58 @@ +""" +The SnappiTestParams module allows for modular pass through of test parameters for all Snappi based tests. +""" + +from tests.common.snappi_tests.common_helpers import packet_capture +from tests.common.snappi_tests.traffic_flow_config import TrafficFlowConfig +from tests.common.snappi_tests.multi_dut_params import MultiDUTParams + + +class SnappiSysTestParams(): + def __init__(self): + """ + Initialize the SnappiTestParams class + + Params: + headroom_test_params (array): 2 element array if the associated pfc pause quanta + results in no packet drop [pfc_delay, headroom_result] + pfc_pause_src_mac (str): PFC pause source MAC address ex. '00:00:00:fa:ce:01' + set_pfc_class_enable_vec (bool): PFC class enable vector setting + packet_capture_type (ENUM): packet capture type ex. packet_capture.IP_CAPTURE + packet_capture_file (str): packet capture file ex. 'capture.pcapng' + packet_capture_ports (list): packet capture ports on ixia chassis ex. ['Port 1', 'Port 2'] + is_snappi_ingress_port_cap (bool): whether or not the packet capture is on the tgen ingress port, if False, + then pcap is on the tgen egress port + base_flow_config (dict): base flow configuration + test_tx_frames (list): number of test frames transmitted for priorities to test ex. [2000, 3000] + for priorities 3 and 4 + multi_dut_params (MultiDUTParams obj): contains details of duthost objects, + multidut_ports and other parameters + test_iterations (int) : No of iterations in the test + for ex. priorities 3 and 4 + gen_background_traffic (bool): whether or not to generate background traffic (default: True) + poll_device_runtime (bool): whether or not to poll the device for stats when traffic is running + (default: False) + for priorities 3 and 4 + gen_background_traffic (bool): whether or not to generate background traffic (default: True) + ecn_params (dict): ECN parameters + Dict values: + kmin: minimum ECN marking threshold + kmax: maximum ECN marking threshold + pmax: maximum ECN marking probability + traffic_flow_config (TrafficFlowConfig obj): traffic flow configuration object + """ + self.headroom_test_params = None + self.pfc_pause_src_mac = None + self.set_pfc_class_enable_vec = True + self.packet_capture_type = packet_capture.NO_CAPTURE + self.packet_capture_file = None + self.packet_capture_ports = None + self.is_snappi_ingress_port_cap = True + self.base_flow_config = [] + self.test_tx_frames = 0 + self.multi_dut_params = MultiDUTParams() + self.test_iterations = 1 + self.gen_background_traffic = True + self.poll_device_runtime = True + self.ecn_params = None + self.traffic_flow_config = TrafficFlowConfig() From c635f572f53f7351b123e6794480f57ae002fd28 Mon Sep 17 00:00:00 2001 From: Amit Pawar Date: Sun, 28 Jul 2024 18:47:14 -0400 Subject: [PATCH 02/12] Snappi-PFC- testplan PR13215 Non-congestion scenarios --- .../systest/files/sys_multidut_helper.py | 385 +++++++++++++++++ .../systest/test_non_congestion_imix.py | 395 ++++++++++++++++++ 2 files changed, 780 insertions(+) create mode 100644 tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py create mode 100644 tests/snappi_tests/multidut/systest/test_non_congestion_imix.py diff --git a/tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py b/tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py new file mode 100644 index 00000000000..820cd1d7e19 --- /dev/null +++ b/tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py @@ -0,0 +1,385 @@ +import logging +import time + +from tests.common.helpers.assertions import pytest_assert +from tests.common.fixtures.conn_graph_facts import conn_graph_facts,\ + fanout_graph_facts # noqa F401 +from tests.common.snappi_tests.common_helpers import pfc_class_enable_vector,\ + get_lossless_buffer_size, get_pg_dropped_packets,\ + stop_pfcwd, disable_packet_aging, sec_to_nanosec,\ + get_pfc_frame_count, packet_capture, config_capture_pkt,\ + start_pfcwd, enable_packet_aging, \ + traffic_flow_mode, calc_pfc_pause_flow_rate # noqa F401 +from tests.common.snappi_tests.port import select_ports, select_tx_port # noqa F401 +from tests.common.snappi_tests.snappi_helpers import wait_for_arp # noqa F401 +from tests.common.snappi_tests.traffic_generation import generate_pause_flows, verify_pause_flow, \ + verify_basic_test_flow, verify_background_flow, verify_pause_frame_count_dut, verify_sys_egress_queue_count, \ + verify_unset_cev_pause_frame_count, verify_tx_frame_count_dut, \ + verify_rx_frame_count_dut, run_sys_traffic, new_base_traffic_config, \ + generate_sys_test_flows, generate_sys_background_flows +from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams +from tests.common.snappi_tests.read_pcap import validate_pfc_frame + +logger = logging.getLogger(__name__) + +dut_port_config = [] +PAUSE_FLOW_NAME = 'Pause Storm' +TEST_FLOW_NAME = 'Test Flow' +BG_FLOW_NAME = 'Background Flow' +TOLERANCE_THRESHOLD = 0.1 +CONTINUOUS_MODE = -5 +ANSIBLE_POLL_DELAY_SEC = 4 +global DATA_FLOW_DURATION_SEC +global data_flow_delay_sec + + +def run_pfc_test(api, + testbed_config, + port_config_list, + conn_data, + fanout_data, + global_pause, + pause_prio_list, + test_prio_list, + bg_prio_list, + prio_dscp_map, + test_traffic_pause, + test_def, + snappi_extra_params=None): + """ + Run a multidut PFC test + Args: + api (obj): snappi session + testbed_config (obj): testbed L1/L2/L3 configuration + port_config_list (list): list of port configuration + conn_data (dict): the dictionary returned by conn_graph_fact. + fanout_data (dict): the dictionary returned by fanout_graph_fact. + duthost (Ansible host instance): device under test + dut_port (str): DUT port to test + global_pause (bool): if pause frame is IEEE 802.3X pause + pause_prio_list (list): priorities to pause for pause frames + test_prio_list (list): priorities of test flows + bg_prio_list (list): priorities of background flows + prio_dscp_map (dict): Priority vs. DSCP map (key = priority). + test_traffic_pause (bool): if test flows are expected to be paused + test_def['enable_pause'] (bool) : if test expects no pause flow traffic. + snappi_extra_params (SnappiSysTestParams obj): additional parameters for Snappi traffic + + Returns: + N/A + """ + + TEST_FLOW_AGGR_RATE_PERCENT = test_def['TEST_FLOW_AGGR_RATE_PERCENT'] + BG_FLOW_AGGR_RATE_PERCENT = test_def['BG_FLOW_AGGR_RATE_PERCENT'] + data_flow_pkt_size = test_def['data_flow_pkt_size'] + DATA_FLOW_DURATION_SEC = test_def['DATA_FLOW_DURATION_SEC'] + data_flow_delay_sec = test_def['data_flow_delay_sec'] + SNAPPI_POLL_DELAY_SEC = test_def['SNAPPI_POLL_DELAY_SEC'] + PAUSE_FLOW_DUR_BASE_SEC = data_flow_delay_sec + DATA_FLOW_DURATION_SEC + if test_def['imix']: + fname = test_def['test_type'] + '_' + test_def['line_card_choice'] + '_' + 'IMIX' + else: + fname = test_def['test_type'] + '_' + test_def['line_card_choice'] + '_' + str(data_flow_pkt_size) + 'B' + port_map = test_def['port_map'] + + if snappi_extra_params is None: + snappi_extra_params = SnappiSysTestParams() + + duthost1 = snappi_extra_params.multi_dut_params.duthost1 + rx_port = snappi_extra_params.multi_dut_params.multi_dut_ports[0] + duthost2 = snappi_extra_params.multi_dut_params.duthost2 + tx_port = snappi_extra_params.multi_dut_params.multi_dut_ports[-1] + dut_list = [] + dut_list.append(duthost1) + dut_list.append(duthost2) + + tx_dut = duthost1 + rx_dut = duthost2 + if (rx_port['peer_device'] == duthost1.hostname): + tx_dut = duthost2 + rx_dut = duthost1 + + if (test_traffic_pause): + logger.info("PFC receiving DUT is {}".format(tx_dut.hostname)) + + pytest_assert(testbed_config is not None, 'Fail to get L2/3 testbed config') + + if (test_def['enable_pfcwd']): + start_pfcwd(rx_dut) + start_pfcwd(tx_dut) + else: + stop_pfcwd(rx_dut) + stop_pfcwd(tx_dut) + + if (test_def['enable_credit_wd']): + enable_packet_aging(rx_dut, rx_port['asic_value']) + enable_packet_aging(tx_dut, tx_port['asic_value']) + else: + disable_packet_aging(rx_dut, rx_port['asic_value']) + disable_packet_aging(tx_dut, tx_port['asic_value']) + + # Port id of Rx port for traffic config + # rx_port_id and tx_port_id belong to IXIA chassis. + rx_port_id = 0 + + # Rate percent must be an integer + bg_flow_rate_percent = int(BG_FLOW_AGGR_RATE_PERCENT / len(bg_prio_list)) + test_flow_rate_percent = int(TEST_FLOW_AGGR_RATE_PERCENT / len(test_prio_list)) + # Generate base traffic config + for i in range(port_map[2]): + tx_port_id = i+1 + snappi_extra_params.base_flow_config.append(new_base_traffic_config(testbed_config=testbed_config, + port_config_list=port_config_list, + rx_port_id=rx_port_id, + tx_port_id=tx_port_id)) + + speed_str = testbed_config.layer1[0].speed + speed_gbps = int(speed_str.split('_')[1]) + + if snappi_extra_params.headroom_test_params is not None: + DATA_FLOW_DURATION_SEC += 10 + data_flow_delay_sec += 2 + + # Set up pfc delay parameter + l1_config = testbed_config.layer1[0] + pfc = l1_config.flow_control.ieee_802_1qbb + pfc.pfc_delay = snappi_extra_params.headroom_test_params[0] + + if snappi_extra_params.poll_device_runtime: + # If the switch needs to be polled as traffic is running for stats, + # then the test runtime needs to be increased for the polling delay + DATA_FLOW_DURATION_SEC += ANSIBLE_POLL_DELAY_SEC + data_flow_delay_sec = ANSIBLE_POLL_DELAY_SEC + + if snappi_extra_params.packet_capture_type != packet_capture.NO_CAPTURE: + # Setup capture config + if snappi_extra_params.is_snappi_ingress_port_cap: + # packet capture is required on the ingress snappi port + snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["rx_port_name"]] + else: + # packet capture will be on the egress snappi port + snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["tx_port_name"]] + + snappi_extra_params.packet_capture_file = snappi_extra_params.packet_capture_type.value + + config_capture_pkt(testbed_config=testbed_config, + port_names=snappi_extra_params.packet_capture_ports, + capture_type=snappi_extra_params.packet_capture_type, + capture_name=snappi_extra_params.packet_capture_file) + logger.info("Packet capture file: {}.pcapng".format(snappi_extra_params.packet_capture_file)) + + # Set default traffic flow configs if not set + if snappi_extra_params.traffic_flow_config.data_flow_config is None: + snappi_extra_params.traffic_flow_config.data_flow_config = { + "flow_name": TEST_FLOW_NAME, + "flow_dur_sec": DATA_FLOW_DURATION_SEC, + "flow_rate_percent": test_flow_rate_percent, + "flow_rate_pps": None, + "flow_rate_bps": None, + "flow_pkt_count": None, + "flow_pkt_size": data_flow_pkt_size, + "flow_delay_sec": data_flow_delay_sec, + "flow_traffic_type": traffic_flow_mode.FIXED_DURATION + } + + if snappi_extra_params.traffic_flow_config.background_flow_config is None and \ + snappi_extra_params.gen_background_traffic: + snappi_extra_params.traffic_flow_config.background_flow_config = { + "flow_name": BG_FLOW_NAME, + "flow_dur_sec": DATA_FLOW_DURATION_SEC, + "flow_rate_percent": bg_flow_rate_percent, + "flow_rate_pps": None, + "flow_rate_bps": None, + "flow_pkt_size": data_flow_pkt_size, + "flow_pkt_count": None, + "flow_delay_sec": data_flow_delay_sec, + "flow_traffic_type": traffic_flow_mode.FIXED_DURATION + } + + if (test_traffic_pause): + if snappi_extra_params.traffic_flow_config.pause_flow_config is None: + snappi_extra_params.traffic_flow_config.pause_flow_config = { + "flow_name": PAUSE_FLOW_NAME, + "flow_dur_sec": None, + "flow_rate_percent": None, + "flow_rate_pps": calc_pfc_pause_flow_rate(speed_gbps), + "flow_rate_bps": None, + "flow_pkt_size": 64, + "flow_pkt_count": None, + "flow_delay_sec": 0, + "flow_traffic_type": traffic_flow_mode.CONTINUOUS + } + + if snappi_extra_params.packet_capture_type == packet_capture.PFC_CAPTURE: + # PFC pause frame capture is requested + valid_pfc_frame_test = True + else: + # PFC pause frame capture is not requested + valid_pfc_frame_test = False + + if (test_traffic_pause): + if valid_pfc_frame_test: + snappi_extra_params.traffic_flow_config.pause_flow_config["flow_dur_sec"] = DATA_FLOW_DURATION_SEC + \ + data_flow_delay_sec + SNAPPI_POLL_DELAY_SEC + PAUSE_FLOW_DUR_BASE_SEC + snappi_extra_params.traffic_flow_config.pause_flow_config["flow_traffic_type"] = \ + traffic_flow_mode.FIXED_DURATION + + # Generate test flow config based on number of ingress ports + # Every ingress port will be used as index. Example - test flow stream 0 - for first ingress. + for m in range(port_map[2]): + generate_sys_test_flows(testbed_config=testbed_config, + test_flow_prio_list=test_prio_list, + prio_dscp_map=prio_dscp_map, + snappi_extra_params=snappi_extra_params, + snap_index=m) + + if (test_def['background_traffic']): + for m in range(port_map[2]): + if snappi_extra_params.gen_background_traffic: + # Generate background flow config + generate_sys_background_flows(testbed_config=testbed_config, + bg_flow_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + snappi_extra_params=snappi_extra_params, + snap_index=m) + + # Generate pause storm config + if (test_traffic_pause): + for m in range(port_map[0]): + generate_pause_flows(testbed_config=testbed_config, + pause_prio_list=pause_prio_list, + global_pause=global_pause, + snappi_extra_params=snappi_extra_params, + snap_index=m) + + flows = testbed_config.flows + + all_flow_names = [flow.name for flow in flows] + data_flow_names = [flow.name for flow in flows if PAUSE_FLOW_NAME not in flow.name] + + # Clear PFC, queue and interface counters before traffic run + for dut in dut_list: + dut.command("pfcstat -c \n") + time.sleep(1) + dut.command("sonic-clear queuecounters \n") + time.sleep(1) + dut.command("sonic-clear counters \n") + time.sleep(1) + + exp_dur_sec = DATA_FLOW_DURATION_SEC + data_flow_delay_sec + + """ Run traffic """ + tgen_flow_stats, switch_flow_stats, test_stats = run_sys_traffic(rx_duthost=rx_dut, + tx_duthost=tx_dut, + api=api, + config=testbed_config, + data_flow_names=data_flow_names, + all_flow_names=all_flow_names, + exp_dur_sec=exp_dur_sec, + port_map=test_def['port_map'], + fname=fname, + stats_interval=test_def['stats_interval'], + imix=test_def['imix'], + snappi_extra_params=snappi_extra_params) + + test_check = test_def['test_check'] + if (not test_check['loss_expected']): + # Check for packet loss on IXIA and DUT. + pytest_assert(test_stats['tgen_loss_pkts'] == 0, 'Loss seen on TGEN') + pytest_assert(test_stats['dut_loss_pkts'] == 0, 'Loss seen on DUT') + + # Check for Tx and Rx packets on IXIA for lossless and lossy streams. + pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['tgen_lossless_tx_pkts'], + 'Losses observed in lossless traffic streams') + pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['tgen_lossy_tx_pkts'], + 'Losses observed in lossy traffic streams') + + # Check for Rx packets between IXIA and DUT for lossy and lossless streams. + pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['dut_lossless_pkts'], + 'Losses observed in lossless traffic streams on DUT Tx and IXIA Rx') + pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['dut_lossy_pkts'], + 'Losses observed in lossy traffic streams on DUT Tx and IXIA Rx') + else: + # Check for lossless and lossy stream percentage drop for a given tolerance limit. + lossless_drop = round((1 - float(test_stats['tgen_lossless_rx_pkts']) / test_stats['tgen_lossless_tx_pkts']), 2) + lossy_drop = round((1 - float(test_stats['tgen_lossy_rx_pkts']) / test_stats['tgen_lossy_tx_pkts']), 2) + logger.info('Lossless Drop %:{}, Lossy Drop %:{}'.format(lossless_drop, lossy_drop)) + pytest_assert((lossless_drop*100) <= test_check['lossless'], 'Lossless packet drop outside tolerance limit') + pytest_assert((lossy_drop*100) <= test_check['lossy'], 'Lossy packet drop outside tolerance limit') + + # Checking if the actual line rate on egress is within tolerable limit of egress line speed. + pytest_assert(((1 - test_stats['tgen_rx_rate'] / float(port_map[0]*port_map[1]))*100) <= test_check['speed_tol'], + 'Egress speed beyond tolerance range') + + # Checking for PFC counts on DUT + if (not test_check['pfc']): + pytest_assert(test_stats['lossless_tx_pfc'] == 0, 'Error:PFC transmitted by DUT for lossless priorities') + pytest_assert(test_stats['lossy_rx_tx_pfc'] == 0, 'Error:PFC transmitted by DUT for lossy priorities') + else: + if (test_stats['lossless_rx_pfc'] != 0): + pytest_assert(test_stats['lossless_tx_pfc'] > 0, 'Error:No Tx PFCs from DUT after receiving PFCs') + pytest_assert(test_stats['lossless_tx_pfc'] > 0, 'Error: PFC not be transmitted from DUT on congestion') + pytest_assert(test_stats['lossy_rx_tx_pfc'] == 0, 'Error:Incorrect Rx/Tx PFCs on DUT for lossy priorities') + + # Reset pfc delay parameter + pfc = testbed_config.layer1[0].flow_control.ieee_802_1qbb + pfc.pfc_delay = 0 + + # Verify PFC pause frames + if (test_traffic_pause): + if valid_pfc_frame_test: + is_valid_pfc_frame = validate_pfc_frame(snappi_extra_params.packet_capture_file + ".pcapng") + pytest_assert(is_valid_pfc_frame, "PFC frames invalid") + return + + # Verify pause flows + if (test_traffic_pause): + verify_pause_flow(flow_metrics=tgen_flow_stats, + pause_flow_name=PAUSE_FLOW_NAME) + + # Check for the flows ONLY if normal packet size (non-imix) is used. + if (test_def['background_traffic'] and test_def['verify_flows'] and not test_def['imix']): + if snappi_extra_params.gen_background_traffic: + # Verify background flows + verify_background_flow(flow_metrics=tgen_flow_stats, + speed_gbps=speed_gbps, + tolerance=TOLERANCE_THRESHOLD, + snappi_extra_params=snappi_extra_params) + + # Verify basic test flows metrics from ixia + if (test_def['verify_flows'] and not test_def['imix']): + verify_basic_test_flow(flow_metrics=tgen_flow_stats, + speed_gbps=speed_gbps, + tolerance=TOLERANCE_THRESHOLD, + test_flow_pause=test_traffic_pause, + snappi_extra_params=snappi_extra_params) + + if (test_traffic_pause and test_def['verify_flows']): + verify_pause_frame_count_dut(rx_dut=rx_dut, + tx_dut=tx_dut, + test_traffic_pause=test_traffic_pause, + global_pause=global_pause, + snappi_extra_params=snappi_extra_params) + + # Verify in flight TX lossless packets do not leave the DUT when traffic is expected + # to be paused, or leave the DUT when the traffic is not expected to be paused + verify_sys_egress_queue_count(duthost=tx_dut, + switch_flow_stats=switch_flow_stats, + test_traffic_pause=test_traffic_pause, + snappi_extra_params=snappi_extra_params) + + if test_traffic_pause: + # Verify zero pause frames are counted when the PFC class enable vector is not set + verify_unset_cev_pause_frame_count(duthost=tx_dut, + snappi_extra_params=snappi_extra_params) + + if test_traffic_pause and not snappi_extra_params.gen_background_traffic: + # Verify TX frame count on the DUT when traffic is expected to be paused + # and only test traffic flows are generated + verify_tx_frame_count_dut(duthost=rx_dut, + snappi_extra_params=snappi_extra_params) + + # Verify TX frame count on the DUT when traffic is expected to be paused + # and only test traffic flows are generated + verify_rx_frame_count_dut(duthost=tx_dut, + snappi_extra_params=snappi_extra_params) diff --git a/tests/snappi_tests/multidut/systest/test_non_congestion_imix.py b/tests/snappi_tests/multidut/systest/test_non_congestion_imix.py new file mode 100644 index 00000000000..f048034ab87 --- /dev/null +++ b/tests/snappi_tests/multidut/systest/test_non_congestion_imix.py @@ -0,0 +1,395 @@ +import pytest +from tests.common.helpers.assertions import pytest_require, pytest_assert # noqa: F401 +from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts # noqa: F401 +from tests.common.snappi_tests.snappi_fixtures import snappi_api_serv_ip, snappi_api_serv_port, \ + snappi_api, snappi_dut_base_config, get_multidut_snappi_ports, \ + new_get_multidut_tgen_peer_port_set, cleanup_config # noqa: F401 +from tests.common.snappi_tests.qos_fixtures import prio_dscp_map # noqa: F401 +from tests.snappi_tests.variables import config_set, line_card_choice +from tests.snappi_tests.multidut.systest.files.sys_multidut_helper import run_pfc_test +from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams + +import logging +logger = logging.getLogger(__name__) + +pytestmark = [pytest.mark.topology('multidut-tgen')] + + +@pytest.mark.parametrize('linecard_configuration_set', [config_set]) +@pytest.mark.parametrize('line_card_choice', line_card_choice) +def test_multiple_prio_diff_dist(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + line_card_choice, + linecard_configuration_set, + get_multidut_snappi_ports): # noqa: F811 + + """ + Purpose of the test is to check if line-rate can be achieved. + Traffic distribution is 88% lossless priority 3 and 4 traffic. + There is additional 12% of lossy priority 0, 1 and 2 traffic. + PFCWD and Credit-watchdog is enabled. + Packet-size is 1024. IMIX can be enabled by setting imix to True. + No losses should be seen for both lossy and lossless traffic. + No PFCs should be generated during the test. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + line_card_choice: Line card choice to be mentioned in the variable.py file + linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) + Returns: + N/A + + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + if '100Gbps' in line_card_choice: + port_map = [1, 100, 1, 100] + else: + port_map = [1, 400, 1, 400] + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': False} + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 88, + 'BG_FLOW_AGGR_RATE_PERCENT': 12, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Single_Ingress_Egress_diff_dist_'+str(port_map[1])+'Gbps', + 'line_card_choice': line_card_choice, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'imix': False, + 'test_check': test_check, + 'verify_flows': True} + + logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) + if line_card_choice not in linecard_configuration_set.keys(): + assert False, "Invalid line_card_choice value passed in parameter" + + if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): + dut_list = [dut for dut in duthosts + if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] + duthost1, duthost2 = dut_list + elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): + dut_list = [dut for dut in duthosts + if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] + duthost1 = duthost2 = dut_list[0] + else: + assert False, "Hostname can't be an empty list" + + snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, + line_card_info=linecard_configuration_set[line_card_choice]) + + if len(snappi_port_list) < 2: + assert False, "Need Minimum of 2 ports for the test" + + snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) + + if len(snappi_ports) < 2: + assert False, "Need Minimum of 2 ports for the test" + + logger.info("Snappi Ports : {}".format(snappi_ports)) + + testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, + snappi_ports, + snappi_api) + + test_prio_list = [3, 4] + pause_prio_list = test_prio_list + bg_prio_list = [0, 1, 2] + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = duthost1 + snappi_extra_params.multi_dut_params.duthost2 = duthost2 + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('linecard_configuration_set', [config_set]) +@pytest.mark.parametrize('line_card_choice', line_card_choice) +def test_multiple_prio_uni_dist(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + line_card_choice, + linecard_configuration_set, + get_multidut_snappi_ports): # noqa: F811 + + """ + Purpose of the test is to check if line-rate can be achieved. + Traffic distribution is 40% lossless priority 3 and 4 traffic. + There is additional 60% of lossy priority 0, 1 and 2 traffic. + PFCWD and Credit-watchdog is enabled. + Packet-size is 1024. IMIX can be enabled by setting imix to True. + No losses should be seen for both lossy and lossless traffic. + No PFCs should be generated during the test. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + line_card_choice: Line card choice to be mentioned in the variable.py file + linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) + Returns: + N/A + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + if '100Gbps' in line_card_choice: + port_map = [1, 100, 1, 100] + else: + port_map = [1, 400, 1, 400] + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': False} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, + 'BG_FLOW_AGGR_RATE_PERCENT': 60, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Single_Ingress_Egress_uni_dist_'+str(port_map[1])+'Gbps', + 'line_card_choice': line_card_choice, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'imix': False, + 'test_check': test_check, + 'verify_flows': True} + + logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) + if line_card_choice not in linecard_configuration_set.keys(): + assert False, "Invalid line_card_choice value passed in parameter" + + if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): + dut_list = [dut for dut in duthosts + if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] + duthost1, duthost2 = dut_list + elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): + dut_list = [dut for dut in duthosts + if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] + duthost1 = duthost2 = dut_list[0] + else: + assert False, "Hostname can't be an empty list" + + snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, + line_card_info=linecard_configuration_set[line_card_choice]) + + if len(snappi_port_list) < 2: + assert False, "Need Minimum of 2 ports for the test" + + # port_map is read as egress port_map[0] links of port_map[1] speed + # and ingress port_map[2] links of port_map[3] speed + port_map = test_def['port_map'] + + snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) + + if len(snappi_ports) < 2: + assert False, "Need Minimum of 2 ports for the test" + + testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, + snappi_ports, + snappi_api) + + test_prio_list = [3, 4] + pause_prio_list = test_prio_list + bg_prio_list = [0, 1, 2] + logger.info("Snappi Ports : {}".format(snappi_ports)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = duthost1 + snappi_extra_params.multi_dut_params.duthost2 = duthost2 + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('linecard_configuration_set', [config_set]) +@pytest.mark.parametrize('line_card_choice', line_card_choice) +def test_single_lossless_prio(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + line_card_choice, + linecard_configuration_set, + get_multidut_snappi_ports): # noqa: F811 + + """ + Purpose of the test is to check if line-rate can be achieved with single priority traffic. + Traffic distribution is 100% lossless priority 3 traffic. + PFCWD and Credit-watchdog is enabled. + Packet-size is 1024. IMIX can be enabled by setting imix to True. + No losses should be seen for both lossy and lossless traffic. + No PFCs should be generated during the test. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + line_card_choice: Line card choice to be mentioned in the variable.py file + linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) + Returns: + N/A + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + if '100Gbps' in line_card_choice: + port_map = [1, 100, 1, 100] + else: + port_map = [1, 400, 1, 400] + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': False} + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 100, + 'BG_FLOW_AGGR_RATE_PERCENT': 50, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Single_Ingress_Egress_1Prio_linerate_'+str(port_map[1])+'Gbps', + 'line_card_choice': line_card_choice, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': False, + 'imix': False, + 'test_check': test_check, + 'verify_flows': True} + + logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) + + if line_card_choice not in linecard_configuration_set.keys(): + assert False, "Invalid line_card_choice value passed in parameter" + if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): + dut_list = [dut for dut in duthosts + if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] + duthost1, duthost2 = dut_list + elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): + dut_list = [dut for dut in duthosts + if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] + duthost1 = duthost2 = dut_list[0] + else: + assert False, "Hostname can't be an empty list" + + snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, + line_card_info=linecard_configuration_set[line_card_choice]) + + if len(snappi_port_list) < 2: + assert False, "Need Minimum of 2 ports for the test" + + # port_map is read as egress port_map[0] links of port_map[1] speed + # and ingress port_map[2] links of port_map[3] speed + port_map = test_def['port_map'] + + snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) + + if len(snappi_ports) < 2: + assert False, "Need Minimum of 2 ports for the test" + + testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, + snappi_ports, + snappi_api) + + test_prio_list = [3] + logger.info('Selected Test Prio:{}'.format(test_prio_list)) + pause_prio_list = test_prio_list + bg_prio_list = [0, 1, 2] + logger.info("Pkt Size:{}, Current port_map:{} and Snappi Ports : {}".format(pkt_size, port_map, snappi_ports)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = duthost1 + snappi_extra_params.multi_dut_params.duthost2 = duthost2 + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + finally: + cleanup_config(dut_list, snappi_ports) From 4b2c5e4ab642fc78ac410d1d68a9cb4c864f9881 Mon Sep 17 00:00:00 2001 From: Amit Pawar Date: Sun, 28 Jul 2024 18:49:14 -0400 Subject: [PATCH 03/12] Snappi-PFC- testplan PR13215 over-subscription scenarios --- .../systest/test_over_subscription_imix.py | 515 ++++++++++++++++++ 1 file changed, 515 insertions(+) create mode 100644 tests/snappi_tests/multidut/systest/test_over_subscription_imix.py diff --git a/tests/snappi_tests/multidut/systest/test_over_subscription_imix.py b/tests/snappi_tests/multidut/systest/test_over_subscription_imix.py new file mode 100644 index 00000000000..4853be9c03e --- /dev/null +++ b/tests/snappi_tests/multidut/systest/test_over_subscription_imix.py @@ -0,0 +1,515 @@ +import pytest +from tests.common.helpers.assertions import pytest_require, pytest_assert # noqa: F401 +from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts # noqa: F401 +from tests.common.snappi_tests.snappi_fixtures import snappi_api_serv_ip, snappi_api_serv_port, \ + snappi_api, snappi_dut_base_config, get_multidut_snappi_ports, \ + new_get_multidut_tgen_peer_port_set, cleanup_config # noqa: F401 +from tests.common.snappi_tests.qos_fixtures import prio_dscp_map # noqa: F401 +from tests.snappi_tests.variables import config_set, line_card_choice +from tests.snappi_tests.multidut.systest.files.sys_multidut_helper import run_pfc_test +from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams + +import logging +logger = logging.getLogger(__name__) + +pytestmark = [pytest.mark.topology('multidut-tgen')] + + +@pytest.mark.parametrize('linecard_configuration_set', [config_set]) +@pytest.mark.parametrize('line_card_choice', line_card_choice) +def test_multiple_prio_diff_dist(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + line_card_choice, + linecard_configuration_set, + get_multidut_snappi_ports): # noqa: F811 + + """ + Purpose of the test case is to test oversubscription with two ingresses and single ingress. + Traffic pattern has 90% lossless priority and 10% lossy priority traffic. + No losses for both lossless and lossy priority traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + line_card_choice: Line card choice to be mentioned in the variable.py file + linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) + Returns: + N/A + + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + if '100Gbps' in line_card_choice: + port_map = [1, 100, 2, 100] + else: + port_map = [1, 400, 2, 400] + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': True} + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 88, + 'BG_FLOW_AGGR_RATE_PERCENT': 12, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Two_Ingress_Single_Egress_diff_dist_'+str(port_map[1])+'Gbps', + 'line_card_choice': line_card_choice, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'imix': False, + 'test_check': test_check, + 'verify_flows': False} + + logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) + if line_card_choice not in linecard_configuration_set.keys(): + assert False, "Invalid line_card_choice value passed in parameter" + + if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): + dut_list = [dut for dut in duthosts + if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] + duthost1, duthost2 = dut_list + elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): + dut_list = [dut for dut in duthosts + if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] + duthost1 = duthost2 = dut_list[0] + else: + assert False, "Hostname can't be an empty list" + + snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, + line_card_info=linecard_configuration_set[line_card_choice]) + + if len(snappi_port_list) < 3: + assert False, "snappi_port_list: Need Minimum of 3 ports for the test" + + snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) + + if len(snappi_ports) < 3: + assert False, "snappi_port: Need Minimum of 3 ports for the test" + + logger.info("Snappi Ports : {}".format(snappi_ports)) + + testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, + snappi_ports, + snappi_api) + + test_prio_list = [3, 4] + pause_prio_list = test_prio_list + bg_prio_list = [0, 1, 2] + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = duthost1 + snappi_extra_params.multi_dut_params.duthost2 = duthost2 + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('linecard_configuration_set', [config_set]) +@pytest.mark.parametrize('line_card_choice', line_card_choice) +def test_multiple_prio_uni_dist_full(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + line_card_choice, + linecard_configuration_set, + get_multidut_snappi_ports): # noqa: F811 + + """ + Purpose of the test case is to test oversubscription with two ingresses and single ingress. + Traffic pattern has 24% lossless priority and 36% lossy priority traffic. + Each priority carries equal 12% of traffic. + No losses for lossless priority traffic. Some loss expected for lossy priority traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + line_card_choice: Line card choice to be mentioned in the variable.py file + linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) + Returns: + N/A + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + if '100Gbps' in line_card_choice: + port_map = [1, 100, 2, 100] + else: + port_map = [1, 400, 2, 400] + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 51, 'speed_tol': 51, 'loss_expected': True, 'pfc': True} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, + 'BG_FLOW_AGGR_RATE_PERCENT': 60, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Two_Ingress_Single_Egress_uni_dist_full'+str(port_map[1])+'Gbps', + 'line_card_choice': line_card_choice, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'imix': False, + 'test_check': test_check, + 'verify_flows': False} + + logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) + if line_card_choice not in linecard_configuration_set.keys(): + assert False, "Invalid line_card_choice value passed in parameter" + + if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): + dut_list = [dut for dut in duthosts + if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] + duthost1, duthost2 = dut_list + elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): + dut_list = [dut for dut in duthosts + if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] + duthost1 = duthost2 = dut_list[0] + else: + assert False, "Hostname can't be an empty list" + + snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, + line_card_info=linecard_configuration_set[line_card_choice]) + + if len(snappi_port_list) < 3: + assert False, "snappi_port_list: Need Minimum of 3 ports for the test" + + # port_map is read as egress port_map[0] links of port_map[1] speed + # and ingress port_map[2] links of port_map[3] speed + port_map = test_def['port_map'] + + snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) + + if len(snappi_ports) < 3: + assert False, "snappi_ports: Need Minimum of 3 ports for the test" + + testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, + snappi_ports, + snappi_api) + + test_prio_list = [3, 4] + pause_prio_list = test_prio_list + bg_prio_list = [0, 1, 2] + logger.info("Snappi Ports : {}".format(snappi_ports)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = duthost1 + snappi_extra_params.multi_dut_params.duthost2 = duthost2 + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('linecard_configuration_set', [config_set]) +@pytest.mark.parametrize('line_card_choice', line_card_choice) +def test_multiple_prio_uni_dist(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + line_card_choice, + linecard_configuration_set, + get_multidut_snappi_ports): # noqa: F811 + + """ + Purpose of the test case is to test oversubscription with two ingresses and single ingress. + Traffic pattern for each priority is same 12%. + Traffic pattern has 24% lossless priority and 36% lossy priority traffic. + Each priority carries equal 12% of traffic. + No losses for lossless priority traffic. Some loss expected for lossy priority traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + line_card_choice: Line card choice to be mentioned in the variable.py file + linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) + Returns: + N/A + + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + if '100Gbps' in line_card_choice: + port_map = [1, 100, 2, 100] + else: + port_map = [1, 400, 2, 400] + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 15, 'speed_tol': 3, 'loss_expected': True, 'pfc': True} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 24, + 'BG_FLOW_AGGR_RATE_PERCENT': 36, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Two_Ingress_Single_Egress_uni_dist_'+str(port_map[1])+'Gbps', + 'line_card_choice': line_card_choice, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'imix': False, + 'test_check': test_check, + 'verify_flows': False} + + logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) + if line_card_choice not in linecard_configuration_set.keys(): + assert False, "Invalid line_card_choice value passed in parameter" + + if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): + dut_list = [dut for dut in duthosts + if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] + duthost1, duthost2 = dut_list + elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): + dut_list = [dut for dut in duthosts + if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] + duthost1 = duthost2 = dut_list[0] + else: + assert False, "Hostname can't be an empty list" + + snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, + line_card_info=linecard_configuration_set[line_card_choice]) + + if len(snappi_port_list) < 3: + assert False, "snappi_port_list: Need Minimum of 3 ports for the test" + + # port_map is read as egress port_map[0] links of port_map[1] speed + # and ingress port_map[2] links of port_map[3] speed + port_map = test_def['port_map'] + + snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) + + if len(snappi_ports) < 3: + assert False, "snappi_ports: Need Minimum of 3 ports for the test" + + testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, + snappi_ports, + snappi_api) + + test_prio_list = [3, 4] + pause_prio_list = test_prio_list + bg_prio_list = [0, 1, 2] + logger.info("Snappi Ports : {}".format(snappi_ports)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = duthost1 + snappi_extra_params.multi_dut_params.duthost2 = duthost2 + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('linecard_configuration_set', [config_set]) +@pytest.mark.parametrize('line_card_choice', line_card_choice) +def test_multiple_prio_non_cngtn(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + line_card_choice, + linecard_configuration_set, + get_multidut_snappi_ports): # noqa: F811 + + """ + Purpose of the test case is to test oversubscription with two ingresses and single ingress. + Traffic pattern has 18% lossless priority and 27% lossy priority traffic. + Total ingress link is sending only 45% link capacity and hence egress will not be congested. + No losses for both lossless and lossy priority traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + line_card_choice: Line card choice to be mentioned in the variable.py file + linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) + Returns: + N/A + """ + if (line_card_choice == 'chassis_slcsa_400Gbps'): + pytest.skip('Not enough 400Gbps ports on Single LC Single ASICs') + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + if '100Gbps' in line_card_choice: + port_map = [1, 100, 2, 100] + else: + port_map = [1, 400, 2, 400] + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 14, 'loss_expected': False, 'pfc': False} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 18, + 'BG_FLOW_AGGR_RATE_PERCENT': 27, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Two_Ingress_Single_Egress_non_cngstn_'+str(port_map[1])+'Gbps', + 'line_card_choice': line_card_choice, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'imix': False, + 'test_check': test_check, + 'verify_flows': False} + + logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) + if line_card_choice not in linecard_configuration_set.keys(): + assert False, "Invalid line_card_choice value passed in parameter" + + if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): + dut_list = [dut for dut in duthosts + if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] + duthost1, duthost2 = dut_list + elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): + dut_list = [dut for dut in duthosts + if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] + duthost1 = duthost2 = dut_list[0] + else: + assert False, "Hostname can't be an empty list" + + snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, + line_card_info=linecard_configuration_set[line_card_choice]) + + if len(snappi_port_list) < 3: + assert False, "snappi_port_list: Need Minimum of 3 ports for the test" + + # port_map is read as egress port_map[0] links of port_map[1] speed + # and ingress port_map[2] links of port_map[3] speed + port_map = test_def['port_map'] + + snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) + + if len(snappi_ports) < 3: + assert False, "snappi_ports: Need Minimum of 3 ports for the test" + + testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, + snappi_ports, + snappi_api) + + test_prio_list = [3, 4] + pause_prio_list = test_prio_list + bg_prio_list = [0, 1, 2] + logger.info("Snappi Ports : {}".format(snappi_ports)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = duthost1 + snappi_extra_params.multi_dut_params.duthost2 = duthost2 + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + finally: + cleanup_config(dut_list, snappi_ports) From 503aed340402905a70e33ce743d79469ce42bb1c Mon Sep 17 00:00:00 2001 From: Amit Pawar Date: Sun, 28 Jul 2024 18:51:34 -0400 Subject: [PATCH 04/12] Snappi-PFC- testplan PR13215 PFCWD-DROP and FRWD scenarios --- .../systest/files/pfcwd_multidut_helper.py | 373 +++++++++ .../multidut/systest/test_multiflow_pfcwd.py | 753 ++++++++++++++++++ 2 files changed, 1126 insertions(+) create mode 100644 tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py create mode 100644 tests/snappi_tests/multidut/systest/test_multiflow_pfcwd.py diff --git a/tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py b/tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py new file mode 100644 index 00000000000..e63ebd381b8 --- /dev/null +++ b/tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py @@ -0,0 +1,373 @@ +import logging +import time + +from tests.common.helpers.assertions import pytest_assert +from tests.common.fixtures.conn_graph_facts import conn_graph_facts,\ + fanout_graph_facts # noqa F401 +from tests.common.snappi_tests.common_helpers import pfc_class_enable_vector,\ + get_lossless_buffer_size, get_pg_dropped_packets,\ + stop_pfcwd, disable_packet_aging, sec_to_nanosec,\ + get_pfc_frame_count, packet_capture, config_capture_pkt,\ + start_pfcwd, enable_packet_aging, start_pfcwd_fwd, \ + traffic_flow_mode, calc_pfc_pause_flow_rate # noqa F401 +from tests.common.snappi_tests.traffic_generation import verify_pause_flow, \ + verify_basic_test_flow, verify_background_flow, verify_pause_frame_count_dut, \ + run_sys_traffic, new_base_traffic_config, \ + generate_sys_test_flows, generate_sys_background_flows, generate_sys_pause_flows +from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams + + +logger = logging.getLogger(__name__) + +dut_port_config = [] +PAUSE_FLOW_NAME = 'Pause Storm' +TEST_FLOW_NAME = 'Test Flow' +BG_FLOW_NAME = 'Background Flow' +TOLERANCE_THRESHOLD = 0.1 +CONTINUOUS_MODE = -5 +ANSIBLE_POLL_DELAY_SEC = 4 +global DATA_FLOW_DURATION_SEC +global data_flow_delay_sec + + +def run_pfc_test(api, + testbed_config, + port_config_list, + conn_data, + fanout_data, + global_pause, + pause_prio_list, + test_prio_list, + bg_prio_list, + prio_dscp_map, + test_traffic_pause, + test_def, + snappi_extra_params=None): + """ + Run a multidut PFC test + Args: + api (obj): snappi session + testbed_config (obj): testbed L1/L2/L3 configuration + port_config_list (list): list of port configuration + conn_data (dict): the dictionary returned by conn_graph_fact. + fanout_data (dict): the dictionary returned by fanout_graph_fact. + duthost (Ansible host instance): device under test + dut_port (str): DUT port to test + global_pause (bool): if pause frame is IEEE 802.3X pause + pause_prio_list (list): priorities to pause for pause frames + test_prio_list (list): priorities of test flows + bg_prio_list (list): priorities of background flows + prio_dscp_map (dict): Priority vs. DSCP map (key = priority). + test_traffic_pause (bool): if test flows are expected to be paused + test_def['enable_pause'] (bool) : if test expects no pause flow traffic. + snappi_extra_params (SnappiSysTestParams obj): additional parameters for Snappi traffic + + Returns: + N/A + """ + + TEST_FLOW_AGGR_RATE_PERCENT = test_def['TEST_FLOW_AGGR_RATE_PERCENT'] + BG_FLOW_AGGR_RATE_PERCENT = test_def['BG_FLOW_AGGR_RATE_PERCENT'] + data_flow_pkt_size = test_def['data_flow_pkt_size'] + DATA_FLOW_DURATION_SEC = test_def['DATA_FLOW_DURATION_SEC'] + data_flow_delay_sec = test_def['data_flow_delay_sec'] + SNAPPI_POLL_DELAY_SEC = test_def['SNAPPI_POLL_DELAY_SEC'] + PAUSE_FLOW_DUR_BASE_SEC = data_flow_delay_sec + DATA_FLOW_DURATION_SEC + if test_def['imix']: + fname = test_def['test_type'] + '_' + test_def['line_card_choice'] + '_' + 'IMIX' + else: + fname = test_def['test_type'] + '_' + test_def['line_card_choice'] + '_' + str(data_flow_pkt_size) + 'B' + + port_map = test_def['port_map'] + + if snappi_extra_params is None: + snappi_extra_params = SnappiSysTestParams() + + duthost1 = snappi_extra_params.multi_dut_params.duthost1 + rx_port = snappi_extra_params.multi_dut_params.multi_dut_ports[0] + duthost2 = snappi_extra_params.multi_dut_params.duthost2 + tx_port = snappi_extra_params.multi_dut_params.multi_dut_ports[-1] + dut_list = [] + dut_list.append(duthost1) + dut_list.append(duthost2) + + tx_dut = duthost1 + rx_dut = duthost2 + + if rx_port['peer_device'] == duthost1.hostname: + tx_dut = duthost2 + rx_dut = duthost1 + + if (test_traffic_pause): + logger.info("PFC receiving DUT is {}".format(tx_dut.hostname)) + + pytest_assert(testbed_config is not None, 'Fail to get L2/3 testbed config') + + if (test_def['enable_pfcwd_drop']): + start_pfcwd(rx_dut) + start_pfcwd(tx_dut) + elif (test_def['enable_pfcwd_fwd']): + start_pfcwd_fwd(rx_dut) + start_pfcwd_fwd(tx_dut) + else: + stop_pfcwd(rx_dut) + stop_pfcwd(tx_dut) + + if (test_def['enable_credit_wd']): + enable_packet_aging(rx_dut, rx_port['asic_value']) + enable_packet_aging(tx_dut, tx_port['asic_value']) + else: + disable_packet_aging(rx_dut, rx_port['asic_value']) + disable_packet_aging(tx_dut, tx_port['asic_value']) + + rx_port_id = 0 + + # Rate percent must be an integer + bg_flow_rate_percent = int(BG_FLOW_AGGR_RATE_PERCENT / len(bg_prio_list)) + test_flow_rate_percent = int(TEST_FLOW_AGGR_RATE_PERCENT / len(test_prio_list)) + # Generate base traffic config + if (port_map[0] == 2): + for i in range(port_map[0]): + rx_port_id = i + tx_port_id = 2 + snappi_extra_params.base_flow_config.append(new_base_traffic_config(testbed_config=testbed_config, + port_config_list=port_config_list, + rx_port_id=rx_port_id, + tx_port_id=tx_port_id)) + else: + rx_port_id = 0 + for i in range(port_map[2]): + tx_port_id = i+1 + snappi_extra_params.base_flow_config.append(new_base_traffic_config(testbed_config=testbed_config, + port_config_list=port_config_list, + rx_port_id=rx_port_id, + tx_port_id=tx_port_id)) + + speed_str = testbed_config.layer1[0].speed + speed_gbps = int(speed_str.split('_')[1]) + + if snappi_extra_params.headroom_test_params is not None: + DATA_FLOW_DURATION_SEC += 10 + data_flow_delay_sec += 2 + + # Set up pfc delay parameter + l1_config = testbed_config.layer1[0] + pfc = l1_config.flow_control.ieee_802_1qbb + pfc.pfc_delay = snappi_extra_params.headroom_test_params[0] + + if snappi_extra_params.poll_device_runtime: + # If the switch needs to be polled as traffic is running for stats, + # then the test runtime needs to be increased for the polling delay + DATA_FLOW_DURATION_SEC += ANSIBLE_POLL_DELAY_SEC + data_flow_delay_sec = ANSIBLE_POLL_DELAY_SEC + + if snappi_extra_params.packet_capture_type != packet_capture.NO_CAPTURE: + # Setup capture config + if snappi_extra_params.is_snappi_ingress_port_cap: + # packet capture is required on the ingress snappi port + snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["rx_port_name"]] + else: + # packet capture will be on the egress snappi port + snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["tx_port_name"]] + + snappi_extra_params.packet_capture_file = snappi_extra_params.packet_capture_type.value + + config_capture_pkt(testbed_config=testbed_config, + port_names=snappi_extra_params.packet_capture_ports, + capture_type=snappi_extra_params.packet_capture_type, + capture_name=snappi_extra_params.packet_capture_file) + logger.info("Packet capture file: {}.pcapng".format(snappi_extra_params.packet_capture_file)) + + # Set default traffic flow configs if not set + if snappi_extra_params.traffic_flow_config.data_flow_config is None: + snappi_extra_params.traffic_flow_config.data_flow_config = { + "flow_name": TEST_FLOW_NAME, + "flow_dur_sec": DATA_FLOW_DURATION_SEC, + "flow_rate_percent": test_flow_rate_percent, + "flow_rate_pps": None, + "flow_rate_bps": None, + "flow_pkt_count": None, + "flow_pkt_size": data_flow_pkt_size, + "flow_delay_sec": data_flow_delay_sec, + "flow_traffic_type": traffic_flow_mode.FIXED_DURATION + } + + if snappi_extra_params.traffic_flow_config.background_flow_config is None and \ + snappi_extra_params.gen_background_traffic: + snappi_extra_params.traffic_flow_config.background_flow_config = { + "flow_name": BG_FLOW_NAME, + "flow_dur_sec": DATA_FLOW_DURATION_SEC, + "flow_rate_percent": bg_flow_rate_percent, + "flow_rate_pps": None, + "flow_rate_bps": None, + "flow_pkt_size": data_flow_pkt_size, + "flow_pkt_count": None, + "flow_delay_sec": data_flow_delay_sec, + "flow_traffic_type": traffic_flow_mode.FIXED_DURATION + } + + # PPS is high to ensure Storm is detected. + # traffic_flow_mode is changed to BURST + # Need to check how it works + if (test_traffic_pause): + if snappi_extra_params.traffic_flow_config.pause_flow_config is None: + snappi_extra_params.traffic_flow_config.pause_flow_config = { + "flow_name": PAUSE_FLOW_NAME, + "flow_dur_sec": DATA_FLOW_DURATION_SEC+60, + "flow_rate_percent": None, + "flow_rate_pps": calc_pfc_pause_flow_rate(speed_gbps), + "flow_rate_bps": None, + "flow_pkt_size": 64, + "flow_pkt_count": None, + "flow_delay_sec": 0, + "flow_traffic_type": traffic_flow_mode.FIXED_DURATION + } + + if snappi_extra_params.packet_capture_type == packet_capture.PFC_CAPTURE: + # PFC pause frame capture is requested + valid_pfc_frame_test = True + else: + # PFC pause frame capture is not requested + valid_pfc_frame_test = False + + if (test_traffic_pause): + if valid_pfc_frame_test: + snappi_extra_params.traffic_flow_config.pause_flow_config["flow_dur_sec"] = DATA_FLOW_DURATION_SEC + \ + data_flow_delay_sec + SNAPPI_POLL_DELAY_SEC + PAUSE_FLOW_DUR_BASE_SEC + snappi_extra_params.traffic_flow_config.pause_flow_config["flow_traffic_type"] = \ + traffic_flow_mode.FIXED_DURATION + + # Generate test flow config + for m in range(port_map[2]): + generate_sys_test_flows(testbed_config=testbed_config, + test_flow_prio_list=test_prio_list, + prio_dscp_map=prio_dscp_map, + snappi_extra_params=snappi_extra_params, + snap_index=m) + + if (test_def['background_traffic']): + for m in range(port_map[2]): + if snappi_extra_params.gen_background_traffic: + # Generate background flow config + generate_sys_background_flows(testbed_config=testbed_config, + bg_flow_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + snappi_extra_params=snappi_extra_params, + snap_index=m) + + # Generate pause storm config + if (test_traffic_pause): + for m in range(port_map[0]): + generate_sys_pause_flows(testbed_config=testbed_config, + pause_prio_list=pause_prio_list, + global_pause=global_pause, + snappi_extra_params=snappi_extra_params, + snap_index=m) + + flows = testbed_config.flows + + all_flow_names = [flow.name for flow in flows] + data_flow_names = [flow.name for flow in flows if PAUSE_FLOW_NAME not in flow.name] + + # Clear PFC, queue and interface counters before traffic run + for dut in dut_list: + dut.command("pfcstat -c \n") + time.sleep(1) + dut.command("sonic-clear queuecounters \n") + time.sleep(1) + dut.command("sonic-clear counters \n") + time.sleep(1) + + exp_dur_sec = DATA_FLOW_DURATION_SEC + data_flow_delay_sec + + """ Run traffic """ + tgen_flow_stats, switch_flow_stats, test_stats = run_sys_traffic(rx_duthost=rx_dut, + tx_duthost=tx_dut, + api=api, + config=testbed_config, + data_flow_names=data_flow_names, + all_flow_names=all_flow_names, + exp_dur_sec=exp_dur_sec, + port_map=test_def['port_map'], + fname=fname, + stats_interval=test_def['stats_interval'], + imix=test_def['imix'], + snappi_extra_params=snappi_extra_params) + + test_check = test_def['test_check'] + if (not test_check['loss_expected']): + # Check for loss packets on IXIA and DUT. + pytest_assert(test_stats['tgen_loss_pkts'] == 0, 'Loss seen on TGEN') + pytest_assert(test_stats['dut_loss_pkts'] == 0, 'Loss seen on DUT') + + # Check for Tx and Rx packets on IXIA for lossless and lossy streams. + pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['tgen_lossless_tx_pkts'], + 'Losses observed in lossless traffic streams') + pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['tgen_lossy_tx_pkts'], + 'Losses observed in lossy traffic streams') + + # Check for Rx packets between IXIA and DUT for lossy and lossless streams. + pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['dut_lossless_pkts'], + 'Losses observed in lossless traffic streams on DUT Tx and IXIA Rx') + pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['dut_lossy_pkts'], + 'Losses observed in lossy traffic streams on DUT Tx and IXIA Rx') + else: + # Check for lossless and lossy stream percentage drop for a given tolerance limit. + lossless_drop = round((1 - float(test_stats['tgen_lossless_rx_pkts']) / test_stats['tgen_lossless_tx_pkts']), 2) + lossy_drop = round((1 - float(test_stats['tgen_lossy_rx_pkts']) / test_stats['tgen_lossy_tx_pkts']), 2) + logger.info('Lossless Drop %:{}, Lossy Drop %:{}'.format(lossless_drop, lossy_drop)) + pytest_assert((lossless_drop*100) <= test_check['lossless'], 'Lossless packet drop outside tolerance limit') + pytest_assert((lossy_drop*100) <= test_check['lossy'], 'Lossy packet drop outside tolerance limit') + + # Checking if the actual line rate on egress is within tolerable limit of egress line speed. + pytest_assert(((1 - test_stats['tgen_rx_rate'] / float(port_map[0]*port_map[1]))*100) <= test_check['speed_tol'], + 'Egress speed beyond tolerance range') + + # Checking for PFC counts on DUT + if (not test_check['pfc']): + pytest_assert(test_stats['lossless_tx_pfc'] == 0, 'Error:PFC transmitted by DUT for lossless priorities') + pytest_assert(test_stats['lossy_rx_tx_pfc'] == 0, 'Error:PFC transmitted by DUT for lossy priorities') + else: + if (test_stats['lossless_rx_pfc'] != 0 and + (test_def['enable_pfcwd_drop'] or test_def['enable_pfcwd_fwd'])): + pytest_assert(test_stats['lossless_tx_pfc'] == 0, 'Error:No Tx PFCs from DUT after receiving PFCs') + if (test_stats['lossless_rx_pfc'] != 0 and + (not test_def['enable_pfcwd_drop'] and not test_def['enable_pfcwd_fwd'])): + pytest_assert(test_stats['lossless_tx_pfc'] != 0, 'Error:Tx PFCs should sent from DUT after receiving PFCs') + pytest_assert(test_stats['lossy_rx_tx_pfc'] == 0, 'Error:Incorrect Rx/Tx PFCs on DUT for lossy priorities') + + # Reset pfc delay parameter + pfc = testbed_config.layer1[0].flow_control.ieee_802_1qbb + pfc.pfc_delay = 0 + + for metric in tgen_flow_stats: + if "Pause" in metric.name: + PAUSE_FLW_NAME = metric.name + + # Verify pause flows + if (test_traffic_pause): + verify_pause_flow(flow_metrics=tgen_flow_stats, + pause_flow_name=PAUSE_FLW_NAME) + + if (test_def['background_traffic'] and test_def['verify_flows']): + if snappi_extra_params.gen_background_traffic: + # Verify background flows + verify_background_flow(flow_metrics=tgen_flow_stats, + speed_gbps=speed_gbps, + tolerance=TOLERANCE_THRESHOLD, + snappi_extra_params=snappi_extra_params) + + # Verify basic test flows metrics from ixia + if (test_def['verify_flows']): + verify_basic_test_flow(flow_metrics=tgen_flow_stats, + speed_gbps=speed_gbps, + tolerance=TOLERANCE_THRESHOLD, + test_flow_pause=test_traffic_pause, + snappi_extra_params=snappi_extra_params) + + if (test_traffic_pause and test_def['verify_flows']): + verify_pause_frame_count_dut(rx_dut=rx_dut, + tx_dut=tx_dut, + test_traffic_pause=test_traffic_pause, + global_pause=global_pause, + snappi_extra_params=snappi_extra_params) diff --git a/tests/snappi_tests/multidut/systest/test_multiflow_pfcwd.py b/tests/snappi_tests/multidut/systest/test_multiflow_pfcwd.py new file mode 100644 index 00000000000..966922d47bd --- /dev/null +++ b/tests/snappi_tests/multidut/systest/test_multiflow_pfcwd.py @@ -0,0 +1,753 @@ +import pytest +from tests.common.helpers.assertions import pytest_require, pytest_assert # noqa: F401 +from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts # noqa: F401 +from tests.common.snappi_tests.snappi_fixtures import snappi_api_serv_ip, snappi_api_serv_port, \ + snappi_api, snappi_dut_base_config, get_tgen_peer_ports, get_multidut_snappi_ports, \ + get_multidut_tgen_peer_port_set, new_get_multidut_tgen_peer_port_set, cleanup_config # noqa: F401 +from tests.common.snappi_tests.qos_fixtures import prio_dscp_map, \ + lossless_prio_list # noqa: F401 +from tests.common.snappi_tests.common_helpers import get_pfcwd_stats +from tests.snappi_tests.variables import config_set, line_card_choice +from files.pfcwd_multidut_helper import run_pfc_test +import logging +from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams +logger = logging.getLogger(__name__) + +pytestmark = [pytest.mark.topology('multidut-tgen')] + + +@pytest.mark.parametrize('linecard_configuration_set', [config_set]) +@pytest.mark.parametrize('line_card_choice', line_card_choice) +def test_pfcwd_drop_90_10(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + line_card_choice, + linecard_configuration_set, + get_multidut_snappi_ports): # noqa: F811 + + """ + Purpose of the test case is to enable PFCWD in drop mode and send 90% lossless traffic and 10% + lossy traffic and check the behavior. DUT is receiving pause storm on the egress port. DUT should + drop the lossless packets without generating any pause towards IXIA transmitter. No loss for lossy traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + line_card_choice: Line card choice to be mentioned in the variable.py file + linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) + Returns: + N/A + """ + + test_pkt_size = 1024 + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + if '100Gbps' in line_card_choice: + port_map = [1, 100, 1, 100] + else: + port_map = [1, 400, 1, 400] + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 100, 'lossy': 0, 'speed_tol': 91, 'loss_expected': True, 'pfc': True} + + test_def = {} + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 90, + 'BG_FLOW_AGGR_RATE_PERCENT': 10, + 'data_flow_pkt_size': test_pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 1, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/One_Ingress_Egress_pfcwd_drop_90_10_dist'+str(port_map[1])+'Gbps', + 'line_card_choice': line_card_choice, + 'port_map': port_map, + 'enable_pfcwd_drop': True, + 'enable_pfcwd_fwd': False, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'verify_flows': False, + 'imix': False, + 'test_check': test_check} + + logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) + if line_card_choice not in linecard_configuration_set.keys(): + assert False, "Invalid line_card_choice value passed in parameter" + + if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): + dut_list = [dut for dut in duthosts + if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] + duthost1, duthost2 = dut_list + elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): + dut_list = [dut for dut in duthosts + if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] + duthost1 = duthost2 = dut_list[0] + else: + assert False, "Hostname can't be an empty list" + + snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, + line_card_info=linecard_configuration_set[line_card_choice]) + + if len(snappi_port_list) < 2: + assert False, "Need Minimum of 2 ports for the test" + + snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) + + if len(snappi_ports) < 2: + assert False, "Need Minimum of 2 ports for the test" + + testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, + snappi_ports, + snappi_api) + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = [0, 1, 2] + logger.info("Snappi Ports : {}".format(snappi_ports)) + + logger.info('PFC-WD stats at the start of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut_list[0].hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut.hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = duthost1 + snappi_extra_params.multi_dut_params.duthost2 = duthost2 + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=True, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + logger.info('PFC-WD stats at the end of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) + + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('linecard_configuration_set', [config_set]) +@pytest.mark.parametrize('line_card_choice', line_card_choice) +def test_pfcwd_frwd_90_10(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + line_card_choice, + linecard_configuration_set, + get_multidut_snappi_ports): # noqa: F811 + + """ + Purpose of the test case is to check behavior of the DUT when PFCWD is enabled in FORWARD mode and egress port + is congested with PAUSE storm. DUT in this mode should forward the lossless packets irrespective of the pause + storm and not send any PAUSE frames towards IXIA transmitter. No effect on lossy traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + line_card_choice: Line card choice to be mentioned in the variable.py file + linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) + Returns: + N/A + """ + + test_pkt_size = 1024 + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + if '100Gbps' in line_card_choice: + port_map = [1, 100, 1, 100] + else: + port_map = [1, 400, 1, 400] + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': True} + + test_def = {} + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 90, + 'BG_FLOW_AGGR_RATE_PERCENT': 10, + 'data_flow_pkt_size': test_pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 1, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/One_Ingress_Egress_pfcwd_frwd_90_10_dist'+str(port_map[1])+'Gbps', + 'line_card_choice': line_card_choice, + 'port_map': port_map, + 'enable_pfcwd_drop': False, + 'enable_pfcwd_fwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'verify_flows': False, + 'imix': False, + 'test_check': test_check} + + logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) + if line_card_choice not in linecard_configuration_set.keys(): + assert False, "Invalid line_card_choice value passed in parameter" + + if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): + dut_list = [dut for dut in duthosts + if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] + duthost1, duthost2 = dut_list + elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): + dut_list = [dut for dut in duthosts + if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] + duthost1 = duthost2 = dut_list[0] + else: + assert False, "Hostname can't be an empty list" + + snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, + line_card_info=linecard_configuration_set[line_card_choice]) + + if len(snappi_port_list) < 2: + assert False, "Need Minimum of 2 ports for the test" + + snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) + + if len(snappi_ports) < 2: + assert False, "Need Minimum of 2 ports for the test" + + testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, + snappi_ports, + snappi_api) + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = [0, 1, 2] + logger.info("Snappi Ports : {}".format(snappi_ports)) + + logger.info('PFC-WD stats at the start of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut_list[0].hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut.hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = duthost1 + snappi_extra_params.multi_dut_params.duthost2 = duthost2 + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=True, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + logger.info('PFC-WD stats at the end of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) + + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('linecard_configuration_set', [config_set]) +@pytest.mark.parametrize('line_card_choice', line_card_choice) +def test_pfcwd_drop_over_subs_40_09(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + line_card_choice, + linecard_configuration_set, + get_multidut_snappi_ports): # noqa: F811 + + """ + Purpose of the testcase is to check PFCWD behavior in DROP mode with over-subscription. + Each ingress is sending 49% of link capacity traffic and DUT is receiving PAUSE storm on egress link. + DUT should drop lossless packets. No drop for lossy traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + line_card_choice: Line card choice to be mentioned in the variable.py file + linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) + Returns: + N/A + + """ + test_pkt_size = 1024 + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + if '100Gbps' in line_card_choice: + port_map = [1, 100, 2, 100] + else: + port_map = [1, 400, 2, 400] + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 100, 'lossy': 0, 'speed_tol': 83, 'loss_expected': True, 'pfc': True} + + test_def = {} + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, + 'BG_FLOW_AGGR_RATE_PERCENT': 9, + 'data_flow_pkt_size': test_pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 1, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Two_Ingress_Single_Egress_pfcwd_drop_40_9_dist'+str(port_map[1])+'Gbps', + 'line_card_choice': line_card_choice, + 'port_map': port_map, + 'enable_pfcwd_drop': True, + 'enable_pfcwd_fwd': False, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'verify_flows': False, + 'imix': False, + 'test_check': test_check} + + logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) + if line_card_choice not in linecard_configuration_set.keys(): + assert False, "Invalid line_card_choice value passed in parameter" + + if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): + dut_list = [dut for dut in duthosts + if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] + duthost1, duthost2 = dut_list + elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): + dut_list = [dut for dut in duthosts + if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] + duthost1 = duthost2 = dut_list[0] + else: + assert False, "Hostname can't be an empty list" + + snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, + line_card_info=linecard_configuration_set[line_card_choice]) + + if len(snappi_port_list) < 3: + assert False, "Need Minimum of 3 ports for the test" + + snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) + + if len(snappi_ports) < 3: + assert False, "Need Minimum of 3 ports for the test" + + testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, + snappi_ports, + snappi_api) + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = [0, 1, 2] + logger.info("Snappi Ports : {}".format(snappi_ports)) + + logger.info('PFC-WD stats at the start of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut_list[0].hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut.hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = duthost1 + snappi_extra_params.multi_dut_params.duthost2 = duthost2 + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=True, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + logger.info('PFC-WD stats at the end of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('linecard_configuration_set', [config_set]) +@pytest.mark.parametrize('line_card_choice', line_card_choice) +def test_pfcwd_frwd_over_subs_40_09(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + line_card_choice, + linecard_configuration_set, + get_multidut_snappi_ports): # noqa: F811 + + """ + Purpose of testcase is to test behavior of DUT in PFCWD-FORWARD mode in oversubscription mode. + Each ingress is sending 49% of link capacity traffic and DUT is receiving PAUSE storm on egress link. + DUT should forward for both lossy and lossless traffic without generating PAUSE frames towards IXIA + transmitter. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + line_card_choice: Line card choice to be mentioned in the variable.py file + linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) + Returns: + N/A + """ + + test_pkt_size = 1024 + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + if '100Gbps' in line_card_choice: + port_map = [1, 100, 2, 100] + else: + port_map = [1, 400, 2, 400] + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': True} + + test_def = {} + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, + 'BG_FLOW_AGGR_RATE_PERCENT': 9, + 'data_flow_pkt_size': test_pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 1, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Two_Ingress_Single_Egress_pfcwd_frwd_40_9_dist'+str(port_map[1])+'Gbps', + 'line_card_choice': line_card_choice, + 'port_map': port_map, + 'enable_pfcwd_drop': False, + 'enable_pfcwd_fwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'verify_flows': False, + 'imix': False, + 'test_check': test_check} + + logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) + if line_card_choice not in linecard_configuration_set.keys(): + assert False, "Invalid line_card_choice value passed in parameter" + + if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): + dut_list = [dut for dut in duthosts + if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] + duthost1, duthost2 = dut_list + elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): + dut_list = [dut for dut in duthosts + if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] + duthost1 = duthost2 = dut_list[0] + else: + assert False, "Hostname can't be an empty list" + + snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, + line_card_info=linecard_configuration_set[line_card_choice]) + + if len(snappi_port_list) < 3: + assert False, "Need Minimum of 3 ports for the test" + + snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) + + if len(snappi_ports) < 3: + assert False, "Need Minimum of 3 ports for the test" + + testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, + snappi_ports, + snappi_api) + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = [0, 1, 2] + logger.info("Snappi Ports : {}".format(snappi_ports)) + + logger.info('PFC-WD stats at the start of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut_list[0].hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut.hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = duthost1 + snappi_extra_params.multi_dut_params.duthost2 = duthost2 + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=True, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + logger.info('PFC-WD stats at the end of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('linecard_configuration_set', [config_set]) +@pytest.mark.parametrize('line_card_choice', line_card_choice) +def test_pfcwd_disable_pause_cngtn(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + line_card_choice, + linecard_configuration_set, + get_multidut_snappi_ports): # noqa: F811 + + """ + Purpose of the test case is to test oversubscription with two ingresses and single ingress. + Traffic pattern has 18% lossless priority and 27% lossy priority traffic. + Total ingress link is sending only 45% link capacity and hence egress will not be congested. + No losses for both lossless and lossy priority traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + line_card_choice: Line card choice to be mentioned in the variable.py file + linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) + Returns: + N/A + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + if '100Gbps' in line_card_choice: + port_map = [1, 100, 1, 100] + else: + port_map = [1, 400, 1, 400] + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 41, 'loss_expected': False, 'pfc': True} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, + 'BG_FLOW_AGGR_RATE_PERCENT': 60, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 1, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Single_Ingress_Single_Egress_pause_cngstn_'+str(port_map[1])+'Gbps', + 'line_card_choice': line_card_choice, + 'port_map': port_map, + 'enable_pfcwd_drop': False, + 'enable_pfcwd_fwd': False, + 'enable_credit_wd': False, + 'stats_interval': 60, + 'background_traffic': True, + 'verify_flows': False, + 'imix': False, + 'test_check': test_check} + + logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) + if line_card_choice not in linecard_configuration_set.keys(): + assert False, "Invalid line_card_choice value passed in parameter" + + if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): + dut_list = [dut for dut in duthosts + if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] + duthost1, duthost2 = dut_list + elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): + dut_list = [dut for dut in duthosts + if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] + duthost1 = duthost2 = dut_list[0] + else: + assert False, "Hostname can't be an empty list" + + snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, + line_card_info=linecard_configuration_set[line_card_choice]) + + if len(snappi_port_list) < 2: + assert False, "snappi_port_list: Need Minimum of 2 ports for the test" + + # port_map is read as egress port_map[0] links of port_map[1] speed + # and ingress port_map[2] links of port_map[3] speed + port_map = test_def['port_map'] + + snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) + + if len(snappi_ports) < 2: + assert False, "snappi_ports: Need Minimum of 2 ports for the test" + + testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, + snappi_ports, + snappi_api) + + test_prio_list = [3, 4] + pause_prio_list = test_prio_list + bg_prio_list = [0, 1, 2] + logger.info("Snappi Ports : {}".format(snappi_ports)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = duthost1 + snappi_extra_params.multi_dut_params.duthost2 = duthost2 + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=True, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + finally: + cleanup_config(dut_list, snappi_ports) From 7532b0f645628ba11b18cc5a85d96bc4cf572b53 Mon Sep 17 00:00:00 2001 From: amitpawa Date: Mon, 7 Oct 2024 17:14:33 -0400 Subject: [PATCH 05/12] removed older-test case files --- .../systest/files/pfcwd_multidut_helper.py | 373 --------- .../systest/files/sys_multidut_helper.py | 385 --------- .../multidut/systest/test_multiflow_pfcwd.py | 753 ------------------ .../systest/test_non_congestion_imix.py | 395 --------- .../systest/test_over_subscription_imix.py | 515 ------------ 5 files changed, 2421 deletions(-) delete mode 100644 tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py delete mode 100644 tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py delete mode 100644 tests/snappi_tests/multidut/systest/test_multiflow_pfcwd.py delete mode 100644 tests/snappi_tests/multidut/systest/test_non_congestion_imix.py delete mode 100644 tests/snappi_tests/multidut/systest/test_over_subscription_imix.py diff --git a/tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py b/tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py deleted file mode 100644 index e63ebd381b8..00000000000 --- a/tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py +++ /dev/null @@ -1,373 +0,0 @@ -import logging -import time - -from tests.common.helpers.assertions import pytest_assert -from tests.common.fixtures.conn_graph_facts import conn_graph_facts,\ - fanout_graph_facts # noqa F401 -from tests.common.snappi_tests.common_helpers import pfc_class_enable_vector,\ - get_lossless_buffer_size, get_pg_dropped_packets,\ - stop_pfcwd, disable_packet_aging, sec_to_nanosec,\ - get_pfc_frame_count, packet_capture, config_capture_pkt,\ - start_pfcwd, enable_packet_aging, start_pfcwd_fwd, \ - traffic_flow_mode, calc_pfc_pause_flow_rate # noqa F401 -from tests.common.snappi_tests.traffic_generation import verify_pause_flow, \ - verify_basic_test_flow, verify_background_flow, verify_pause_frame_count_dut, \ - run_sys_traffic, new_base_traffic_config, \ - generate_sys_test_flows, generate_sys_background_flows, generate_sys_pause_flows -from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams - - -logger = logging.getLogger(__name__) - -dut_port_config = [] -PAUSE_FLOW_NAME = 'Pause Storm' -TEST_FLOW_NAME = 'Test Flow' -BG_FLOW_NAME = 'Background Flow' -TOLERANCE_THRESHOLD = 0.1 -CONTINUOUS_MODE = -5 -ANSIBLE_POLL_DELAY_SEC = 4 -global DATA_FLOW_DURATION_SEC -global data_flow_delay_sec - - -def run_pfc_test(api, - testbed_config, - port_config_list, - conn_data, - fanout_data, - global_pause, - pause_prio_list, - test_prio_list, - bg_prio_list, - prio_dscp_map, - test_traffic_pause, - test_def, - snappi_extra_params=None): - """ - Run a multidut PFC test - Args: - api (obj): snappi session - testbed_config (obj): testbed L1/L2/L3 configuration - port_config_list (list): list of port configuration - conn_data (dict): the dictionary returned by conn_graph_fact. - fanout_data (dict): the dictionary returned by fanout_graph_fact. - duthost (Ansible host instance): device under test - dut_port (str): DUT port to test - global_pause (bool): if pause frame is IEEE 802.3X pause - pause_prio_list (list): priorities to pause for pause frames - test_prio_list (list): priorities of test flows - bg_prio_list (list): priorities of background flows - prio_dscp_map (dict): Priority vs. DSCP map (key = priority). - test_traffic_pause (bool): if test flows are expected to be paused - test_def['enable_pause'] (bool) : if test expects no pause flow traffic. - snappi_extra_params (SnappiSysTestParams obj): additional parameters for Snappi traffic - - Returns: - N/A - """ - - TEST_FLOW_AGGR_RATE_PERCENT = test_def['TEST_FLOW_AGGR_RATE_PERCENT'] - BG_FLOW_AGGR_RATE_PERCENT = test_def['BG_FLOW_AGGR_RATE_PERCENT'] - data_flow_pkt_size = test_def['data_flow_pkt_size'] - DATA_FLOW_DURATION_SEC = test_def['DATA_FLOW_DURATION_SEC'] - data_flow_delay_sec = test_def['data_flow_delay_sec'] - SNAPPI_POLL_DELAY_SEC = test_def['SNAPPI_POLL_DELAY_SEC'] - PAUSE_FLOW_DUR_BASE_SEC = data_flow_delay_sec + DATA_FLOW_DURATION_SEC - if test_def['imix']: - fname = test_def['test_type'] + '_' + test_def['line_card_choice'] + '_' + 'IMIX' - else: - fname = test_def['test_type'] + '_' + test_def['line_card_choice'] + '_' + str(data_flow_pkt_size) + 'B' - - port_map = test_def['port_map'] - - if snappi_extra_params is None: - snappi_extra_params = SnappiSysTestParams() - - duthost1 = snappi_extra_params.multi_dut_params.duthost1 - rx_port = snappi_extra_params.multi_dut_params.multi_dut_ports[0] - duthost2 = snappi_extra_params.multi_dut_params.duthost2 - tx_port = snappi_extra_params.multi_dut_params.multi_dut_ports[-1] - dut_list = [] - dut_list.append(duthost1) - dut_list.append(duthost2) - - tx_dut = duthost1 - rx_dut = duthost2 - - if rx_port['peer_device'] == duthost1.hostname: - tx_dut = duthost2 - rx_dut = duthost1 - - if (test_traffic_pause): - logger.info("PFC receiving DUT is {}".format(tx_dut.hostname)) - - pytest_assert(testbed_config is not None, 'Fail to get L2/3 testbed config') - - if (test_def['enable_pfcwd_drop']): - start_pfcwd(rx_dut) - start_pfcwd(tx_dut) - elif (test_def['enable_pfcwd_fwd']): - start_pfcwd_fwd(rx_dut) - start_pfcwd_fwd(tx_dut) - else: - stop_pfcwd(rx_dut) - stop_pfcwd(tx_dut) - - if (test_def['enable_credit_wd']): - enable_packet_aging(rx_dut, rx_port['asic_value']) - enable_packet_aging(tx_dut, tx_port['asic_value']) - else: - disable_packet_aging(rx_dut, rx_port['asic_value']) - disable_packet_aging(tx_dut, tx_port['asic_value']) - - rx_port_id = 0 - - # Rate percent must be an integer - bg_flow_rate_percent = int(BG_FLOW_AGGR_RATE_PERCENT / len(bg_prio_list)) - test_flow_rate_percent = int(TEST_FLOW_AGGR_RATE_PERCENT / len(test_prio_list)) - # Generate base traffic config - if (port_map[0] == 2): - for i in range(port_map[0]): - rx_port_id = i - tx_port_id = 2 - snappi_extra_params.base_flow_config.append(new_base_traffic_config(testbed_config=testbed_config, - port_config_list=port_config_list, - rx_port_id=rx_port_id, - tx_port_id=tx_port_id)) - else: - rx_port_id = 0 - for i in range(port_map[2]): - tx_port_id = i+1 - snappi_extra_params.base_flow_config.append(new_base_traffic_config(testbed_config=testbed_config, - port_config_list=port_config_list, - rx_port_id=rx_port_id, - tx_port_id=tx_port_id)) - - speed_str = testbed_config.layer1[0].speed - speed_gbps = int(speed_str.split('_')[1]) - - if snappi_extra_params.headroom_test_params is not None: - DATA_FLOW_DURATION_SEC += 10 - data_flow_delay_sec += 2 - - # Set up pfc delay parameter - l1_config = testbed_config.layer1[0] - pfc = l1_config.flow_control.ieee_802_1qbb - pfc.pfc_delay = snappi_extra_params.headroom_test_params[0] - - if snappi_extra_params.poll_device_runtime: - # If the switch needs to be polled as traffic is running for stats, - # then the test runtime needs to be increased for the polling delay - DATA_FLOW_DURATION_SEC += ANSIBLE_POLL_DELAY_SEC - data_flow_delay_sec = ANSIBLE_POLL_DELAY_SEC - - if snappi_extra_params.packet_capture_type != packet_capture.NO_CAPTURE: - # Setup capture config - if snappi_extra_params.is_snappi_ingress_port_cap: - # packet capture is required on the ingress snappi port - snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["rx_port_name"]] - else: - # packet capture will be on the egress snappi port - snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["tx_port_name"]] - - snappi_extra_params.packet_capture_file = snappi_extra_params.packet_capture_type.value - - config_capture_pkt(testbed_config=testbed_config, - port_names=snappi_extra_params.packet_capture_ports, - capture_type=snappi_extra_params.packet_capture_type, - capture_name=snappi_extra_params.packet_capture_file) - logger.info("Packet capture file: {}.pcapng".format(snappi_extra_params.packet_capture_file)) - - # Set default traffic flow configs if not set - if snappi_extra_params.traffic_flow_config.data_flow_config is None: - snappi_extra_params.traffic_flow_config.data_flow_config = { - "flow_name": TEST_FLOW_NAME, - "flow_dur_sec": DATA_FLOW_DURATION_SEC, - "flow_rate_percent": test_flow_rate_percent, - "flow_rate_pps": None, - "flow_rate_bps": None, - "flow_pkt_count": None, - "flow_pkt_size": data_flow_pkt_size, - "flow_delay_sec": data_flow_delay_sec, - "flow_traffic_type": traffic_flow_mode.FIXED_DURATION - } - - if snappi_extra_params.traffic_flow_config.background_flow_config is None and \ - snappi_extra_params.gen_background_traffic: - snappi_extra_params.traffic_flow_config.background_flow_config = { - "flow_name": BG_FLOW_NAME, - "flow_dur_sec": DATA_FLOW_DURATION_SEC, - "flow_rate_percent": bg_flow_rate_percent, - "flow_rate_pps": None, - "flow_rate_bps": None, - "flow_pkt_size": data_flow_pkt_size, - "flow_pkt_count": None, - "flow_delay_sec": data_flow_delay_sec, - "flow_traffic_type": traffic_flow_mode.FIXED_DURATION - } - - # PPS is high to ensure Storm is detected. - # traffic_flow_mode is changed to BURST - # Need to check how it works - if (test_traffic_pause): - if snappi_extra_params.traffic_flow_config.pause_flow_config is None: - snappi_extra_params.traffic_flow_config.pause_flow_config = { - "flow_name": PAUSE_FLOW_NAME, - "flow_dur_sec": DATA_FLOW_DURATION_SEC+60, - "flow_rate_percent": None, - "flow_rate_pps": calc_pfc_pause_flow_rate(speed_gbps), - "flow_rate_bps": None, - "flow_pkt_size": 64, - "flow_pkt_count": None, - "flow_delay_sec": 0, - "flow_traffic_type": traffic_flow_mode.FIXED_DURATION - } - - if snappi_extra_params.packet_capture_type == packet_capture.PFC_CAPTURE: - # PFC pause frame capture is requested - valid_pfc_frame_test = True - else: - # PFC pause frame capture is not requested - valid_pfc_frame_test = False - - if (test_traffic_pause): - if valid_pfc_frame_test: - snappi_extra_params.traffic_flow_config.pause_flow_config["flow_dur_sec"] = DATA_FLOW_DURATION_SEC + \ - data_flow_delay_sec + SNAPPI_POLL_DELAY_SEC + PAUSE_FLOW_DUR_BASE_SEC - snappi_extra_params.traffic_flow_config.pause_flow_config["flow_traffic_type"] = \ - traffic_flow_mode.FIXED_DURATION - - # Generate test flow config - for m in range(port_map[2]): - generate_sys_test_flows(testbed_config=testbed_config, - test_flow_prio_list=test_prio_list, - prio_dscp_map=prio_dscp_map, - snappi_extra_params=snappi_extra_params, - snap_index=m) - - if (test_def['background_traffic']): - for m in range(port_map[2]): - if snappi_extra_params.gen_background_traffic: - # Generate background flow config - generate_sys_background_flows(testbed_config=testbed_config, - bg_flow_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - snappi_extra_params=snappi_extra_params, - snap_index=m) - - # Generate pause storm config - if (test_traffic_pause): - for m in range(port_map[0]): - generate_sys_pause_flows(testbed_config=testbed_config, - pause_prio_list=pause_prio_list, - global_pause=global_pause, - snappi_extra_params=snappi_extra_params, - snap_index=m) - - flows = testbed_config.flows - - all_flow_names = [flow.name for flow in flows] - data_flow_names = [flow.name for flow in flows if PAUSE_FLOW_NAME not in flow.name] - - # Clear PFC, queue and interface counters before traffic run - for dut in dut_list: - dut.command("pfcstat -c \n") - time.sleep(1) - dut.command("sonic-clear queuecounters \n") - time.sleep(1) - dut.command("sonic-clear counters \n") - time.sleep(1) - - exp_dur_sec = DATA_FLOW_DURATION_SEC + data_flow_delay_sec - - """ Run traffic """ - tgen_flow_stats, switch_flow_stats, test_stats = run_sys_traffic(rx_duthost=rx_dut, - tx_duthost=tx_dut, - api=api, - config=testbed_config, - data_flow_names=data_flow_names, - all_flow_names=all_flow_names, - exp_dur_sec=exp_dur_sec, - port_map=test_def['port_map'], - fname=fname, - stats_interval=test_def['stats_interval'], - imix=test_def['imix'], - snappi_extra_params=snappi_extra_params) - - test_check = test_def['test_check'] - if (not test_check['loss_expected']): - # Check for loss packets on IXIA and DUT. - pytest_assert(test_stats['tgen_loss_pkts'] == 0, 'Loss seen on TGEN') - pytest_assert(test_stats['dut_loss_pkts'] == 0, 'Loss seen on DUT') - - # Check for Tx and Rx packets on IXIA for lossless and lossy streams. - pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['tgen_lossless_tx_pkts'], - 'Losses observed in lossless traffic streams') - pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['tgen_lossy_tx_pkts'], - 'Losses observed in lossy traffic streams') - - # Check for Rx packets between IXIA and DUT for lossy and lossless streams. - pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['dut_lossless_pkts'], - 'Losses observed in lossless traffic streams on DUT Tx and IXIA Rx') - pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['dut_lossy_pkts'], - 'Losses observed in lossy traffic streams on DUT Tx and IXIA Rx') - else: - # Check for lossless and lossy stream percentage drop for a given tolerance limit. - lossless_drop = round((1 - float(test_stats['tgen_lossless_rx_pkts']) / test_stats['tgen_lossless_tx_pkts']), 2) - lossy_drop = round((1 - float(test_stats['tgen_lossy_rx_pkts']) / test_stats['tgen_lossy_tx_pkts']), 2) - logger.info('Lossless Drop %:{}, Lossy Drop %:{}'.format(lossless_drop, lossy_drop)) - pytest_assert((lossless_drop*100) <= test_check['lossless'], 'Lossless packet drop outside tolerance limit') - pytest_assert((lossy_drop*100) <= test_check['lossy'], 'Lossy packet drop outside tolerance limit') - - # Checking if the actual line rate on egress is within tolerable limit of egress line speed. - pytest_assert(((1 - test_stats['tgen_rx_rate'] / float(port_map[0]*port_map[1]))*100) <= test_check['speed_tol'], - 'Egress speed beyond tolerance range') - - # Checking for PFC counts on DUT - if (not test_check['pfc']): - pytest_assert(test_stats['lossless_tx_pfc'] == 0, 'Error:PFC transmitted by DUT for lossless priorities') - pytest_assert(test_stats['lossy_rx_tx_pfc'] == 0, 'Error:PFC transmitted by DUT for lossy priorities') - else: - if (test_stats['lossless_rx_pfc'] != 0 and - (test_def['enable_pfcwd_drop'] or test_def['enable_pfcwd_fwd'])): - pytest_assert(test_stats['lossless_tx_pfc'] == 0, 'Error:No Tx PFCs from DUT after receiving PFCs') - if (test_stats['lossless_rx_pfc'] != 0 and - (not test_def['enable_pfcwd_drop'] and not test_def['enable_pfcwd_fwd'])): - pytest_assert(test_stats['lossless_tx_pfc'] != 0, 'Error:Tx PFCs should sent from DUT after receiving PFCs') - pytest_assert(test_stats['lossy_rx_tx_pfc'] == 0, 'Error:Incorrect Rx/Tx PFCs on DUT for lossy priorities') - - # Reset pfc delay parameter - pfc = testbed_config.layer1[0].flow_control.ieee_802_1qbb - pfc.pfc_delay = 0 - - for metric in tgen_flow_stats: - if "Pause" in metric.name: - PAUSE_FLW_NAME = metric.name - - # Verify pause flows - if (test_traffic_pause): - verify_pause_flow(flow_metrics=tgen_flow_stats, - pause_flow_name=PAUSE_FLW_NAME) - - if (test_def['background_traffic'] and test_def['verify_flows']): - if snappi_extra_params.gen_background_traffic: - # Verify background flows - verify_background_flow(flow_metrics=tgen_flow_stats, - speed_gbps=speed_gbps, - tolerance=TOLERANCE_THRESHOLD, - snappi_extra_params=snappi_extra_params) - - # Verify basic test flows metrics from ixia - if (test_def['verify_flows']): - verify_basic_test_flow(flow_metrics=tgen_flow_stats, - speed_gbps=speed_gbps, - tolerance=TOLERANCE_THRESHOLD, - test_flow_pause=test_traffic_pause, - snappi_extra_params=snappi_extra_params) - - if (test_traffic_pause and test_def['verify_flows']): - verify_pause_frame_count_dut(rx_dut=rx_dut, - tx_dut=tx_dut, - test_traffic_pause=test_traffic_pause, - global_pause=global_pause, - snappi_extra_params=snappi_extra_params) diff --git a/tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py b/tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py deleted file mode 100644 index 820cd1d7e19..00000000000 --- a/tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py +++ /dev/null @@ -1,385 +0,0 @@ -import logging -import time - -from tests.common.helpers.assertions import pytest_assert -from tests.common.fixtures.conn_graph_facts import conn_graph_facts,\ - fanout_graph_facts # noqa F401 -from tests.common.snappi_tests.common_helpers import pfc_class_enable_vector,\ - get_lossless_buffer_size, get_pg_dropped_packets,\ - stop_pfcwd, disable_packet_aging, sec_to_nanosec,\ - get_pfc_frame_count, packet_capture, config_capture_pkt,\ - start_pfcwd, enable_packet_aging, \ - traffic_flow_mode, calc_pfc_pause_flow_rate # noqa F401 -from tests.common.snappi_tests.port import select_ports, select_tx_port # noqa F401 -from tests.common.snappi_tests.snappi_helpers import wait_for_arp # noqa F401 -from tests.common.snappi_tests.traffic_generation import generate_pause_flows, verify_pause_flow, \ - verify_basic_test_flow, verify_background_flow, verify_pause_frame_count_dut, verify_sys_egress_queue_count, \ - verify_unset_cev_pause_frame_count, verify_tx_frame_count_dut, \ - verify_rx_frame_count_dut, run_sys_traffic, new_base_traffic_config, \ - generate_sys_test_flows, generate_sys_background_flows -from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams -from tests.common.snappi_tests.read_pcap import validate_pfc_frame - -logger = logging.getLogger(__name__) - -dut_port_config = [] -PAUSE_FLOW_NAME = 'Pause Storm' -TEST_FLOW_NAME = 'Test Flow' -BG_FLOW_NAME = 'Background Flow' -TOLERANCE_THRESHOLD = 0.1 -CONTINUOUS_MODE = -5 -ANSIBLE_POLL_DELAY_SEC = 4 -global DATA_FLOW_DURATION_SEC -global data_flow_delay_sec - - -def run_pfc_test(api, - testbed_config, - port_config_list, - conn_data, - fanout_data, - global_pause, - pause_prio_list, - test_prio_list, - bg_prio_list, - prio_dscp_map, - test_traffic_pause, - test_def, - snappi_extra_params=None): - """ - Run a multidut PFC test - Args: - api (obj): snappi session - testbed_config (obj): testbed L1/L2/L3 configuration - port_config_list (list): list of port configuration - conn_data (dict): the dictionary returned by conn_graph_fact. - fanout_data (dict): the dictionary returned by fanout_graph_fact. - duthost (Ansible host instance): device under test - dut_port (str): DUT port to test - global_pause (bool): if pause frame is IEEE 802.3X pause - pause_prio_list (list): priorities to pause for pause frames - test_prio_list (list): priorities of test flows - bg_prio_list (list): priorities of background flows - prio_dscp_map (dict): Priority vs. DSCP map (key = priority). - test_traffic_pause (bool): if test flows are expected to be paused - test_def['enable_pause'] (bool) : if test expects no pause flow traffic. - snappi_extra_params (SnappiSysTestParams obj): additional parameters for Snappi traffic - - Returns: - N/A - """ - - TEST_FLOW_AGGR_RATE_PERCENT = test_def['TEST_FLOW_AGGR_RATE_PERCENT'] - BG_FLOW_AGGR_RATE_PERCENT = test_def['BG_FLOW_AGGR_RATE_PERCENT'] - data_flow_pkt_size = test_def['data_flow_pkt_size'] - DATA_FLOW_DURATION_SEC = test_def['DATA_FLOW_DURATION_SEC'] - data_flow_delay_sec = test_def['data_flow_delay_sec'] - SNAPPI_POLL_DELAY_SEC = test_def['SNAPPI_POLL_DELAY_SEC'] - PAUSE_FLOW_DUR_BASE_SEC = data_flow_delay_sec + DATA_FLOW_DURATION_SEC - if test_def['imix']: - fname = test_def['test_type'] + '_' + test_def['line_card_choice'] + '_' + 'IMIX' - else: - fname = test_def['test_type'] + '_' + test_def['line_card_choice'] + '_' + str(data_flow_pkt_size) + 'B' - port_map = test_def['port_map'] - - if snappi_extra_params is None: - snappi_extra_params = SnappiSysTestParams() - - duthost1 = snappi_extra_params.multi_dut_params.duthost1 - rx_port = snappi_extra_params.multi_dut_params.multi_dut_ports[0] - duthost2 = snappi_extra_params.multi_dut_params.duthost2 - tx_port = snappi_extra_params.multi_dut_params.multi_dut_ports[-1] - dut_list = [] - dut_list.append(duthost1) - dut_list.append(duthost2) - - tx_dut = duthost1 - rx_dut = duthost2 - if (rx_port['peer_device'] == duthost1.hostname): - tx_dut = duthost2 - rx_dut = duthost1 - - if (test_traffic_pause): - logger.info("PFC receiving DUT is {}".format(tx_dut.hostname)) - - pytest_assert(testbed_config is not None, 'Fail to get L2/3 testbed config') - - if (test_def['enable_pfcwd']): - start_pfcwd(rx_dut) - start_pfcwd(tx_dut) - else: - stop_pfcwd(rx_dut) - stop_pfcwd(tx_dut) - - if (test_def['enable_credit_wd']): - enable_packet_aging(rx_dut, rx_port['asic_value']) - enable_packet_aging(tx_dut, tx_port['asic_value']) - else: - disable_packet_aging(rx_dut, rx_port['asic_value']) - disable_packet_aging(tx_dut, tx_port['asic_value']) - - # Port id of Rx port for traffic config - # rx_port_id and tx_port_id belong to IXIA chassis. - rx_port_id = 0 - - # Rate percent must be an integer - bg_flow_rate_percent = int(BG_FLOW_AGGR_RATE_PERCENT / len(bg_prio_list)) - test_flow_rate_percent = int(TEST_FLOW_AGGR_RATE_PERCENT / len(test_prio_list)) - # Generate base traffic config - for i in range(port_map[2]): - tx_port_id = i+1 - snappi_extra_params.base_flow_config.append(new_base_traffic_config(testbed_config=testbed_config, - port_config_list=port_config_list, - rx_port_id=rx_port_id, - tx_port_id=tx_port_id)) - - speed_str = testbed_config.layer1[0].speed - speed_gbps = int(speed_str.split('_')[1]) - - if snappi_extra_params.headroom_test_params is not None: - DATA_FLOW_DURATION_SEC += 10 - data_flow_delay_sec += 2 - - # Set up pfc delay parameter - l1_config = testbed_config.layer1[0] - pfc = l1_config.flow_control.ieee_802_1qbb - pfc.pfc_delay = snappi_extra_params.headroom_test_params[0] - - if snappi_extra_params.poll_device_runtime: - # If the switch needs to be polled as traffic is running for stats, - # then the test runtime needs to be increased for the polling delay - DATA_FLOW_DURATION_SEC += ANSIBLE_POLL_DELAY_SEC - data_flow_delay_sec = ANSIBLE_POLL_DELAY_SEC - - if snappi_extra_params.packet_capture_type != packet_capture.NO_CAPTURE: - # Setup capture config - if snappi_extra_params.is_snappi_ingress_port_cap: - # packet capture is required on the ingress snappi port - snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["rx_port_name"]] - else: - # packet capture will be on the egress snappi port - snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["tx_port_name"]] - - snappi_extra_params.packet_capture_file = snappi_extra_params.packet_capture_type.value - - config_capture_pkt(testbed_config=testbed_config, - port_names=snappi_extra_params.packet_capture_ports, - capture_type=snappi_extra_params.packet_capture_type, - capture_name=snappi_extra_params.packet_capture_file) - logger.info("Packet capture file: {}.pcapng".format(snappi_extra_params.packet_capture_file)) - - # Set default traffic flow configs if not set - if snappi_extra_params.traffic_flow_config.data_flow_config is None: - snappi_extra_params.traffic_flow_config.data_flow_config = { - "flow_name": TEST_FLOW_NAME, - "flow_dur_sec": DATA_FLOW_DURATION_SEC, - "flow_rate_percent": test_flow_rate_percent, - "flow_rate_pps": None, - "flow_rate_bps": None, - "flow_pkt_count": None, - "flow_pkt_size": data_flow_pkt_size, - "flow_delay_sec": data_flow_delay_sec, - "flow_traffic_type": traffic_flow_mode.FIXED_DURATION - } - - if snappi_extra_params.traffic_flow_config.background_flow_config is None and \ - snappi_extra_params.gen_background_traffic: - snappi_extra_params.traffic_flow_config.background_flow_config = { - "flow_name": BG_FLOW_NAME, - "flow_dur_sec": DATA_FLOW_DURATION_SEC, - "flow_rate_percent": bg_flow_rate_percent, - "flow_rate_pps": None, - "flow_rate_bps": None, - "flow_pkt_size": data_flow_pkt_size, - "flow_pkt_count": None, - "flow_delay_sec": data_flow_delay_sec, - "flow_traffic_type": traffic_flow_mode.FIXED_DURATION - } - - if (test_traffic_pause): - if snappi_extra_params.traffic_flow_config.pause_flow_config is None: - snappi_extra_params.traffic_flow_config.pause_flow_config = { - "flow_name": PAUSE_FLOW_NAME, - "flow_dur_sec": None, - "flow_rate_percent": None, - "flow_rate_pps": calc_pfc_pause_flow_rate(speed_gbps), - "flow_rate_bps": None, - "flow_pkt_size": 64, - "flow_pkt_count": None, - "flow_delay_sec": 0, - "flow_traffic_type": traffic_flow_mode.CONTINUOUS - } - - if snappi_extra_params.packet_capture_type == packet_capture.PFC_CAPTURE: - # PFC pause frame capture is requested - valid_pfc_frame_test = True - else: - # PFC pause frame capture is not requested - valid_pfc_frame_test = False - - if (test_traffic_pause): - if valid_pfc_frame_test: - snappi_extra_params.traffic_flow_config.pause_flow_config["flow_dur_sec"] = DATA_FLOW_DURATION_SEC + \ - data_flow_delay_sec + SNAPPI_POLL_DELAY_SEC + PAUSE_FLOW_DUR_BASE_SEC - snappi_extra_params.traffic_flow_config.pause_flow_config["flow_traffic_type"] = \ - traffic_flow_mode.FIXED_DURATION - - # Generate test flow config based on number of ingress ports - # Every ingress port will be used as index. Example - test flow stream 0 - for first ingress. - for m in range(port_map[2]): - generate_sys_test_flows(testbed_config=testbed_config, - test_flow_prio_list=test_prio_list, - prio_dscp_map=prio_dscp_map, - snappi_extra_params=snappi_extra_params, - snap_index=m) - - if (test_def['background_traffic']): - for m in range(port_map[2]): - if snappi_extra_params.gen_background_traffic: - # Generate background flow config - generate_sys_background_flows(testbed_config=testbed_config, - bg_flow_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - snappi_extra_params=snappi_extra_params, - snap_index=m) - - # Generate pause storm config - if (test_traffic_pause): - for m in range(port_map[0]): - generate_pause_flows(testbed_config=testbed_config, - pause_prio_list=pause_prio_list, - global_pause=global_pause, - snappi_extra_params=snappi_extra_params, - snap_index=m) - - flows = testbed_config.flows - - all_flow_names = [flow.name for flow in flows] - data_flow_names = [flow.name for flow in flows if PAUSE_FLOW_NAME not in flow.name] - - # Clear PFC, queue and interface counters before traffic run - for dut in dut_list: - dut.command("pfcstat -c \n") - time.sleep(1) - dut.command("sonic-clear queuecounters \n") - time.sleep(1) - dut.command("sonic-clear counters \n") - time.sleep(1) - - exp_dur_sec = DATA_FLOW_DURATION_SEC + data_flow_delay_sec - - """ Run traffic """ - tgen_flow_stats, switch_flow_stats, test_stats = run_sys_traffic(rx_duthost=rx_dut, - tx_duthost=tx_dut, - api=api, - config=testbed_config, - data_flow_names=data_flow_names, - all_flow_names=all_flow_names, - exp_dur_sec=exp_dur_sec, - port_map=test_def['port_map'], - fname=fname, - stats_interval=test_def['stats_interval'], - imix=test_def['imix'], - snappi_extra_params=snappi_extra_params) - - test_check = test_def['test_check'] - if (not test_check['loss_expected']): - # Check for packet loss on IXIA and DUT. - pytest_assert(test_stats['tgen_loss_pkts'] == 0, 'Loss seen on TGEN') - pytest_assert(test_stats['dut_loss_pkts'] == 0, 'Loss seen on DUT') - - # Check for Tx and Rx packets on IXIA for lossless and lossy streams. - pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['tgen_lossless_tx_pkts'], - 'Losses observed in lossless traffic streams') - pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['tgen_lossy_tx_pkts'], - 'Losses observed in lossy traffic streams') - - # Check for Rx packets between IXIA and DUT for lossy and lossless streams. - pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['dut_lossless_pkts'], - 'Losses observed in lossless traffic streams on DUT Tx and IXIA Rx') - pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['dut_lossy_pkts'], - 'Losses observed in lossy traffic streams on DUT Tx and IXIA Rx') - else: - # Check for lossless and lossy stream percentage drop for a given tolerance limit. - lossless_drop = round((1 - float(test_stats['tgen_lossless_rx_pkts']) / test_stats['tgen_lossless_tx_pkts']), 2) - lossy_drop = round((1 - float(test_stats['tgen_lossy_rx_pkts']) / test_stats['tgen_lossy_tx_pkts']), 2) - logger.info('Lossless Drop %:{}, Lossy Drop %:{}'.format(lossless_drop, lossy_drop)) - pytest_assert((lossless_drop*100) <= test_check['lossless'], 'Lossless packet drop outside tolerance limit') - pytest_assert((lossy_drop*100) <= test_check['lossy'], 'Lossy packet drop outside tolerance limit') - - # Checking if the actual line rate on egress is within tolerable limit of egress line speed. - pytest_assert(((1 - test_stats['tgen_rx_rate'] / float(port_map[0]*port_map[1]))*100) <= test_check['speed_tol'], - 'Egress speed beyond tolerance range') - - # Checking for PFC counts on DUT - if (not test_check['pfc']): - pytest_assert(test_stats['lossless_tx_pfc'] == 0, 'Error:PFC transmitted by DUT for lossless priorities') - pytest_assert(test_stats['lossy_rx_tx_pfc'] == 0, 'Error:PFC transmitted by DUT for lossy priorities') - else: - if (test_stats['lossless_rx_pfc'] != 0): - pytest_assert(test_stats['lossless_tx_pfc'] > 0, 'Error:No Tx PFCs from DUT after receiving PFCs') - pytest_assert(test_stats['lossless_tx_pfc'] > 0, 'Error: PFC not be transmitted from DUT on congestion') - pytest_assert(test_stats['lossy_rx_tx_pfc'] == 0, 'Error:Incorrect Rx/Tx PFCs on DUT for lossy priorities') - - # Reset pfc delay parameter - pfc = testbed_config.layer1[0].flow_control.ieee_802_1qbb - pfc.pfc_delay = 0 - - # Verify PFC pause frames - if (test_traffic_pause): - if valid_pfc_frame_test: - is_valid_pfc_frame = validate_pfc_frame(snappi_extra_params.packet_capture_file + ".pcapng") - pytest_assert(is_valid_pfc_frame, "PFC frames invalid") - return - - # Verify pause flows - if (test_traffic_pause): - verify_pause_flow(flow_metrics=tgen_flow_stats, - pause_flow_name=PAUSE_FLOW_NAME) - - # Check for the flows ONLY if normal packet size (non-imix) is used. - if (test_def['background_traffic'] and test_def['verify_flows'] and not test_def['imix']): - if snappi_extra_params.gen_background_traffic: - # Verify background flows - verify_background_flow(flow_metrics=tgen_flow_stats, - speed_gbps=speed_gbps, - tolerance=TOLERANCE_THRESHOLD, - snappi_extra_params=snappi_extra_params) - - # Verify basic test flows metrics from ixia - if (test_def['verify_flows'] and not test_def['imix']): - verify_basic_test_flow(flow_metrics=tgen_flow_stats, - speed_gbps=speed_gbps, - tolerance=TOLERANCE_THRESHOLD, - test_flow_pause=test_traffic_pause, - snappi_extra_params=snappi_extra_params) - - if (test_traffic_pause and test_def['verify_flows']): - verify_pause_frame_count_dut(rx_dut=rx_dut, - tx_dut=tx_dut, - test_traffic_pause=test_traffic_pause, - global_pause=global_pause, - snappi_extra_params=snappi_extra_params) - - # Verify in flight TX lossless packets do not leave the DUT when traffic is expected - # to be paused, or leave the DUT when the traffic is not expected to be paused - verify_sys_egress_queue_count(duthost=tx_dut, - switch_flow_stats=switch_flow_stats, - test_traffic_pause=test_traffic_pause, - snappi_extra_params=snappi_extra_params) - - if test_traffic_pause: - # Verify zero pause frames are counted when the PFC class enable vector is not set - verify_unset_cev_pause_frame_count(duthost=tx_dut, - snappi_extra_params=snappi_extra_params) - - if test_traffic_pause and not snappi_extra_params.gen_background_traffic: - # Verify TX frame count on the DUT when traffic is expected to be paused - # and only test traffic flows are generated - verify_tx_frame_count_dut(duthost=rx_dut, - snappi_extra_params=snappi_extra_params) - - # Verify TX frame count on the DUT when traffic is expected to be paused - # and only test traffic flows are generated - verify_rx_frame_count_dut(duthost=tx_dut, - snappi_extra_params=snappi_extra_params) diff --git a/tests/snappi_tests/multidut/systest/test_multiflow_pfcwd.py b/tests/snappi_tests/multidut/systest/test_multiflow_pfcwd.py deleted file mode 100644 index 966922d47bd..00000000000 --- a/tests/snappi_tests/multidut/systest/test_multiflow_pfcwd.py +++ /dev/null @@ -1,753 +0,0 @@ -import pytest -from tests.common.helpers.assertions import pytest_require, pytest_assert # noqa: F401 -from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts # noqa: F401 -from tests.common.snappi_tests.snappi_fixtures import snappi_api_serv_ip, snappi_api_serv_port, \ - snappi_api, snappi_dut_base_config, get_tgen_peer_ports, get_multidut_snappi_ports, \ - get_multidut_tgen_peer_port_set, new_get_multidut_tgen_peer_port_set, cleanup_config # noqa: F401 -from tests.common.snappi_tests.qos_fixtures import prio_dscp_map, \ - lossless_prio_list # noqa: F401 -from tests.common.snappi_tests.common_helpers import get_pfcwd_stats -from tests.snappi_tests.variables import config_set, line_card_choice -from files.pfcwd_multidut_helper import run_pfc_test -import logging -from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams -logger = logging.getLogger(__name__) - -pytestmark = [pytest.mark.topology('multidut-tgen')] - - -@pytest.mark.parametrize('linecard_configuration_set', [config_set]) -@pytest.mark.parametrize('line_card_choice', line_card_choice) -def test_pfcwd_drop_90_10(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - lossless_prio_list, # noqa: F811 - line_card_choice, - linecard_configuration_set, - get_multidut_snappi_ports): # noqa: F811 - - """ - Purpose of the test case is to enable PFCWD in drop mode and send 90% lossless traffic and 10% - lossy traffic and check the behavior. DUT is receiving pause storm on the egress port. DUT should - drop the lossless packets without generating any pause towards IXIA transmitter. No loss for lossy traffic. - - Args: - snappi_api (pytest fixture): SNAPPI session - conn_graph_facts (pytest fixture): connection graph - fanout_graph_facts (pytest fixture): fanout graph - duthosts (pytest fixture): list of DUTs - prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). - line_card_choice: Line card choice to be mentioned in the variable.py file - linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) - Returns: - N/A - """ - - test_pkt_size = 1024 - # port_map is defined as port-speed combination. - # first two parameters are count of egress links and its speed. - # last two parameters are count of ingress links and its speed. - if '100Gbps' in line_card_choice: - port_map = [1, 100, 1, 100] - else: - port_map = [1, 400, 1, 400] - - # Percentage drop expected for lossless and lossy traffic. - # speed_tol is speed tolerance between egress link speed and actual speed. - # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 100, 'lossy': 0, 'speed_tol': 91, 'loss_expected': True, 'pfc': True} - - test_def = {} - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 90, - 'BG_FLOW_AGGR_RATE_PERCENT': 10, - 'data_flow_pkt_size': test_pkt_size, - 'DATA_FLOW_DURATION_SEC': 300, - 'data_flow_delay_sec': 1, - 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/One_Ingress_Egress_pfcwd_drop_90_10_dist'+str(port_map[1])+'Gbps', - 'line_card_choice': line_card_choice, - 'port_map': port_map, - 'enable_pfcwd_drop': True, - 'enable_pfcwd_fwd': False, - 'enable_credit_wd': True, - 'stats_interval': 60, - 'background_traffic': True, - 'verify_flows': False, - 'imix': False, - 'test_check': test_check} - - logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) - if line_card_choice not in linecard_configuration_set.keys(): - assert False, "Invalid line_card_choice value passed in parameter" - - if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): - dut_list = [dut for dut in duthosts - if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] - duthost1, duthost2 = dut_list - elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): - dut_list = [dut for dut in duthosts - if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] - duthost1 = duthost2 = dut_list[0] - else: - assert False, "Hostname can't be an empty list" - - snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, - line_card_info=linecard_configuration_set[line_card_choice]) - - if len(snappi_port_list) < 2: - assert False, "Need Minimum of 2 ports for the test" - - snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) - - if len(snappi_ports) < 2: - assert False, "Need Minimum of 2 ports for the test" - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, - snappi_ports, - snappi_api) - - test_prio_list = lossless_prio_list - pause_prio_list = test_prio_list - bg_prio_list = [0, 1, 2] - logger.info("Snappi Ports : {}".format(snappi_ports)) - - logger.info('PFC-WD stats at the start of the test:') - for prio in test_prio_list: - for port in snappi_ports: - if len(dut_list) == 1: - if dut_list[0].hostname == port['peer_device']: - logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. - format(dut_list[0].hostname, port['peer_port'], prio)) - pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) - logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) - else: - for dut in dut_list: - if dut.hostname == port['peer_device']: - logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. - format(dut.hostname, port['peer_port'], prio)) - pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) - logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) - - snappi_extra_params = SnappiSysTestParams() - snappi_extra_params.multi_dut_params.duthost1 = duthost1 - snappi_extra_params.multi_dut_params.duthost2 = duthost2 - snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports - - try: - run_pfc_test(api=snappi_api, - testbed_config=testbed_config, - port_config_list=port_config_list, - conn_data=conn_graph_facts, - fanout_data=fanout_graph_facts, - global_pause=False, - pause_prio_list=pause_prio_list, - test_prio_list=test_prio_list, - bg_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - test_traffic_pause=True, - test_def=test_def, - snappi_extra_params=snappi_extra_params) - - logger.info('PFC-WD stats at the end of the test:') - for prio in test_prio_list: - for port in snappi_ports: - if len(dut_list) == 1: - if dut_list[0].hostname == port['peer_device']: - pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) - logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. - format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) - else: - for dut in dut_list: - if dut.hostname == port['peer_device']: - pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) - logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. - format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) - - finally: - cleanup_config(dut_list, snappi_ports) - - -@pytest.mark.parametrize('linecard_configuration_set', [config_set]) -@pytest.mark.parametrize('line_card_choice', line_card_choice) -def test_pfcwd_frwd_90_10(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - lossless_prio_list, # noqa: F811 - line_card_choice, - linecard_configuration_set, - get_multidut_snappi_ports): # noqa: F811 - - """ - Purpose of the test case is to check behavior of the DUT when PFCWD is enabled in FORWARD mode and egress port - is congested with PAUSE storm. DUT in this mode should forward the lossless packets irrespective of the pause - storm and not send any PAUSE frames towards IXIA transmitter. No effect on lossy traffic. - - Args: - snappi_api (pytest fixture): SNAPPI session - conn_graph_facts (pytest fixture): connection graph - fanout_graph_facts (pytest fixture): fanout graph - duthosts (pytest fixture): list of DUTs - prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). - line_card_choice: Line card choice to be mentioned in the variable.py file - linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) - Returns: - N/A - """ - - test_pkt_size = 1024 - # port_map is defined as port-speed combination. - # first two parameters are count of egress links and its speed. - # last two parameters are count of ingress links and its speed. - if '100Gbps' in line_card_choice: - port_map = [1, 100, 1, 100] - else: - port_map = [1, 400, 1, 400] - - # Percentage drop expected for lossless and lossy traffic. - # speed_tol is speed tolerance between egress link speed and actual speed. - # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': True} - - test_def = {} - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 90, - 'BG_FLOW_AGGR_RATE_PERCENT': 10, - 'data_flow_pkt_size': test_pkt_size, - 'DATA_FLOW_DURATION_SEC': 300, - 'data_flow_delay_sec': 1, - 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/One_Ingress_Egress_pfcwd_frwd_90_10_dist'+str(port_map[1])+'Gbps', - 'line_card_choice': line_card_choice, - 'port_map': port_map, - 'enable_pfcwd_drop': False, - 'enable_pfcwd_fwd': True, - 'enable_credit_wd': True, - 'stats_interval': 60, - 'background_traffic': True, - 'verify_flows': False, - 'imix': False, - 'test_check': test_check} - - logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) - if line_card_choice not in linecard_configuration_set.keys(): - assert False, "Invalid line_card_choice value passed in parameter" - - if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): - dut_list = [dut for dut in duthosts - if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] - duthost1, duthost2 = dut_list - elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): - dut_list = [dut for dut in duthosts - if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] - duthost1 = duthost2 = dut_list[0] - else: - assert False, "Hostname can't be an empty list" - - snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, - line_card_info=linecard_configuration_set[line_card_choice]) - - if len(snappi_port_list) < 2: - assert False, "Need Minimum of 2 ports for the test" - - snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) - - if len(snappi_ports) < 2: - assert False, "Need Minimum of 2 ports for the test" - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, - snappi_ports, - snappi_api) - - test_prio_list = lossless_prio_list - pause_prio_list = test_prio_list - bg_prio_list = [0, 1, 2] - logger.info("Snappi Ports : {}".format(snappi_ports)) - - logger.info('PFC-WD stats at the start of the test:') - for prio in test_prio_list: - for port in snappi_ports: - if len(dut_list) == 1: - if dut_list[0].hostname == port['peer_device']: - logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. - format(dut_list[0].hostname, port['peer_port'], prio)) - pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) - logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) - else: - for dut in dut_list: - if dut.hostname == port['peer_device']: - logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. - format(dut.hostname, port['peer_port'], prio)) - pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) - logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) - - snappi_extra_params = SnappiSysTestParams() - snappi_extra_params.multi_dut_params.duthost1 = duthost1 - snappi_extra_params.multi_dut_params.duthost2 = duthost2 - snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports - - try: - run_pfc_test(api=snappi_api, - testbed_config=testbed_config, - port_config_list=port_config_list, - conn_data=conn_graph_facts, - fanout_data=fanout_graph_facts, - global_pause=False, - pause_prio_list=pause_prio_list, - test_prio_list=test_prio_list, - bg_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - test_traffic_pause=True, - test_def=test_def, - snappi_extra_params=snappi_extra_params) - - logger.info('PFC-WD stats at the end of the test:') - for prio in test_prio_list: - for port in snappi_ports: - if len(dut_list) == 1: - if dut_list[0].hostname == port['peer_device']: - pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) - logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. - format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) - else: - for dut in dut_list: - if dut.hostname == port['peer_device']: - pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) - logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. - format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) - - finally: - cleanup_config(dut_list, snappi_ports) - - -@pytest.mark.parametrize('linecard_configuration_set', [config_set]) -@pytest.mark.parametrize('line_card_choice', line_card_choice) -def test_pfcwd_drop_over_subs_40_09(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - lossless_prio_list, # noqa: F811 - line_card_choice, - linecard_configuration_set, - get_multidut_snappi_ports): # noqa: F811 - - """ - Purpose of the testcase is to check PFCWD behavior in DROP mode with over-subscription. - Each ingress is sending 49% of link capacity traffic and DUT is receiving PAUSE storm on egress link. - DUT should drop lossless packets. No drop for lossy traffic. - - Args: - snappi_api (pytest fixture): SNAPPI session - conn_graph_facts (pytest fixture): connection graph - fanout_graph_facts (pytest fixture): fanout graph - duthosts (pytest fixture): list of DUTs - prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). - line_card_choice: Line card choice to be mentioned in the variable.py file - linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) - Returns: - N/A - - """ - test_pkt_size = 1024 - # port_map is defined as port-speed combination. - # first two parameters are count of egress links and its speed. - # last two parameters are count of ingress links and its speed. - if '100Gbps' in line_card_choice: - port_map = [1, 100, 2, 100] - else: - port_map = [1, 400, 2, 400] - - # Percentage drop expected for lossless and lossy traffic. - # speed_tol is speed tolerance between egress link speed and actual speed. - # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 100, 'lossy': 0, 'speed_tol': 83, 'loss_expected': True, 'pfc': True} - - test_def = {} - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, - 'BG_FLOW_AGGR_RATE_PERCENT': 9, - 'data_flow_pkt_size': test_pkt_size, - 'DATA_FLOW_DURATION_SEC': 300, - 'data_flow_delay_sec': 1, - 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/Two_Ingress_Single_Egress_pfcwd_drop_40_9_dist'+str(port_map[1])+'Gbps', - 'line_card_choice': line_card_choice, - 'port_map': port_map, - 'enable_pfcwd_drop': True, - 'enable_pfcwd_fwd': False, - 'enable_credit_wd': True, - 'stats_interval': 60, - 'background_traffic': True, - 'verify_flows': False, - 'imix': False, - 'test_check': test_check} - - logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) - if line_card_choice not in linecard_configuration_set.keys(): - assert False, "Invalid line_card_choice value passed in parameter" - - if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): - dut_list = [dut for dut in duthosts - if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] - duthost1, duthost2 = dut_list - elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): - dut_list = [dut for dut in duthosts - if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] - duthost1 = duthost2 = dut_list[0] - else: - assert False, "Hostname can't be an empty list" - - snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, - line_card_info=linecard_configuration_set[line_card_choice]) - - if len(snappi_port_list) < 3: - assert False, "Need Minimum of 3 ports for the test" - - snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) - - if len(snappi_ports) < 3: - assert False, "Need Minimum of 3 ports for the test" - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, - snappi_ports, - snappi_api) - - test_prio_list = lossless_prio_list - pause_prio_list = test_prio_list - bg_prio_list = [0, 1, 2] - logger.info("Snappi Ports : {}".format(snappi_ports)) - - logger.info('PFC-WD stats at the start of the test:') - for prio in test_prio_list: - for port in snappi_ports: - if len(dut_list) == 1: - if dut_list[0].hostname == port['peer_device']: - logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. - format(dut_list[0].hostname, port['peer_port'], prio)) - pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) - logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) - else: - for dut in dut_list: - if dut.hostname == port['peer_device']: - logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. - format(dut.hostname, port['peer_port'], prio)) - pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) - logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) - - snappi_extra_params = SnappiSysTestParams() - snappi_extra_params.multi_dut_params.duthost1 = duthost1 - snappi_extra_params.multi_dut_params.duthost2 = duthost2 - snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports - - try: - run_pfc_test(api=snappi_api, - testbed_config=testbed_config, - port_config_list=port_config_list, - conn_data=conn_graph_facts, - fanout_data=fanout_graph_facts, - global_pause=False, - pause_prio_list=pause_prio_list, - test_prio_list=test_prio_list, - bg_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - test_traffic_pause=True, - test_def=test_def, - snappi_extra_params=snappi_extra_params) - - logger.info('PFC-WD stats at the end of the test:') - for prio in test_prio_list: - for port in snappi_ports: - if len(dut_list) == 1: - if dut_list[0].hostname == port['peer_device']: - pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) - logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. - format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) - else: - for dut in dut_list: - if dut.hostname == port['peer_device']: - pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) - logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. - format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) - finally: - cleanup_config(dut_list, snappi_ports) - - -@pytest.mark.parametrize('linecard_configuration_set', [config_set]) -@pytest.mark.parametrize('line_card_choice', line_card_choice) -def test_pfcwd_frwd_over_subs_40_09(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - lossless_prio_list, # noqa: F811 - line_card_choice, - linecard_configuration_set, - get_multidut_snappi_ports): # noqa: F811 - - """ - Purpose of testcase is to test behavior of DUT in PFCWD-FORWARD mode in oversubscription mode. - Each ingress is sending 49% of link capacity traffic and DUT is receiving PAUSE storm on egress link. - DUT should forward for both lossy and lossless traffic without generating PAUSE frames towards IXIA - transmitter. - - Args: - snappi_api (pytest fixture): SNAPPI session - conn_graph_facts (pytest fixture): connection graph - fanout_graph_facts (pytest fixture): fanout graph - duthosts (pytest fixture): list of DUTs - prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). - line_card_choice: Line card choice to be mentioned in the variable.py file - linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) - Returns: - N/A - """ - - test_pkt_size = 1024 - # port_map is defined as port-speed combination. - # first two parameters are count of egress links and its speed. - # last two parameters are count of ingress links and its speed. - if '100Gbps' in line_card_choice: - port_map = [1, 100, 2, 100] - else: - port_map = [1, 400, 2, 400] - - # Percentage drop expected for lossless and lossy traffic. - # speed_tol is speed tolerance between egress link speed and actual speed. - # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': True} - - test_def = {} - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, - 'BG_FLOW_AGGR_RATE_PERCENT': 9, - 'data_flow_pkt_size': test_pkt_size, - 'DATA_FLOW_DURATION_SEC': 300, - 'data_flow_delay_sec': 1, - 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/Two_Ingress_Single_Egress_pfcwd_frwd_40_9_dist'+str(port_map[1])+'Gbps', - 'line_card_choice': line_card_choice, - 'port_map': port_map, - 'enable_pfcwd_drop': False, - 'enable_pfcwd_fwd': True, - 'enable_credit_wd': True, - 'stats_interval': 60, - 'background_traffic': True, - 'verify_flows': False, - 'imix': False, - 'test_check': test_check} - - logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) - if line_card_choice not in linecard_configuration_set.keys(): - assert False, "Invalid line_card_choice value passed in parameter" - - if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): - dut_list = [dut for dut in duthosts - if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] - duthost1, duthost2 = dut_list - elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): - dut_list = [dut for dut in duthosts - if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] - duthost1 = duthost2 = dut_list[0] - else: - assert False, "Hostname can't be an empty list" - - snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, - line_card_info=linecard_configuration_set[line_card_choice]) - - if len(snappi_port_list) < 3: - assert False, "Need Minimum of 3 ports for the test" - - snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) - - if len(snappi_ports) < 3: - assert False, "Need Minimum of 3 ports for the test" - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, - snappi_ports, - snappi_api) - - test_prio_list = lossless_prio_list - pause_prio_list = test_prio_list - bg_prio_list = [0, 1, 2] - logger.info("Snappi Ports : {}".format(snappi_ports)) - - logger.info('PFC-WD stats at the start of the test:') - for prio in test_prio_list: - for port in snappi_ports: - if len(dut_list) == 1: - if dut_list[0].hostname == port['peer_device']: - logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. - format(dut_list[0].hostname, port['peer_port'], prio)) - pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) - logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) - else: - for dut in dut_list: - if dut.hostname == port['peer_device']: - logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. - format(dut.hostname, port['peer_port'], prio)) - pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) - logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) - - snappi_extra_params = SnappiSysTestParams() - snappi_extra_params.multi_dut_params.duthost1 = duthost1 - snappi_extra_params.multi_dut_params.duthost2 = duthost2 - snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports - - try: - run_pfc_test(api=snappi_api, - testbed_config=testbed_config, - port_config_list=port_config_list, - conn_data=conn_graph_facts, - fanout_data=fanout_graph_facts, - global_pause=False, - pause_prio_list=pause_prio_list, - test_prio_list=test_prio_list, - bg_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - test_traffic_pause=True, - test_def=test_def, - snappi_extra_params=snappi_extra_params) - - logger.info('PFC-WD stats at the end of the test:') - for prio in test_prio_list: - for port in snappi_ports: - if len(dut_list) == 1: - if dut_list[0].hostname == port['peer_device']: - pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) - logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. - format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) - else: - for dut in dut_list: - if dut.hostname == port['peer_device']: - pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) - logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. - format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) - finally: - cleanup_config(dut_list, snappi_ports) - - -@pytest.mark.parametrize('linecard_configuration_set', [config_set]) -@pytest.mark.parametrize('line_card_choice', line_card_choice) -def test_pfcwd_disable_pause_cngtn(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - line_card_choice, - linecard_configuration_set, - get_multidut_snappi_ports): # noqa: F811 - - """ - Purpose of the test case is to test oversubscription with two ingresses and single ingress. - Traffic pattern has 18% lossless priority and 27% lossy priority traffic. - Total ingress link is sending only 45% link capacity and hence egress will not be congested. - No losses for both lossless and lossy priority traffic. - - Args: - snappi_api (pytest fixture): SNAPPI session - conn_graph_facts (pytest fixture): connection graph - fanout_graph_facts (pytest fixture): fanout graph - duthosts (pytest fixture): list of DUTs - prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). - line_card_choice: Line card choice to be mentioned in the variable.py file - linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) - Returns: - N/A - """ - - # port_map is defined as port-speed combination. - # first two parameters are count of egress links and its speed. - # last two parameters are count of ingress links and its speed. - if '100Gbps' in line_card_choice: - port_map = [1, 100, 1, 100] - else: - port_map = [1, 400, 1, 400] - - # pkt_size of 1024B will be used unless imix flag is set. - # With imix flag set, the traffic_generation.py uses IMIX profile. - pkt_size = 1024 - - # Percentage drop expected for lossless and lossy traffic. - # speed_tol is speed tolerance between egress link speed and actual speed. - # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 41, 'loss_expected': False, 'pfc': True} - - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, - 'BG_FLOW_AGGR_RATE_PERCENT': 60, - 'data_flow_pkt_size': pkt_size, - 'DATA_FLOW_DURATION_SEC': 300, - 'data_flow_delay_sec': 1, - 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/Single_Ingress_Single_Egress_pause_cngstn_'+str(port_map[1])+'Gbps', - 'line_card_choice': line_card_choice, - 'port_map': port_map, - 'enable_pfcwd_drop': False, - 'enable_pfcwd_fwd': False, - 'enable_credit_wd': False, - 'stats_interval': 60, - 'background_traffic': True, - 'verify_flows': False, - 'imix': False, - 'test_check': test_check} - - logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) - if line_card_choice not in linecard_configuration_set.keys(): - assert False, "Invalid line_card_choice value passed in parameter" - - if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): - dut_list = [dut for dut in duthosts - if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] - duthost1, duthost2 = dut_list - elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): - dut_list = [dut for dut in duthosts - if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] - duthost1 = duthost2 = dut_list[0] - else: - assert False, "Hostname can't be an empty list" - - snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, - line_card_info=linecard_configuration_set[line_card_choice]) - - if len(snappi_port_list) < 2: - assert False, "snappi_port_list: Need Minimum of 2 ports for the test" - - # port_map is read as egress port_map[0] links of port_map[1] speed - # and ingress port_map[2] links of port_map[3] speed - port_map = test_def['port_map'] - - snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) - - if len(snappi_ports) < 2: - assert False, "snappi_ports: Need Minimum of 2 ports for the test" - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, - snappi_ports, - snappi_api) - - test_prio_list = [3, 4] - pause_prio_list = test_prio_list - bg_prio_list = [0, 1, 2] - logger.info("Snappi Ports : {}".format(snappi_ports)) - - snappi_extra_params = SnappiSysTestParams() - snappi_extra_params.multi_dut_params.duthost1 = duthost1 - snappi_extra_params.multi_dut_params.duthost2 = duthost2 - snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports - - try: - run_pfc_test(api=snappi_api, - testbed_config=testbed_config, - port_config_list=port_config_list, - conn_data=conn_graph_facts, - fanout_data=fanout_graph_facts, - global_pause=False, - pause_prio_list=pause_prio_list, - test_prio_list=test_prio_list, - bg_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - test_traffic_pause=True, - test_def=test_def, - snappi_extra_params=snappi_extra_params) - finally: - cleanup_config(dut_list, snappi_ports) diff --git a/tests/snappi_tests/multidut/systest/test_non_congestion_imix.py b/tests/snappi_tests/multidut/systest/test_non_congestion_imix.py deleted file mode 100644 index f048034ab87..00000000000 --- a/tests/snappi_tests/multidut/systest/test_non_congestion_imix.py +++ /dev/null @@ -1,395 +0,0 @@ -import pytest -from tests.common.helpers.assertions import pytest_require, pytest_assert # noqa: F401 -from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts # noqa: F401 -from tests.common.snappi_tests.snappi_fixtures import snappi_api_serv_ip, snappi_api_serv_port, \ - snappi_api, snappi_dut_base_config, get_multidut_snappi_ports, \ - new_get_multidut_tgen_peer_port_set, cleanup_config # noqa: F401 -from tests.common.snappi_tests.qos_fixtures import prio_dscp_map # noqa: F401 -from tests.snappi_tests.variables import config_set, line_card_choice -from tests.snappi_tests.multidut.systest.files.sys_multidut_helper import run_pfc_test -from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams - -import logging -logger = logging.getLogger(__name__) - -pytestmark = [pytest.mark.topology('multidut-tgen')] - - -@pytest.mark.parametrize('linecard_configuration_set', [config_set]) -@pytest.mark.parametrize('line_card_choice', line_card_choice) -def test_multiple_prio_diff_dist(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - line_card_choice, - linecard_configuration_set, - get_multidut_snappi_ports): # noqa: F811 - - """ - Purpose of the test is to check if line-rate can be achieved. - Traffic distribution is 88% lossless priority 3 and 4 traffic. - There is additional 12% of lossy priority 0, 1 and 2 traffic. - PFCWD and Credit-watchdog is enabled. - Packet-size is 1024. IMIX can be enabled by setting imix to True. - No losses should be seen for both lossy and lossless traffic. - No PFCs should be generated during the test. - - Args: - snappi_api (pytest fixture): SNAPPI session - conn_graph_facts (pytest fixture): connection graph - fanout_graph_facts (pytest fixture): fanout graph - duthosts (pytest fixture): list of DUTs - prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). - line_card_choice: Line card choice to be mentioned in the variable.py file - linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) - Returns: - N/A - - """ - - # port_map is defined as port-speed combination. - # first two parameters are count of egress links and its speed. - # last two parameters are count of ingress links and its speed. - if '100Gbps' in line_card_choice: - port_map = [1, 100, 1, 100] - else: - port_map = [1, 400, 1, 400] - - # pkt_size of 1024B will be used unless imix flag is set. - # With imix flag set, the traffic_generation.py uses IMIX profile. - pkt_size = 1024 - - # Percentage drop expected for lossless and lossy traffic. - # speed_tol is speed tolerance between egress link speed and actual speed. - # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': False} - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 88, - 'BG_FLOW_AGGR_RATE_PERCENT': 12, - 'data_flow_pkt_size': pkt_size, - 'DATA_FLOW_DURATION_SEC': 300, - 'data_flow_delay_sec': 0, - 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/Single_Ingress_Egress_diff_dist_'+str(port_map[1])+'Gbps', - 'line_card_choice': line_card_choice, - 'port_map': port_map, - 'enable_pfcwd': True, - 'enable_credit_wd': True, - 'stats_interval': 60, - 'background_traffic': True, - 'imix': False, - 'test_check': test_check, - 'verify_flows': True} - - logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) - if line_card_choice not in linecard_configuration_set.keys(): - assert False, "Invalid line_card_choice value passed in parameter" - - if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): - dut_list = [dut for dut in duthosts - if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] - duthost1, duthost2 = dut_list - elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): - dut_list = [dut for dut in duthosts - if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] - duthost1 = duthost2 = dut_list[0] - else: - assert False, "Hostname can't be an empty list" - - snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, - line_card_info=linecard_configuration_set[line_card_choice]) - - if len(snappi_port_list) < 2: - assert False, "Need Minimum of 2 ports for the test" - - snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) - - if len(snappi_ports) < 2: - assert False, "Need Minimum of 2 ports for the test" - - logger.info("Snappi Ports : {}".format(snappi_ports)) - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, - snappi_ports, - snappi_api) - - test_prio_list = [3, 4] - pause_prio_list = test_prio_list - bg_prio_list = [0, 1, 2] - - snappi_extra_params = SnappiSysTestParams() - snappi_extra_params.multi_dut_params.duthost1 = duthost1 - snappi_extra_params.multi_dut_params.duthost2 = duthost2 - snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports - - try: - run_pfc_test(api=snappi_api, - testbed_config=testbed_config, - port_config_list=port_config_list, - conn_data=conn_graph_facts, - fanout_data=fanout_graph_facts, - global_pause=False, - pause_prio_list=pause_prio_list, - test_prio_list=test_prio_list, - bg_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - test_traffic_pause=False, - test_def=test_def, - snappi_extra_params=snappi_extra_params) - finally: - cleanup_config(dut_list, snappi_ports) - - -@pytest.mark.parametrize('linecard_configuration_set', [config_set]) -@pytest.mark.parametrize('line_card_choice', line_card_choice) -def test_multiple_prio_uni_dist(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - line_card_choice, - linecard_configuration_set, - get_multidut_snappi_ports): # noqa: F811 - - """ - Purpose of the test is to check if line-rate can be achieved. - Traffic distribution is 40% lossless priority 3 and 4 traffic. - There is additional 60% of lossy priority 0, 1 and 2 traffic. - PFCWD and Credit-watchdog is enabled. - Packet-size is 1024. IMIX can be enabled by setting imix to True. - No losses should be seen for both lossy and lossless traffic. - No PFCs should be generated during the test. - - Args: - snappi_api (pytest fixture): SNAPPI session - conn_graph_facts (pytest fixture): connection graph - fanout_graph_facts (pytest fixture): fanout graph - duthosts (pytest fixture): list of DUTs - prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). - line_card_choice: Line card choice to be mentioned in the variable.py file - linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) - Returns: - N/A - """ - - # port_map is defined as port-speed combination. - # first two parameters are count of egress links and its speed. - # last two parameters are count of ingress links and its speed. - if '100Gbps' in line_card_choice: - port_map = [1, 100, 1, 100] - else: - port_map = [1, 400, 1, 400] - - # pkt_size of 1024B will be used unless imix flag is set. - # With imix flag set, the traffic_generation.py uses IMIX profile. - pkt_size = 1024 - - # Percentage drop expected for lossless and lossy traffic. - # speed_tol is speed tolerance between egress link speed and actual speed. - # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': False} - - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, - 'BG_FLOW_AGGR_RATE_PERCENT': 60, - 'data_flow_pkt_size': pkt_size, - 'DATA_FLOW_DURATION_SEC': 300, - 'data_flow_delay_sec': 0, - 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/Single_Ingress_Egress_uni_dist_'+str(port_map[1])+'Gbps', - 'line_card_choice': line_card_choice, - 'port_map': port_map, - 'enable_pfcwd': True, - 'enable_credit_wd': True, - 'stats_interval': 60, - 'background_traffic': True, - 'imix': False, - 'test_check': test_check, - 'verify_flows': True} - - logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) - if line_card_choice not in linecard_configuration_set.keys(): - assert False, "Invalid line_card_choice value passed in parameter" - - if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): - dut_list = [dut for dut in duthosts - if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] - duthost1, duthost2 = dut_list - elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): - dut_list = [dut for dut in duthosts - if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] - duthost1 = duthost2 = dut_list[0] - else: - assert False, "Hostname can't be an empty list" - - snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, - line_card_info=linecard_configuration_set[line_card_choice]) - - if len(snappi_port_list) < 2: - assert False, "Need Minimum of 2 ports for the test" - - # port_map is read as egress port_map[0] links of port_map[1] speed - # and ingress port_map[2] links of port_map[3] speed - port_map = test_def['port_map'] - - snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) - - if len(snappi_ports) < 2: - assert False, "Need Minimum of 2 ports for the test" - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, - snappi_ports, - snappi_api) - - test_prio_list = [3, 4] - pause_prio_list = test_prio_list - bg_prio_list = [0, 1, 2] - logger.info("Snappi Ports : {}".format(snappi_ports)) - - snappi_extra_params = SnappiSysTestParams() - snappi_extra_params.multi_dut_params.duthost1 = duthost1 - snappi_extra_params.multi_dut_params.duthost2 = duthost2 - snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports - - try: - run_pfc_test(api=snappi_api, - testbed_config=testbed_config, - port_config_list=port_config_list, - conn_data=conn_graph_facts, - fanout_data=fanout_graph_facts, - global_pause=False, - pause_prio_list=pause_prio_list, - test_prio_list=test_prio_list, - bg_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - test_traffic_pause=False, - test_def=test_def, - snappi_extra_params=snappi_extra_params) - finally: - cleanup_config(dut_list, snappi_ports) - - -@pytest.mark.parametrize('linecard_configuration_set', [config_set]) -@pytest.mark.parametrize('line_card_choice', line_card_choice) -def test_single_lossless_prio(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - line_card_choice, - linecard_configuration_set, - get_multidut_snappi_ports): # noqa: F811 - - """ - Purpose of the test is to check if line-rate can be achieved with single priority traffic. - Traffic distribution is 100% lossless priority 3 traffic. - PFCWD and Credit-watchdog is enabled. - Packet-size is 1024. IMIX can be enabled by setting imix to True. - No losses should be seen for both lossy and lossless traffic. - No PFCs should be generated during the test. - - Args: - snappi_api (pytest fixture): SNAPPI session - conn_graph_facts (pytest fixture): connection graph - fanout_graph_facts (pytest fixture): fanout graph - duthosts (pytest fixture): list of DUTs - prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). - line_card_choice: Line card choice to be mentioned in the variable.py file - linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) - Returns: - N/A - """ - - # port_map is defined as port-speed combination. - # first two parameters are count of egress links and its speed. - # last two parameters are count of ingress links and its speed. - if '100Gbps' in line_card_choice: - port_map = [1, 100, 1, 100] - else: - port_map = [1, 400, 1, 400] - - # pkt_size of 1024B will be used unless imix flag is set. - # With imix flag set, the traffic_generation.py uses IMIX profile. - pkt_size = 1024 - - # Percentage drop expected for lossless and lossy traffic. - # speed_tol is speed tolerance between egress link speed and actual speed. - # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': False} - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 100, - 'BG_FLOW_AGGR_RATE_PERCENT': 50, - 'data_flow_pkt_size': pkt_size, - 'DATA_FLOW_DURATION_SEC': 300, - 'data_flow_delay_sec': 0, - 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/Single_Ingress_Egress_1Prio_linerate_'+str(port_map[1])+'Gbps', - 'line_card_choice': line_card_choice, - 'port_map': port_map, - 'enable_pfcwd': True, - 'enable_credit_wd': True, - 'stats_interval': 60, - 'background_traffic': False, - 'imix': False, - 'test_check': test_check, - 'verify_flows': True} - - logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) - - if line_card_choice not in linecard_configuration_set.keys(): - assert False, "Invalid line_card_choice value passed in parameter" - if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): - dut_list = [dut for dut in duthosts - if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] - duthost1, duthost2 = dut_list - elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): - dut_list = [dut for dut in duthosts - if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] - duthost1 = duthost2 = dut_list[0] - else: - assert False, "Hostname can't be an empty list" - - snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, - line_card_info=linecard_configuration_set[line_card_choice]) - - if len(snappi_port_list) < 2: - assert False, "Need Minimum of 2 ports for the test" - - # port_map is read as egress port_map[0] links of port_map[1] speed - # and ingress port_map[2] links of port_map[3] speed - port_map = test_def['port_map'] - - snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) - - if len(snappi_ports) < 2: - assert False, "Need Minimum of 2 ports for the test" - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, - snappi_ports, - snappi_api) - - test_prio_list = [3] - logger.info('Selected Test Prio:{}'.format(test_prio_list)) - pause_prio_list = test_prio_list - bg_prio_list = [0, 1, 2] - logger.info("Pkt Size:{}, Current port_map:{} and Snappi Ports : {}".format(pkt_size, port_map, snappi_ports)) - - snappi_extra_params = SnappiSysTestParams() - snappi_extra_params.multi_dut_params.duthost1 = duthost1 - snappi_extra_params.multi_dut_params.duthost2 = duthost2 - snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports - - try: - run_pfc_test(api=snappi_api, - testbed_config=testbed_config, - port_config_list=port_config_list, - conn_data=conn_graph_facts, - fanout_data=fanout_graph_facts, - global_pause=False, - pause_prio_list=pause_prio_list, - test_prio_list=test_prio_list, - bg_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - test_traffic_pause=False, - test_def=test_def, - snappi_extra_params=snappi_extra_params) - finally: - cleanup_config(dut_list, snappi_ports) diff --git a/tests/snappi_tests/multidut/systest/test_over_subscription_imix.py b/tests/snappi_tests/multidut/systest/test_over_subscription_imix.py deleted file mode 100644 index 4853be9c03e..00000000000 --- a/tests/snappi_tests/multidut/systest/test_over_subscription_imix.py +++ /dev/null @@ -1,515 +0,0 @@ -import pytest -from tests.common.helpers.assertions import pytest_require, pytest_assert # noqa: F401 -from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts # noqa: F401 -from tests.common.snappi_tests.snappi_fixtures import snappi_api_serv_ip, snappi_api_serv_port, \ - snappi_api, snappi_dut_base_config, get_multidut_snappi_ports, \ - new_get_multidut_tgen_peer_port_set, cleanup_config # noqa: F401 -from tests.common.snappi_tests.qos_fixtures import prio_dscp_map # noqa: F401 -from tests.snappi_tests.variables import config_set, line_card_choice -from tests.snappi_tests.multidut.systest.files.sys_multidut_helper import run_pfc_test -from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams - -import logging -logger = logging.getLogger(__name__) - -pytestmark = [pytest.mark.topology('multidut-tgen')] - - -@pytest.mark.parametrize('linecard_configuration_set', [config_set]) -@pytest.mark.parametrize('line_card_choice', line_card_choice) -def test_multiple_prio_diff_dist(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - line_card_choice, - linecard_configuration_set, - get_multidut_snappi_ports): # noqa: F811 - - """ - Purpose of the test case is to test oversubscription with two ingresses and single ingress. - Traffic pattern has 90% lossless priority and 10% lossy priority traffic. - No losses for both lossless and lossy priority traffic. - - Args: - snappi_api (pytest fixture): SNAPPI session - conn_graph_facts (pytest fixture): connection graph - fanout_graph_facts (pytest fixture): fanout graph - duthosts (pytest fixture): list of DUTs - prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). - line_card_choice: Line card choice to be mentioned in the variable.py file - linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) - Returns: - N/A - - """ - - # port_map is defined as port-speed combination. - # first two parameters are count of egress links and its speed. - # last two parameters are count of ingress links and its speed. - if '100Gbps' in line_card_choice: - port_map = [1, 100, 2, 100] - else: - port_map = [1, 400, 2, 400] - - # pkt_size of 1024B will be used unless imix flag is set. - # With imix flag set, the traffic_generation.py uses IMIX profile. - pkt_size = 1024 - - # Percentage drop expected for lossless and lossy traffic. - # speed_tol is speed tolerance between egress link speed and actual speed. - # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': True} - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 88, - 'BG_FLOW_AGGR_RATE_PERCENT': 12, - 'data_flow_pkt_size': pkt_size, - 'DATA_FLOW_DURATION_SEC': 300, - 'data_flow_delay_sec': 0, - 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/Two_Ingress_Single_Egress_diff_dist_'+str(port_map[1])+'Gbps', - 'line_card_choice': line_card_choice, - 'port_map': port_map, - 'enable_pfcwd': True, - 'enable_credit_wd': True, - 'stats_interval': 60, - 'background_traffic': True, - 'imix': False, - 'test_check': test_check, - 'verify_flows': False} - - logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) - if line_card_choice not in linecard_configuration_set.keys(): - assert False, "Invalid line_card_choice value passed in parameter" - - if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): - dut_list = [dut for dut in duthosts - if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] - duthost1, duthost2 = dut_list - elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): - dut_list = [dut for dut in duthosts - if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] - duthost1 = duthost2 = dut_list[0] - else: - assert False, "Hostname can't be an empty list" - - snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, - line_card_info=linecard_configuration_set[line_card_choice]) - - if len(snappi_port_list) < 3: - assert False, "snappi_port_list: Need Minimum of 3 ports for the test" - - snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) - - if len(snappi_ports) < 3: - assert False, "snappi_port: Need Minimum of 3 ports for the test" - - logger.info("Snappi Ports : {}".format(snappi_ports)) - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, - snappi_ports, - snappi_api) - - test_prio_list = [3, 4] - pause_prio_list = test_prio_list - bg_prio_list = [0, 1, 2] - - snappi_extra_params = SnappiSysTestParams() - snappi_extra_params.multi_dut_params.duthost1 = duthost1 - snappi_extra_params.multi_dut_params.duthost2 = duthost2 - snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports - - try: - run_pfc_test(api=snappi_api, - testbed_config=testbed_config, - port_config_list=port_config_list, - conn_data=conn_graph_facts, - fanout_data=fanout_graph_facts, - global_pause=False, - pause_prio_list=pause_prio_list, - test_prio_list=test_prio_list, - bg_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - test_traffic_pause=False, - test_def=test_def, - snappi_extra_params=snappi_extra_params) - finally: - cleanup_config(dut_list, snappi_ports) - - -@pytest.mark.parametrize('linecard_configuration_set', [config_set]) -@pytest.mark.parametrize('line_card_choice', line_card_choice) -def test_multiple_prio_uni_dist_full(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - line_card_choice, - linecard_configuration_set, - get_multidut_snappi_ports): # noqa: F811 - - """ - Purpose of the test case is to test oversubscription with two ingresses and single ingress. - Traffic pattern has 24% lossless priority and 36% lossy priority traffic. - Each priority carries equal 12% of traffic. - No losses for lossless priority traffic. Some loss expected for lossy priority traffic. - - Args: - snappi_api (pytest fixture): SNAPPI session - conn_graph_facts (pytest fixture): connection graph - fanout_graph_facts (pytest fixture): fanout graph - duthosts (pytest fixture): list of DUTs - prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). - line_card_choice: Line card choice to be mentioned in the variable.py file - linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) - Returns: - N/A - """ - - # port_map is defined as port-speed combination. - # first two parameters are count of egress links and its speed. - # last two parameters are count of ingress links and its speed. - if '100Gbps' in line_card_choice: - port_map = [1, 100, 2, 100] - else: - port_map = [1, 400, 2, 400] - - # pkt_size of 1024B will be used unless imix flag is set. - # With imix flag set, the traffic_generation.py uses IMIX profile. - pkt_size = 1024 - - # Percentage drop expected for lossless and lossy traffic. - # speed_tol is speed tolerance between egress link speed and actual speed. - # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 0, 'lossy': 51, 'speed_tol': 51, 'loss_expected': True, 'pfc': True} - - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, - 'BG_FLOW_AGGR_RATE_PERCENT': 60, - 'data_flow_pkt_size': pkt_size, - 'DATA_FLOW_DURATION_SEC': 300, - 'data_flow_delay_sec': 0, - 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/Two_Ingress_Single_Egress_uni_dist_full'+str(port_map[1])+'Gbps', - 'line_card_choice': line_card_choice, - 'port_map': port_map, - 'enable_pfcwd': True, - 'enable_credit_wd': True, - 'stats_interval': 60, - 'background_traffic': True, - 'imix': False, - 'test_check': test_check, - 'verify_flows': False} - - logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) - if line_card_choice not in linecard_configuration_set.keys(): - assert False, "Invalid line_card_choice value passed in parameter" - - if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): - dut_list = [dut for dut in duthosts - if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] - duthost1, duthost2 = dut_list - elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): - dut_list = [dut for dut in duthosts - if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] - duthost1 = duthost2 = dut_list[0] - else: - assert False, "Hostname can't be an empty list" - - snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, - line_card_info=linecard_configuration_set[line_card_choice]) - - if len(snappi_port_list) < 3: - assert False, "snappi_port_list: Need Minimum of 3 ports for the test" - - # port_map is read as egress port_map[0] links of port_map[1] speed - # and ingress port_map[2] links of port_map[3] speed - port_map = test_def['port_map'] - - snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) - - if len(snappi_ports) < 3: - assert False, "snappi_ports: Need Minimum of 3 ports for the test" - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, - snappi_ports, - snappi_api) - - test_prio_list = [3, 4] - pause_prio_list = test_prio_list - bg_prio_list = [0, 1, 2] - logger.info("Snappi Ports : {}".format(snappi_ports)) - - snappi_extra_params = SnappiSysTestParams() - snappi_extra_params.multi_dut_params.duthost1 = duthost1 - snappi_extra_params.multi_dut_params.duthost2 = duthost2 - snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports - - try: - run_pfc_test(api=snappi_api, - testbed_config=testbed_config, - port_config_list=port_config_list, - conn_data=conn_graph_facts, - fanout_data=fanout_graph_facts, - global_pause=False, - pause_prio_list=pause_prio_list, - test_prio_list=test_prio_list, - bg_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - test_traffic_pause=False, - test_def=test_def, - snappi_extra_params=snappi_extra_params) - finally: - cleanup_config(dut_list, snappi_ports) - - -@pytest.mark.parametrize('linecard_configuration_set', [config_set]) -@pytest.mark.parametrize('line_card_choice', line_card_choice) -def test_multiple_prio_uni_dist(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - line_card_choice, - linecard_configuration_set, - get_multidut_snappi_ports): # noqa: F811 - - """ - Purpose of the test case is to test oversubscription with two ingresses and single ingress. - Traffic pattern for each priority is same 12%. - Traffic pattern has 24% lossless priority and 36% lossy priority traffic. - Each priority carries equal 12% of traffic. - No losses for lossless priority traffic. Some loss expected for lossy priority traffic. - - Args: - snappi_api (pytest fixture): SNAPPI session - conn_graph_facts (pytest fixture): connection graph - fanout_graph_facts (pytest fixture): fanout graph - duthosts (pytest fixture): list of DUTs - prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). - line_card_choice: Line card choice to be mentioned in the variable.py file - linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) - Returns: - N/A - - """ - - # port_map is defined as port-speed combination. - # first two parameters are count of egress links and its speed. - # last two parameters are count of ingress links and its speed. - if '100Gbps' in line_card_choice: - port_map = [1, 100, 2, 100] - else: - port_map = [1, 400, 2, 400] - - # pkt_size of 1024B will be used unless imix flag is set. - # With imix flag set, the traffic_generation.py uses IMIX profile. - pkt_size = 1024 - - # Percentage drop expected for lossless and lossy traffic. - # speed_tol is speed tolerance between egress link speed and actual speed. - # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 0, 'lossy': 15, 'speed_tol': 3, 'loss_expected': True, 'pfc': True} - - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 24, - 'BG_FLOW_AGGR_RATE_PERCENT': 36, - 'data_flow_pkt_size': pkt_size, - 'DATA_FLOW_DURATION_SEC': 300, - 'data_flow_delay_sec': 0, - 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/Two_Ingress_Single_Egress_uni_dist_'+str(port_map[1])+'Gbps', - 'line_card_choice': line_card_choice, - 'port_map': port_map, - 'enable_pfcwd': True, - 'enable_credit_wd': True, - 'stats_interval': 60, - 'background_traffic': True, - 'imix': False, - 'test_check': test_check, - 'verify_flows': False} - - logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) - if line_card_choice not in linecard_configuration_set.keys(): - assert False, "Invalid line_card_choice value passed in parameter" - - if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): - dut_list = [dut for dut in duthosts - if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] - duthost1, duthost2 = dut_list - elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): - dut_list = [dut for dut in duthosts - if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] - duthost1 = duthost2 = dut_list[0] - else: - assert False, "Hostname can't be an empty list" - - snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, - line_card_info=linecard_configuration_set[line_card_choice]) - - if len(snappi_port_list) < 3: - assert False, "snappi_port_list: Need Minimum of 3 ports for the test" - - # port_map is read as egress port_map[0] links of port_map[1] speed - # and ingress port_map[2] links of port_map[3] speed - port_map = test_def['port_map'] - - snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) - - if len(snappi_ports) < 3: - assert False, "snappi_ports: Need Minimum of 3 ports for the test" - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, - snappi_ports, - snappi_api) - - test_prio_list = [3, 4] - pause_prio_list = test_prio_list - bg_prio_list = [0, 1, 2] - logger.info("Snappi Ports : {}".format(snappi_ports)) - - snappi_extra_params = SnappiSysTestParams() - snappi_extra_params.multi_dut_params.duthost1 = duthost1 - snappi_extra_params.multi_dut_params.duthost2 = duthost2 - snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports - - try: - run_pfc_test(api=snappi_api, - testbed_config=testbed_config, - port_config_list=port_config_list, - conn_data=conn_graph_facts, - fanout_data=fanout_graph_facts, - global_pause=False, - pause_prio_list=pause_prio_list, - test_prio_list=test_prio_list, - bg_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - test_traffic_pause=False, - test_def=test_def, - snappi_extra_params=snappi_extra_params) - finally: - cleanup_config(dut_list, snappi_ports) - - -@pytest.mark.parametrize('linecard_configuration_set', [config_set]) -@pytest.mark.parametrize('line_card_choice', line_card_choice) -def test_multiple_prio_non_cngtn(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - line_card_choice, - linecard_configuration_set, - get_multidut_snappi_ports): # noqa: F811 - - """ - Purpose of the test case is to test oversubscription with two ingresses and single ingress. - Traffic pattern has 18% lossless priority and 27% lossy priority traffic. - Total ingress link is sending only 45% link capacity and hence egress will not be congested. - No losses for both lossless and lossy priority traffic. - - Args: - snappi_api (pytest fixture): SNAPPI session - conn_graph_facts (pytest fixture): connection graph - fanout_graph_facts (pytest fixture): fanout graph - duthosts (pytest fixture): list of DUTs - prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). - line_card_choice: Line card choice to be mentioned in the variable.py file - linecard_configuration_set : Line card classification, (min 1 or max 2 hostnames and asics to be given) - Returns: - N/A - """ - if (line_card_choice == 'chassis_slcsa_400Gbps'): - pytest.skip('Not enough 400Gbps ports on Single LC Single ASICs') - - # port_map is defined as port-speed combination. - # first two parameters are count of egress links and its speed. - # last two parameters are count of ingress links and its speed. - if '100Gbps' in line_card_choice: - port_map = [1, 100, 2, 100] - else: - port_map = [1, 400, 2, 400] - - # pkt_size of 1024B will be used unless imix flag is set. - # With imix flag set, the traffic_generation.py uses IMIX profile. - pkt_size = 1024 - - # Percentage drop expected for lossless and lossy traffic. - # speed_tol is speed tolerance between egress link speed and actual speed. - # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 14, 'loss_expected': False, 'pfc': False} - - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 18, - 'BG_FLOW_AGGR_RATE_PERCENT': 27, - 'data_flow_pkt_size': pkt_size, - 'DATA_FLOW_DURATION_SEC': 300, - 'data_flow_delay_sec': 0, - 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/Two_Ingress_Single_Egress_non_cngstn_'+str(port_map[1])+'Gbps', - 'line_card_choice': line_card_choice, - 'port_map': port_map, - 'enable_pfcwd': True, - 'enable_credit_wd': True, - 'stats_interval': 60, - 'background_traffic': True, - 'imix': False, - 'test_check': test_check, - 'verify_flows': False} - - logger.info('Starting the test for line_card_choice : {}'.format(line_card_choice)) - if line_card_choice not in linecard_configuration_set.keys(): - assert False, "Invalid line_card_choice value passed in parameter" - - if (len(linecard_configuration_set[line_card_choice]['hostname']) >= 2): - dut_list = [dut for dut in duthosts - if dut.hostname in linecard_configuration_set[line_card_choice]['hostname']] - duthost1, duthost2 = dut_list - elif (len(linecard_configuration_set[line_card_choice]['hostname']) == 1): - dut_list = [dut for dut in duthosts - if linecard_configuration_set[line_card_choice]['hostname'] == [dut.hostname]] - duthost1 = duthost2 = dut_list[0] - else: - assert False, "Hostname can't be an empty list" - - snappi_port_list = get_multidut_snappi_ports(line_card_choice=line_card_choice, - line_card_info=linecard_configuration_set[line_card_choice]) - - if len(snappi_port_list) < 3: - assert False, "snappi_port_list: Need Minimum of 3 ports for the test" - - # port_map is read as egress port_map[0] links of port_map[1] speed - # and ingress port_map[2] links of port_map[3] speed - port_map = test_def['port_map'] - - snappi_ports = new_get_multidut_tgen_peer_port_set(line_card_choice, snappi_port_list, config_set, port_map) - - if len(snappi_ports) < 3: - assert False, "snappi_ports: Need Minimum of 3 ports for the test" - - testbed_config, port_config_list, snappi_ports = snappi_dut_base_config(dut_list, - snappi_ports, - snappi_api) - - test_prio_list = [3, 4] - pause_prio_list = test_prio_list - bg_prio_list = [0, 1, 2] - logger.info("Snappi Ports : {}".format(snappi_ports)) - - snappi_extra_params = SnappiSysTestParams() - snappi_extra_params.multi_dut_params.duthost1 = duthost1 - snappi_extra_params.multi_dut_params.duthost2 = duthost2 - snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports - - try: - run_pfc_test(api=snappi_api, - testbed_config=testbed_config, - port_config_list=port_config_list, - conn_data=conn_graph_facts, - fanout_data=fanout_graph_facts, - global_pause=False, - pause_prio_list=pause_prio_list, - test_prio_list=test_prio_list, - bg_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - test_traffic_pause=False, - test_def=test_def, - snappi_extra_params=snappi_extra_params) - finally: - cleanup_config(dut_list, snappi_ports) From d28cdb3984e64c2941cabe4d41c0d1dcfe9a3548 Mon Sep 17 00:00:00 2001 From: amitpawa Date: Mon, 7 Oct 2024 11:56:45 -0400 Subject: [PATCH 06/12] snappi: new snappi non-congestion testcase --- .../systest/files/sys_multidut_helper.py | 381 +++++++++++++++ .../systest/test_sys_non_congestion.py | 445 ++++++++++++++++++ 2 files changed, 826 insertions(+) create mode 100644 tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py create mode 100644 tests/snappi_tests/multidut/systest/test_sys_non_congestion.py diff --git a/tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py b/tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py new file mode 100644 index 00000000000..2618b18ee49 --- /dev/null +++ b/tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py @@ -0,0 +1,381 @@ +import logging +import time + +from tests.common.helpers.assertions import pytest_assert +from tests.common.fixtures.conn_graph_facts import conn_graph_facts,\ + fanout_graph_facts # noqa F401 +from tests.common.snappi_tests.common_helpers import pfc_class_enable_vector,\ + get_lossless_buffer_size, get_pg_dropped_packets,\ + stop_pfcwd, disable_packet_aging, sec_to_nanosec,\ + get_pfc_frame_count, packet_capture, config_capture_pkt,\ + start_pfcwd, enable_packet_aging, \ + traffic_flow_mode, calc_pfc_pause_flow_rate # noqa F401 +from tests.common.snappi_tests.port import select_ports, select_tx_port # noqa F401 +from tests.common.snappi_tests.snappi_helpers import wait_for_arp # noqa F401 +from tests.common.snappi_tests.traffic_generation import generate_sys_pause_flows, verify_pause_flow, \ + verify_basic_test_flow, verify_background_flow, verify_pause_frame_count_dut, verify_sys_egress_queue_count, \ + verify_in_flight_buffer_pkts, verify_unset_cev_pause_frame_count, run_sys_traffic, new_base_traffic_config, \ + generate_sys_test_flows, generate_sys_background_flows +from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams +from tests.common.snappi_tests.read_pcap import validate_pfc_frame + +logger = logging.getLogger(__name__) + +dut_port_config = [] +PAUSE_FLOW_NAME = 'Pause Storm' +TEST_FLOW_NAME = 'Test Flow' +BG_FLOW_NAME = 'Background Flow' +TOLERANCE_THRESHOLD = 0.1 +CONTINUOUS_MODE = -5 +ANSIBLE_POLL_DELAY_SEC = 4 +global DATA_FLOW_DURATION_SEC +global data_flow_delay_sec + + +def run_pfc_test(api, + testbed_config, + port_config_list, + conn_data, + fanout_data, + global_pause, + pause_prio_list, + test_prio_list, + bg_prio_list, + prio_dscp_map, + test_traffic_pause, + test_def, + snappi_extra_params=None): + """ + Run a multidut PFC test + Args: + api (obj): snappi session + testbed_config (obj): testbed L1/L2/L3 configuration + port_config_list (list): list of port configuration + conn_data (dict): the dictionary returned by conn_graph_fact. + fanout_data (dict): the dictionary returned by fanout_graph_fact. + duthost (Ansible host instance): device under test + dut_port (str): DUT port to test + global_pause (bool): if pause frame is IEEE 802.3X pause + pause_prio_list (list): priorities to pause for pause frames + test_prio_list (list): priorities of test flows + bg_prio_list (list): priorities of background flows + prio_dscp_map (dict): Priority vs. DSCP map (key = priority). + test_traffic_pause (bool): if test flows are expected to be paused + test_def['enable_pause'] (bool) : if test expects no pause flow traffic. + snappi_extra_params (SnappiSysTestParams obj): additional parameters for Snappi traffic + + Returns: + N/A + """ + + TEST_FLOW_AGGR_RATE_PERCENT = test_def['TEST_FLOW_AGGR_RATE_PERCENT'] + BG_FLOW_AGGR_RATE_PERCENT = test_def['BG_FLOW_AGGR_RATE_PERCENT'] + data_flow_pkt_size = test_def['data_flow_pkt_size'] + DATA_FLOW_DURATION_SEC = test_def['DATA_FLOW_DURATION_SEC'] + data_flow_delay_sec = test_def['data_flow_delay_sec'] + SNAPPI_POLL_DELAY_SEC = test_def['SNAPPI_POLL_DELAY_SEC'] + PAUSE_FLOW_DUR_BASE_SEC = data_flow_delay_sec + DATA_FLOW_DURATION_SEC + if test_def['imix']: + fname = test_def['test_type'] + '_' + test_def['line_card_choice'] + '_' + 'IMIX' + else: + fname = test_def['test_type'] + '_' + test_def['line_card_choice'] + '_' + str(data_flow_pkt_size) + 'B' + port_map = test_def['port_map'] + + if snappi_extra_params is None: + snappi_extra_params = SnappiSysTestParams() + + # Traffic flow: + # tx_port (TGEN) --- ingress DUT --- egress DUT --- rx_port (TGEN) + + rx_port = snappi_extra_params.multi_dut_params.multi_dut_ports[0] + egress_duthost = rx_port['duthost'] + + tx_port = snappi_extra_params.multi_dut_params.multi_dut_ports[1] + ingress_duthost = tx_port['duthost'] + + dut_list = [] + dut_list.append(egress_duthost) + dut_list.append(ingress_duthost) + + if (test_traffic_pause): + logger.info("PFC receiving DUT is {}".format(egress_duthost.hostname)) + + pytest_assert(testbed_config is not None, 'Fail to get L2/3 testbed config') + + if (test_def['enable_pfcwd']): + start_pfcwd(egress_duthost) + start_pfcwd(ingress_duthost) + else: + stop_pfcwd(egress_duthost) + stop_pfcwd(ingress_duthost) + + if (test_def['enable_credit_wd']): + enable_packet_aging(egress_duthost, rx_port['asic_value']) + enable_packet_aging(ingress_duthost, tx_port['asic_value']) + else: + disable_packet_aging(egress_duthost, rx_port['asic_value']) + disable_packet_aging(ingress_duthost, tx_port['asic_value']) + + # Port id of Rx port for traffic config + # rx_port_id and tx_port_id belong to IXIA chassis. + rx_port_id = 0 + + # Rate percent must be an integer + bg_flow_rate_percent = int(BG_FLOW_AGGR_RATE_PERCENT / len(bg_prio_list)) + test_flow_rate_percent = int(TEST_FLOW_AGGR_RATE_PERCENT / len(test_prio_list)) + # Generate base traffic config + for i in range(port_map[2]): + tx_port_id = i+1 + snappi_extra_params.base_flow_config.append(new_base_traffic_config(testbed_config=testbed_config, + port_config_list=port_config_list, + rx_port_id=rx_port_id, + tx_port_id=tx_port_id)) + + speed_str = testbed_config.layer1[0].speed + speed_gbps = int(speed_str.split('_')[1]) + + if snappi_extra_params.headroom_test_params is not None: + DATA_FLOW_DURATION_SEC += 10 + data_flow_delay_sec += 2 + + # Set up pfc delay parameter + l1_config = testbed_config.layer1[0] + pfc = l1_config.flow_control.ieee_802_1qbb + pfc.pfc_delay = snappi_extra_params.headroom_test_params[0] + + if snappi_extra_params.poll_device_runtime: + # If the switch needs to be polled as traffic is running for stats, + # then the test runtime needs to be increased for the polling delay + DATA_FLOW_DURATION_SEC += ANSIBLE_POLL_DELAY_SEC + data_flow_delay_sec = ANSIBLE_POLL_DELAY_SEC + + if snappi_extra_params.packet_capture_type != packet_capture.NO_CAPTURE: + # Setup capture config + if snappi_extra_params.is_snappi_ingress_port_cap: + # packet capture is required on the ingress snappi port + snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["rx_port_name"]] + else: + # packet capture will be on the egress snappi port + snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["tx_port_name"]] + + snappi_extra_params.packet_capture_file = snappi_extra_params.packet_capture_type.value + + config_capture_pkt(testbed_config=testbed_config, + port_names=snappi_extra_params.packet_capture_ports, + capture_type=snappi_extra_params.packet_capture_type, + capture_name=snappi_extra_params.packet_capture_file) + logger.info("Packet capture file: {}.pcapng".format(snappi_extra_params.packet_capture_file)) + + # Set default traffic flow configs if not set + if snappi_extra_params.traffic_flow_config.data_flow_config is None: + snappi_extra_params.traffic_flow_config.data_flow_config = { + "flow_name": TEST_FLOW_NAME, + "flow_dur_sec": DATA_FLOW_DURATION_SEC, + "flow_rate_percent": test_flow_rate_percent, + "flow_rate_pps": None, + "flow_rate_bps": None, + "flow_pkt_count": None, + "flow_pkt_size": data_flow_pkt_size, + "flow_delay_sec": data_flow_delay_sec, + "flow_traffic_type": traffic_flow_mode.FIXED_DURATION + } + + if snappi_extra_params.traffic_flow_config.background_flow_config is None and \ + snappi_extra_params.gen_background_traffic: + snappi_extra_params.traffic_flow_config.background_flow_config = { + "flow_name": BG_FLOW_NAME, + "flow_dur_sec": DATA_FLOW_DURATION_SEC, + "flow_rate_percent": bg_flow_rate_percent, + "flow_rate_pps": None, + "flow_rate_bps": None, + "flow_pkt_size": data_flow_pkt_size, + "flow_pkt_count": None, + "flow_delay_sec": data_flow_delay_sec, + "flow_traffic_type": traffic_flow_mode.FIXED_DURATION + } + + if (test_traffic_pause): + if snappi_extra_params.traffic_flow_config.pause_flow_config is None: + snappi_extra_params.traffic_flow_config.pause_flow_config = { + "flow_name": PAUSE_FLOW_NAME, + "flow_dur_sec": None, + "flow_rate_percent": None, + "flow_rate_pps": calc_pfc_pause_flow_rate(speed_gbps), + "flow_rate_bps": None, + "flow_pkt_size": 64, + "flow_pkt_count": None, + "flow_delay_sec": 0, + "flow_traffic_type": traffic_flow_mode.CONTINUOUS + } + + if snappi_extra_params.packet_capture_type == packet_capture.PFC_CAPTURE: + # PFC pause frame capture is requested + valid_pfc_frame_test = True + else: + # PFC pause frame capture is not requested + valid_pfc_frame_test = False + + if (test_traffic_pause): + if valid_pfc_frame_test: + snappi_extra_params.traffic_flow_config.pause_flow_config["flow_dur_sec"] = DATA_FLOW_DURATION_SEC + \ + data_flow_delay_sec + SNAPPI_POLL_DELAY_SEC + PAUSE_FLOW_DUR_BASE_SEC + snappi_extra_params.traffic_flow_config.pause_flow_config["flow_traffic_type"] = \ + traffic_flow_mode.FIXED_DURATION + + # Generate test flow config based on number of ingress ports + # Every ingress port will be used as index. Example - test flow stream 0 - for first ingress. + for m in range(port_map[2]): + generate_sys_test_flows(testbed_config=testbed_config, + test_flow_prio_list=test_prio_list, + prio_dscp_map=prio_dscp_map, + snappi_extra_params=snappi_extra_params, + snap_index=m) + + if (test_def['background_traffic']): + for m in range(port_map[2]): + if snappi_extra_params.gen_background_traffic: + # Generate background flow config + generate_sys_background_flows(testbed_config=testbed_config, + bg_flow_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + snappi_extra_params=snappi_extra_params, + snap_index=m) + + # Generate pause storm config + if (test_traffic_pause): + for m in range(port_map[0]): + generate_sys_pause_flows(testbed_config=testbed_config, + pause_prio_list=pause_prio_list, + global_pause=global_pause, + snappi_extra_params=snappi_extra_params, + snap_index=m) + + flows = testbed_config.flows + + all_flow_names = [flow.name for flow in flows] + data_flow_names = [flow.name for flow in flows if PAUSE_FLOW_NAME not in flow.name] + + # Clear PFC, queue and interface counters before traffic run + for dut in dut_list: + dut.command("pfcstat -c \n") + time.sleep(1) + dut.command("sonic-clear queuecounters \n") + time.sleep(1) + dut.command("sonic-clear counters \n") + time.sleep(1) + + exp_dur_sec = DATA_FLOW_DURATION_SEC + data_flow_delay_sec + + """ Run traffic """ + tgen_flow_stats, switch_flow_stats, test_stats = run_sys_traffic(rx_duthost=ingress_duthost, + tx_duthost=egress_duthost, + api=api, + config=testbed_config, + data_flow_names=data_flow_names, + all_flow_names=all_flow_names, + exp_dur_sec=exp_dur_sec, + port_map=test_def['port_map'], + fname=fname, + stats_interval=test_def['stats_interval'], + imix=test_def['imix'], + snappi_extra_params=snappi_extra_params) + + test_check = test_def['test_check'] + if (not test_check['loss_expected']): + # Check for loss packets on IXIA and DUT. + pytest_assert(test_stats['tgen_loss_pkts'] == 0, 'Loss seen on TGEN') + pytest_assert(test_stats['dut_loss_pkts'] == 0, 'Loss seen on DUT') + + # Check for Tx and Rx packets on IXIA for lossless and lossy streams. + pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['tgen_lossless_tx_pkts'], + 'Losses observed in lossless traffic streams') + pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['tgen_lossy_tx_pkts'], + 'Losses observed in lossy traffic streams') + + # Check for Rx packets between IXIA and DUT for lossy and lossless streams. + pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['dut_lossless_pkts'], + 'Losses observed in lossless traffic streams on DUT Tx and IXIA Rx') + pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['dut_lossy_pkts'], + 'Losses observed in lossy traffic streams on DUT Tx and IXIA Rx') + else: + # Check for lossless and lossy stream percentage drop for a given tolerance limit. + lossless_drop = round((1 - float(test_stats['tgen_lossless_rx_pkts']) / test_stats['tgen_lossless_tx_pkts']), 2) + lossy_drop = round((1 - float(test_stats['tgen_lossy_rx_pkts']) / test_stats['tgen_lossy_tx_pkts']), 2) + logger.info('Lossless Drop %:{}, Lossy Drop %:{}'.format(lossless_drop, lossy_drop)) + pytest_assert((lossless_drop*100) <= test_check['lossless'], 'Lossless packet drop outside tolerance limit') + pytest_assert((lossy_drop*100) <= test_check['lossy'], 'Lossy packet drop outside tolerance limit') + + # Checking if the actual line rate on egress is within tolerable limit of egress line speed. + pytest_assert(((1 - test_stats['tgen_rx_rate'] / float(port_map[0]*port_map[1]))*100) <= test_check['speed_tol'], + 'Egress speed beyond tolerance range') + + # Checking for PFC counts on DUT + if (not test_check['pfc']): + pytest_assert(test_stats['lossless_tx_pfc'] == 0, 'Error:PFC transmitted by DUT for lossless priorities') + pytest_assert(test_stats['lossy_rx_tx_pfc'] == 0, 'Error:PFC transmitted by DUT for lossy priorities') + else: + if (test_stats['lossless_rx_pfc'] != 0): + pytest_assert(test_stats['lossless_tx_pfc'] > 0, 'Error:No Tx PFCs from DUT after receiving PFCs') + pytest_assert(test_stats['lossless_tx_pfc'] > 0, 'Error: PFC not be transmitted from DUT on congestion') + pytest_assert(test_stats['lossy_rx_tx_pfc'] == 0, 'Error:Incorrect Rx/Tx PFCs on DUT for lossy priorities') + + # Reset pfc delay parameter + pfc = testbed_config.layer1[0].flow_control.ieee_802_1qbb + pfc.pfc_delay = 0 + + # Verify PFC pause frames + if (test_traffic_pause): + if valid_pfc_frame_test: + is_valid_pfc_frame = validate_pfc_frame(snappi_extra_params.packet_capture_file + ".pcapng") + pytest_assert(is_valid_pfc_frame, "PFC frames invalid") + return + + # Verify pause flows + if (test_traffic_pause): + for metric in tgen_flow_stats: + if PAUSE_FLOW_NAME in metric.name: + pause_flow_name = metric.name + verify_pause_flow(flow_metrics=tgen_flow_stats, + pause_flow_name=pause_flow_name) + + # Check for the flows ONLY if normal packet size (non-imix) is used. + if (test_def['background_traffic'] and test_def['verify_flows'] and not test_def['imix']): + if snappi_extra_params.gen_background_traffic: + # Verify background flows + verify_background_flow(flow_metrics=tgen_flow_stats, + speed_gbps=speed_gbps, + tolerance=TOLERANCE_THRESHOLD, + snappi_extra_params=snappi_extra_params) + + # Verify basic test flows metrics from ixia + if (test_def['verify_flows'] and not test_def['imix']): + verify_basic_test_flow(flow_metrics=tgen_flow_stats, + speed_gbps=speed_gbps, + tolerance=TOLERANCE_THRESHOLD, + test_flow_pause=test_traffic_pause, + snappi_extra_params=snappi_extra_params) + + if (test_traffic_pause and test_def['verify_flows']): + verify_pause_frame_count_dut(rx_dut=ingress_duthost, + tx_dut=egress_duthost, + test_traffic_pause=test_traffic_pause, + global_pause=global_pause, + snappi_extra_params=snappi_extra_params) + + # Verify in flight TX lossless packets do not leave the DUT when traffic is expected + # to be paused, or leave the DUT when the traffic is not expected to be paused + verify_sys_egress_queue_count(duthost=egress_duthost, + switch_flow_stats=switch_flow_stats, + test_traffic_pause=test_traffic_pause, + snappi_extra_params=snappi_extra_params) + + if (test_traffic_pause and test_def['verify_flows']): + # Verify in flight TX packets count relative to switch buffer size + verify_in_flight_buffer_pkts(duthost=ingress_duthost, + asic_value=rx_port['asic_value'], + flow_metrics=tgen_flow_stats, + snappi_extra_params=snappi_extra_params) + + # Verify zero pause frames are counted when the PFC class enable vector is not set + verify_unset_cev_pause_frame_count(duthost=egress_duthost, + snappi_extra_params=snappi_extra_params) diff --git a/tests/snappi_tests/multidut/systest/test_sys_non_congestion.py b/tests/snappi_tests/multidut/systest/test_sys_non_congestion.py new file mode 100644 index 00000000000..81c46fc6aa8 --- /dev/null +++ b/tests/snappi_tests/multidut/systest/test_sys_non_congestion.py @@ -0,0 +1,445 @@ +import pytest +import random +from tests.common.helpers.assertions import pytest_require, pytest_assert # noqa: F401 +from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts_multidut # noqa: F401 +from tests.common.snappi_tests.snappi_fixtures import snappi_api_serv_ip, snappi_api_serv_port, \ + snappi_api, cleanup_config, get_snappi_ports_for_rdma, snappi_sys_base_config, \ + get_snappi_ports, get_snappi_ports_multi_dut, clear_fabric_counters, check_fabric_counters # noqa: F401 +from tests.common.snappi_tests.qos_fixtures import prio_dscp_map, lossless_prio_list, \ + lossy_prio_list, all_prio_list # noqa: F401 +from tests.snappi_tests.multidut.systest.files.sys_multidut_helper import run_pfc_test +from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams +from tests.snappi_tests.variables import MULTIDUT_PORT_INFO, MULTIDUT_TESTBED + +import logging +logger = logging.getLogger(__name__) + +pytestmark = [pytest.mark.topology('multidut-tgen')] + +port_map = [[1, 100, 1, 100]] + +# Testplan: docs/testplan/PFC_Snappi_Additional_Testcases.md +# This test-script covers testcase#01-non-congestion(normal). + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_multiple_prio_diff_dist(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + + """ + Purpose of the test is to check if line-rate can be achieved. + Traffic distribution is 88% lossless priority 3 and 4 traffic. + There is additional 12% of lossy priority 0, 1 and 2 traffic. + PFCWD and Credit-watchdog is enabled. + Packet-size is 1024. IMIX can be enabled by setting imix to True. + No losses should be seen for both lossy and lossless traffic. + No PFCs should be generated during the test. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + Returns: + N/A + + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': False} + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 88, + 'BG_FLOW_AGGR_RATE_PERCENT': 12, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Single_Ingress_Egress_diff_dist_'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'imix': False, + 'test_check': test_check, + 'verify_flows': True} + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + for dut in duthosts: + check_fabric_counters(dut) + + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_multiple_prio_uni_dist(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + + """ + Purpose of the test is to check if line-rate can be achieved. + Traffic distribution is 40% lossless priority 3 and 4 traffic. + There is additional 60% of lossy priority 0, 1 and 2 traffic. + PFCWD and Credit-watchdog is enabled. + Packet-size is 1024. IMIX can be enabled by setting imix to True. + No losses should be seen for both lossy and lossless traffic. + No PFCs should be generated during the test. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + + Returns: + N/A + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': False} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, + 'BG_FLOW_AGGR_RATE_PERCENT': 60, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Single_Ingress_Egress_uni_dist_'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'imix': False, + 'test_check': test_check, + 'verify_flows': True} + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + for dut in duthosts: + check_fabric_counters(dut) + + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_single_lossless_prio(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + + """ + Purpose of the test is to check if line-rate can be achieved with single priority traffic. + Traffic distribution is 100% lossless priority 3 traffic. + PFCWD and Credit-watchdog is enabled. + Packet-size is 1024. IMIX can be enabled by setting imix to True. + No losses should be seen for both lossy and lossless traffic. + No PFCs should be generated during the test. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + + Returns: + N/A + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + # background_traffic is set to False. + # test_flow_aggregate_rate_percent is set to 100% to ensure all to be single lossless priority traffic. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': False} + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 100, + 'BG_FLOW_AGGR_RATE_PERCENT': 50, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Single_Ingress_Egress_1Prio_linerate_'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': False, + 'imix': False, + 'test_check': test_check, + 'verify_flows': True} + + # Selecting only one lossless priority for the test. + test_prio_list = random.sample(lossless_prio_list, 1) + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless priority:{} for the test'.format(test_prio_list)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + for dut in duthosts: + check_fabric_counters(dut) + + finally: + cleanup_config(dut_list, snappi_ports) From 71ad95b83184ab2be8b6c6cf6b41b7ed3b5f5216 Mon Sep 17 00:00:00 2001 From: amitpawa Date: Mon, 7 Oct 2024 12:03:00 -0400 Subject: [PATCH 07/12] snappi: new snappi over-subscription testcase --- .../systest/test_sys_over_subscription.py | 570 ++++++++++++++++++ 1 file changed, 570 insertions(+) create mode 100644 tests/snappi_tests/multidut/systest/test_sys_over_subscription.py diff --git a/tests/snappi_tests/multidut/systest/test_sys_over_subscription.py b/tests/snappi_tests/multidut/systest/test_sys_over_subscription.py new file mode 100644 index 00000000000..05f3b89133f --- /dev/null +++ b/tests/snappi_tests/multidut/systest/test_sys_over_subscription.py @@ -0,0 +1,570 @@ +import pytest +import random +from tests.common.helpers.assertions import pytest_require, pytest_assert # noqa: F401 +from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts_multidut # noqa: F401 +from tests.common.snappi_tests.snappi_fixtures import snappi_api_serv_ip, snappi_api_serv_port, \ + snappi_api, snappi_sys_base_config, cleanup_config, get_snappi_ports_for_rdma, \ + get_snappi_ports, get_snappi_ports_multi_dut, clear_fabric_counters, check_fabric_counters # noqa: F401 +from tests.common.snappi_tests.qos_fixtures import prio_dscp_map, lossless_prio_list, \ + lossy_prio_list, all_prio_list # noqa: F401 +from tests.snappi_tests.variables import MULTIDUT_PORT_INFO, MULTIDUT_TESTBED +from tests.snappi_tests.multidut.systest.files.sys_multidut_helper import run_pfc_test +from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams + +import logging +logger = logging.getLogger(__name__) + +pytestmark = [pytest.mark.topology('multidut-tgen')] + +port_map = [[1, 100, 2, 100], [1, 400, 2, 400]] + +# Testplan: docs/testplan/PFC_Snappi_Additional_Testcases.md +# This test-script covers following testcases: +# testcase#04: DETECT CONGESTION WITH REAL-LIFE TRAFFIC PATTERN - 90% LOSSLESS and 10% LOSSY +# testcase#05: DETECT CONGESTION WITH EQUAL DISTRIBUTION OF LOSSLESS AND LOSSY TRAFFIC + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_multiple_prio_diff_dist(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + + """ + Purpose of the test case is to test oversubscription with two ingresses and single ingress. + Traffic pattern has 90% lossless priority and 10% lossy priority traffic. + No losses for both lossless and lossy priority traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + Returns: + N/A + + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': True} + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 88, + 'BG_FLOW_AGGR_RATE_PERCENT': 12, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Two_Ingress_Single_Egress_diff_dist_'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'imix': False, + 'test_check': test_check, + 'verify_flows': False} + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + for dut in duthosts: + check_fabric_counters(dut) + + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_multiple_prio_uni_dist(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + """ + Purpose of the test case is to test oversubscription with two ingresses and single ingress. + Traffic pattern has 24% lossless priority and 36% lossy priority traffic. + Each priority carries equal 12% of traffic. + No losses for lossless priority traffic. Some loss expected for lossy priority traffic. + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + + Returns: + N/A + """ + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 51, 'speed_tol': 51, 'loss_expected': True, 'pfc': True} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, + 'BG_FLOW_AGGR_RATE_PERCENT': 60, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Two_Ingress_Single_Egress_uni_dist_full'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'imix': False, + 'test_check': test_check, + 'verify_flows': False} + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + for dut in duthosts: + check_fabric_counters(dut) + + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_multiple_prio_uni_dist_full(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + + """ + Purpose of the test case is to test oversubscription with two ingresses and single ingress. + Traffic pattern has 24% lossless priority and 36% lossy priority traffic. + Each priority carries equal 12% of traffic. + No losses for lossless priority traffic. Some loss expected for lossy priority traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + + Returns: + N/A + """ + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 51, 'speed_tol': 51, 'loss_expected': True, 'pfc': True} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, + 'BG_FLOW_AGGR_RATE_PERCENT': 60, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Two_Ingress_Single_Egress_uni_dist_full'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'imix': False, + 'test_check': test_check, + 'verify_flows': False} + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + for dut in duthosts: + check_fabric_counters(dut) + + finally: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_multiple_prio_non_cngtn(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + + """ + Purpose of the test case is to test oversubscription with two ingresses and single ingress. + Traffic pattern has 18% lossless priority and 27% lossy priority traffic. + Total ingress link is sending only 45% link capacity and hence egress will not be congested. + No losses for both lossless and lossy priority traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + Returns: + N/A + + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 14, 'loss_expected': False, 'pfc': False} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 18, + 'BG_FLOW_AGGR_RATE_PERCENT': 27, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 0, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Two_Ingress_Single_Egress_non_cngstn_'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'imix': False, + 'test_check': test_check, + 'verify_flows': False} + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=False, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + for dut in duthosts: + check_fabric_counters(dut) + + finally: + cleanup_config(dut_list, snappi_ports) From 4d9d910b498802bd78da1398426b4248907bd4c1 Mon Sep 17 00:00:00 2001 From: amitpawa Date: Mon, 7 Oct 2024 12:09:26 -0400 Subject: [PATCH 08/12] snappi: new snappi pfcwd testcase --- .../systest/files/pfcwd_multidut_helper.py | 369 ++++++++ .../multidut/systest/test_sys_pfcwd.py | 848 ++++++++++++++++++ 2 files changed, 1217 insertions(+) create mode 100644 tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py create mode 100644 tests/snappi_tests/multidut/systest/test_sys_pfcwd.py diff --git a/tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py b/tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py new file mode 100644 index 00000000000..9dbdd06e2ec --- /dev/null +++ b/tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py @@ -0,0 +1,369 @@ +import logging +import time + +from tests.common.helpers.assertions import pytest_assert +from tests.common.fixtures.conn_graph_facts import conn_graph_facts,\ + fanout_graph_facts # noqa F401 +from tests.common.snappi_tests.common_helpers import pfc_class_enable_vector,\ + get_lossless_buffer_size, get_pg_dropped_packets,\ + stop_pfcwd, disable_packet_aging, sec_to_nanosec,\ + get_pfc_frame_count, packet_capture, config_capture_pkt,\ + start_pfcwd, enable_packet_aging, start_pfcwd_fwd, \ + traffic_flow_mode, calc_pfc_pause_flow_rate # noqa F401 +from tests.common.snappi_tests.port import select_ports, select_tx_port # noqa F401 +from tests.common.snappi_tests.snappi_helpers import wait_for_arp # noqa F401 +from tests.common.snappi_tests.traffic_generation import verify_pause_flow, \ + verify_basic_test_flow, verify_background_flow, verify_pause_frame_count_dut, \ + run_sys_traffic, new_base_traffic_config, \ + generate_sys_test_flows, generate_sys_background_flows, generate_sys_pause_flows +from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams + + +logger = logging.getLogger(__name__) + +dut_port_config = [] +PAUSE_FLOW_NAME = 'Pause Storm' +TEST_FLOW_NAME = 'Test Flow' +BG_FLOW_NAME = 'Background Flow' +TOLERANCE_THRESHOLD = 0.1 +CONTINUOUS_MODE = -5 +ANSIBLE_POLL_DELAY_SEC = 4 +global DATA_FLOW_DURATION_SEC +global data_flow_delay_sec + + +def run_pfc_test(api, + testbed_config, + port_config_list, + conn_data, + fanout_data, + global_pause, + pause_prio_list, + test_prio_list, + bg_prio_list, + prio_dscp_map, + test_traffic_pause, + test_def, + snappi_extra_params=None): + """ + Run a multidut PFC test + Args: + api (obj): snappi session + testbed_config (obj): testbed L1/L2/L3 configuration + port_config_list (list): list of port configuration + conn_data (dict): the dictionary returned by conn_graph_fact. + fanout_data (dict): the dictionary returned by fanout_graph_fact. + duthost (Ansible host instance): device under test + dut_port (str): DUT port to test + global_pause (bool): if pause frame is IEEE 802.3X pause + pause_prio_list (list): priorities to pause for pause frames + test_prio_list (list): priorities of test flows + bg_prio_list (list): priorities of background flows + prio_dscp_map (dict): Priority vs. DSCP map (key = priority). + test_traffic_pause (bool): if test flows are expected to be paused + test_def['enable_pause'] (bool) : if test expects no pause flow traffic. + snappi_extra_params (SnappiSysTestParams obj): additional parameters for Snappi traffic + + Returns: + N/A + """ + + TEST_FLOW_AGGR_RATE_PERCENT = test_def['TEST_FLOW_AGGR_RATE_PERCENT'] + BG_FLOW_AGGR_RATE_PERCENT = test_def['BG_FLOW_AGGR_RATE_PERCENT'] + data_flow_pkt_size = test_def['data_flow_pkt_size'] + DATA_FLOW_DURATION_SEC = test_def['DATA_FLOW_DURATION_SEC'] + data_flow_delay_sec = test_def['data_flow_delay_sec'] + SNAPPI_POLL_DELAY_SEC = test_def['SNAPPI_POLL_DELAY_SEC'] + PAUSE_FLOW_DUR_BASE_SEC = data_flow_delay_sec + DATA_FLOW_DURATION_SEC + if test_def['imix']: + fname = test_def['test_type'] + '_' + test_def['line_card_choice'] + '_' + 'IMIX' + else: + fname = test_def['test_type'] + '_' + test_def['line_card_choice'] + '_' + str(data_flow_pkt_size) + 'B' + + port_map = test_def['port_map'] + + if snappi_extra_params is None: + snappi_extra_params = SnappiSysTestParams() + + # Traffic flow: + # tx_port (TGEN) --- ingress DUT --- egress DUT --- rx_port (TGEN) + + rx_port = snappi_extra_params.multi_dut_params.multi_dut_ports[0] + egress_duthost = rx_port['duthost'] + + tx_port = snappi_extra_params.multi_dut_params.multi_dut_ports[-1] + ingress_duthost = tx_port['duthost'] + dut_list = [egress_duthost, ingress_duthost] + + if (test_traffic_pause): + logger.info("PFC receiving DUT is {}".format(egress_duthost.hostname)) + + pytest_assert(testbed_config is not None, 'Fail to get L2/3 testbed config') + + if (test_def['enable_pfcwd_drop']): + start_pfcwd(egress_duthost) + start_pfcwd(ingress_duthost) + elif (test_def['enable_pfcwd_fwd']): + start_pfcwd_fwd(egress_duthost) + start_pfcwd_fwd(ingress_duthost) + else: + stop_pfcwd(egress_duthost) + stop_pfcwd(ingress_duthost) + + if (test_def['enable_credit_wd']): + enable_packet_aging(egress_duthost, rx_port['asic_value']) + enable_packet_aging(ingress_duthost, tx_port['asic_value']) + else: + disable_packet_aging(egress_duthost, rx_port['asic_value']) + disable_packet_aging(ingress_duthost, tx_port['asic_value']) + + rx_port_id = 0 + + # Rate percent must be an integer + bg_flow_rate_percent = int(BG_FLOW_AGGR_RATE_PERCENT / len(bg_prio_list)) + test_flow_rate_percent = int(TEST_FLOW_AGGR_RATE_PERCENT / len(test_prio_list)) + # Generate base traffic config + if (port_map[0] == 2): + for i in range(port_map[0]): + rx_port_id = i + tx_port_id = 2 + snappi_extra_params.base_flow_config.append(new_base_traffic_config(testbed_config=testbed_config, + port_config_list=port_config_list, + rx_port_id=rx_port_id, + tx_port_id=tx_port_id)) + else: + rx_port_id = 0 + for i in range(port_map[2]): + tx_port_id = i+1 + snappi_extra_params.base_flow_config.append(new_base_traffic_config(testbed_config=testbed_config, + port_config_list=port_config_list, + rx_port_id=rx_port_id, + tx_port_id=tx_port_id)) + + speed_str = testbed_config.layer1[0].speed + speed_gbps = int(speed_str.split('_')[1]) + + if snappi_extra_params.headroom_test_params is not None: + DATA_FLOW_DURATION_SEC += 10 + data_flow_delay_sec += 2 + + # Set up pfc delay parameter + l1_config = testbed_config.layer1[0] + pfc = l1_config.flow_control.ieee_802_1qbb + pfc.pfc_delay = snappi_extra_params.headroom_test_params[0] + + if snappi_extra_params.poll_device_runtime: + # If the switch needs to be polled as traffic is running for stats, + # then the test runtime needs to be increased for the polling delay + DATA_FLOW_DURATION_SEC += ANSIBLE_POLL_DELAY_SEC + data_flow_delay_sec = ANSIBLE_POLL_DELAY_SEC + + if snappi_extra_params.packet_capture_type != packet_capture.NO_CAPTURE: + # Setup capture config + if snappi_extra_params.is_snappi_ingress_port_cap: + # packet capture is required on the ingress snappi port + snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["rx_port_name"]] + else: + # packet capture will be on the egress snappi port + snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["tx_port_name"]] + + snappi_extra_params.packet_capture_file = snappi_extra_params.packet_capture_type.value + + config_capture_pkt(testbed_config=testbed_config, + port_names=snappi_extra_params.packet_capture_ports, + capture_type=snappi_extra_params.packet_capture_type, + capture_name=snappi_extra_params.packet_capture_file) + logger.info("Packet capture file: {}.pcapng".format(snappi_extra_params.packet_capture_file)) + + # Set default traffic flow configs if not set + if snappi_extra_params.traffic_flow_config.data_flow_config is None: + snappi_extra_params.traffic_flow_config.data_flow_config = { + "flow_name": TEST_FLOW_NAME, + "flow_dur_sec": DATA_FLOW_DURATION_SEC, + "flow_rate_percent": test_flow_rate_percent, + "flow_rate_pps": None, + "flow_rate_bps": None, + "flow_pkt_count": None, + "flow_pkt_size": data_flow_pkt_size, + "flow_delay_sec": data_flow_delay_sec, + "flow_traffic_type": traffic_flow_mode.FIXED_DURATION + } + + if snappi_extra_params.traffic_flow_config.background_flow_config is None and \ + snappi_extra_params.gen_background_traffic: + snappi_extra_params.traffic_flow_config.background_flow_config = { + "flow_name": BG_FLOW_NAME, + "flow_dur_sec": DATA_FLOW_DURATION_SEC, + "flow_rate_percent": bg_flow_rate_percent, + "flow_rate_pps": None, + "flow_rate_bps": None, + "flow_pkt_size": data_flow_pkt_size, + "flow_pkt_count": None, + "flow_delay_sec": data_flow_delay_sec, + "flow_traffic_type": traffic_flow_mode.FIXED_DURATION + } + + # PPS is high to ensure Storm is detected. + # traffic_flow_mode is changed to BURST + # Need to check how it works + if (test_traffic_pause): + if snappi_extra_params.traffic_flow_config.pause_flow_config is None: + snappi_extra_params.traffic_flow_config.pause_flow_config = { + "flow_name": PAUSE_FLOW_NAME, + "flow_dur_sec": DATA_FLOW_DURATION_SEC+60, + "flow_rate_percent": None, + "flow_rate_pps": calc_pfc_pause_flow_rate(speed_gbps), + "flow_rate_bps": None, + "flow_pkt_size": 64, + "flow_pkt_count": None, + "flow_delay_sec": 0, + "flow_traffic_type": traffic_flow_mode.FIXED_DURATION + } + + if snappi_extra_params.packet_capture_type == packet_capture.PFC_CAPTURE: + # PFC pause frame capture is requested + valid_pfc_frame_test = True + else: + # PFC pause frame capture is not requested + valid_pfc_frame_test = False + + if (test_traffic_pause): + if valid_pfc_frame_test: + snappi_extra_params.traffic_flow_config.pause_flow_config["flow_dur_sec"] = DATA_FLOW_DURATION_SEC + \ + data_flow_delay_sec + SNAPPI_POLL_DELAY_SEC + PAUSE_FLOW_DUR_BASE_SEC + snappi_extra_params.traffic_flow_config.pause_flow_config["flow_traffic_type"] = \ + traffic_flow_mode.FIXED_DURATION + + # Generate test flow config + for m in range(port_map[2]): + generate_sys_test_flows(testbed_config=testbed_config, + test_flow_prio_list=test_prio_list, + prio_dscp_map=prio_dscp_map, + snappi_extra_params=snappi_extra_params, + snap_index=m) + + if (test_def['background_traffic']): + for m in range(port_map[2]): + if snappi_extra_params.gen_background_traffic: + # Generate background flow config + generate_sys_background_flows(testbed_config=testbed_config, + bg_flow_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + snappi_extra_params=snappi_extra_params, + snap_index=m) + + # Generate pause storm config + if (test_traffic_pause): + for m in range(port_map[0]): + generate_sys_pause_flows(testbed_config=testbed_config, + pause_prio_list=pause_prio_list, + global_pause=global_pause, + snappi_extra_params=snappi_extra_params, + snap_index=m) + + flows = testbed_config.flows + + all_flow_names = [flow.name for flow in flows] + data_flow_names = [flow.name for flow in flows if PAUSE_FLOW_NAME not in flow.name] + + # Clear PFC, queue and interface counters before traffic run + for dut in dut_list: + dut.command("pfcstat -c \n") + time.sleep(1) + dut.command("sonic-clear queuecounters \n") + time.sleep(1) + dut.command("sonic-clear counters \n") + time.sleep(1) + + exp_dur_sec = DATA_FLOW_DURATION_SEC + data_flow_delay_sec + + """ Run traffic """ + tgen_flow_stats, switch_flow_stats, test_stats = run_sys_traffic(rx_duthost=ingress_duthost, + tx_duthost=egress_duthost, + api=api, + config=testbed_config, + data_flow_names=data_flow_names, + all_flow_names=all_flow_names, + exp_dur_sec=exp_dur_sec, + port_map=test_def['port_map'], + fname=fname, + stats_interval=test_def['stats_interval'], + imix=test_def['imix'], + snappi_extra_params=snappi_extra_params) + + test_check = test_def['test_check'] + if (not test_check['loss_expected']): + # Check for loss packets on IXIA and DUT. + pytest_assert(test_stats['tgen_loss_pkts'] == 0, 'Loss seen on TGEN') + pytest_assert(test_stats['dut_loss_pkts'] == 0, 'Loss seen on DUT') + + # Check for Tx and Rx packets on IXIA for lossless and lossy streams. + pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['tgen_lossless_tx_pkts'], + 'Losses observed in lossless traffic streams') + pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['tgen_lossy_tx_pkts'], + 'Losses observed in lossy traffic streams') + + # Check for Rx packets between IXIA and DUT for lossy and lossless streams. + pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['dut_lossless_pkts'], + 'Losses observed in lossless traffic streams on DUT Tx and IXIA Rx') + pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['dut_lossy_pkts'], + 'Losses observed in lossy traffic streams on DUT Tx and IXIA Rx') + else: + # Check for lossless and lossy stream percentage drop for a given tolerance limit. + lossless_drop = round((1 - float(test_stats['tgen_lossless_rx_pkts']) / test_stats['tgen_lossless_tx_pkts']), 2) + lossy_drop = round((1 - float(test_stats['tgen_lossy_rx_pkts']) / test_stats['tgen_lossy_tx_pkts']), 2) + logger.info('Lossless Drop %:{}, Lossy Drop %:{}'.format(lossless_drop, lossy_drop)) + pytest_assert((lossless_drop*100) <= test_check['lossless'], 'Lossless packet drop outside tolerance limit') + pytest_assert((lossy_drop*100) <= test_check['lossy'], 'Lossy packet drop outside tolerance limit') + + # Checking if the actual line rate on egress is within tolerable limit of egress line speed. + pytest_assert(((1 - test_stats['tgen_rx_rate'] / float(port_map[0]*port_map[1]))*100) <= test_check['speed_tol'], + 'Egress speed beyond tolerance range') + + # Checking for PFC counts on DUT + if (not test_check['pfc']): + pytest_assert(test_stats['lossless_tx_pfc'] == 0, 'Error:PFC transmitted by DUT for lossless priorities') + pytest_assert(test_stats['lossy_rx_tx_pfc'] == 0, 'Error:PFC transmitted by DUT for lossy priorities') + else: + if (test_stats['lossless_rx_pfc'] != 0 and (test_def['enable_pfcwd_drop'] or test_def['enable_pfcwd_fwd'])): + pytest_assert(test_stats['lossless_tx_pfc'] == 0, 'Error:No Tx PFCs from DUT after receiving PFCs') + if (test_stats['lossless_rx_pfc'] != 0 and + (not test_def['enable_pfcwd_drop'] and not test_def['enable_pfcwd_fwd'])): + pytest_assert(test_stats['lossless_tx_pfc'] != 0, 'Error:Tx PFCs should sent from DUT after receiving PFCs') + pytest_assert(test_stats['lossy_rx_tx_pfc'] == 0, 'Error:Incorrect Rx/Tx PFCs on DUT for lossy priorities') + + # Reset pfc delay parameter + pfc = testbed_config.layer1[0].flow_control.ieee_802_1qbb + pfc.pfc_delay = 0 + + for metric in tgen_flow_stats: + if "Pause" in metric.name: + PAUSE_FLW_NAME = metric.name + + # Verify pause flows + if (test_traffic_pause): + verify_pause_flow(flow_metrics=tgen_flow_stats, + pause_flow_name=PAUSE_FLW_NAME) + + if (test_def['background_traffic'] and test_def['verify_flows']): + if snappi_extra_params.gen_background_traffic: + # Verify background flows + verify_background_flow(flow_metrics=tgen_flow_stats, + speed_gbps=speed_gbps, + tolerance=TOLERANCE_THRESHOLD, + snappi_extra_params=snappi_extra_params) + + # Verify basic test flows metrics from ixia + if (test_def['verify_flows']): + verify_basic_test_flow(flow_metrics=tgen_flow_stats, + speed_gbps=speed_gbps, + tolerance=TOLERANCE_THRESHOLD, + test_flow_pause=test_traffic_pause, + snappi_extra_params=snappi_extra_params) + + if (test_traffic_pause and test_def['verify_flows']): + verify_pause_frame_count_dut(rx_dut=ingress_duthost, + tx_dut=egress_duthost, + test_traffic_pause=test_traffic_pause, + global_pause=global_pause, + snappi_extra_params=snappi_extra_params) diff --git a/tests/snappi_tests/multidut/systest/test_sys_pfcwd.py b/tests/snappi_tests/multidut/systest/test_sys_pfcwd.py new file mode 100644 index 00000000000..1a350506a42 --- /dev/null +++ b/tests/snappi_tests/multidut/systest/test_sys_pfcwd.py @@ -0,0 +1,848 @@ +import pytest +import logging +import random +from tests.common.helpers.assertions import pytest_require, pytest_assert # noqa: F401 +from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts_multidut # noqa: F401 +from tests.common.snappi_tests.snappi_fixtures import snappi_api_serv_ip, snappi_api_serv_port, \ + snappi_api, snappi_sys_base_config, cleanup_config, get_snappi_ports_for_rdma, \ + get_snappi_ports, get_snappi_ports_multi_dut, clear_fabric_counters, check_fabric_counters # noqa: F401 +from tests.common.snappi_tests.qos_fixtures import prio_dscp_map, lossless_prio_list, \ + lossy_prio_list, all_prio_list # noqa: F401 +from tests.common.snappi_tests.common_helpers import get_pfcwd_stats +from tests.snappi_tests.multidut.systest.files.pfcwd_multidut_helper import run_pfc_test +from tests.common.config_reload import config_reload +from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams +from tests.snappi_tests.variables import MULTIDUT_PORT_INFO, MULTIDUT_TESTBED + +logger = logging.getLogger(__name__) + +pytestmark = [pytest.mark.topology('multidut-tgen')] + +port_map = [[1, 100, 1, 100], [1, 400, 1, 400]] + +# Testplan: docs/testplan/PFC_Snappi_Additional_Testcases.md +# This test-script covers testcase#10: PFCWD-enabled DROP mode test. +# This test-script also covers testcase#11: PFCWD-enabled FWD mode test. + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_pfcwd_drop_90_10(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + """ + Purpose of the test case is to enable PFCWD in drop mode and send 90% lossless traffic and 10% + lossy traffic and check the behavior. DUT is receiving pause storm on the egress port. DUT should + drop the lossless packets without generating any pause towards IXIA transmitter. No loss for lossy traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + + Returns: + N/A + """ + + pkt_size = 1024 + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 100, 'lossy': 0, 'speed_tol': 91, 'loss_expected': True, 'pfc': True} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 90, + 'BG_FLOW_AGGR_RATE_PERCENT': 10, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 1, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/One_Ingress_Egress_pfcwd_drop_90_10_dist'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd_drop': True, + 'enable_pfcwd_fwd': False, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'verify_flows': False, + 'imix': False, + 'test_check': test_check} + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + logger.info('PFC-WD stats at the start of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut_list[0].hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut.hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=True, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + logger.info('PFC-WD stats at the end of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) + + for dut in duthosts: + check_fabric_counters(dut) + + finally: + for duthost in dut_list: + config_reload(sonic_host=duthost, config_source='config_db', safe_reload=True) + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_pfcwd_frwd_90_10(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + + """ + Purpose of the test case is to check behavior of the DUT when PFCWD is enabled in FORWARD mode and egress port + is congested with PAUSE storm. DUT in this mode should forward the lossless packets irrespective of the pause + storm and not send any PAUSE frames towards IXIA transmitter. No effect on lossy traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + Returns: + N/A + + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': True} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 90, + 'BG_FLOW_AGGR_RATE_PERCENT': 10, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 1, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/One_Ingress_Egress_pfcwd_frwd_90_10_dist'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd_drop': False, + 'enable_pfcwd_fwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'verify_flows': False, + 'imix': False, + 'test_check': test_check} + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + logger.info('PFC-WD stats at the start of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut_list[0].hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut.hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=True, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + logger.info('PFC-WD stats at the end of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) + + for dut in duthosts: + check_fabric_counters(dut) + + finally: + for duthost in dut_list: + config_reload(sonic_host=duthost, config_source='config_db', safe_reload=True) + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_pfcwd_drop_over_subs_40_09(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + + """ + Purpose of the testcase is to check PFCWD behavior in DROP mode with over-subscription. + Each ingress is sending 49% of link capacity traffic and DUT is receiving PAUSE storm on egress link. + DUT should drop lossless packets. No drop for lossy traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + + Returns: + N/A + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 100, 'lossy': 0, 'speed_tol': 83, 'loss_expected': True, 'pfc': True} + + test_def = {} + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, + 'BG_FLOW_AGGR_RATE_PERCENT': 9, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 1, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Two_Ingress_Single_Egress_pfcwd_drop_40_9_dist'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd_drop': True, + 'enable_pfcwd_fwd': False, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'verify_flows': False, + 'imix': False, + 'test_check': test_check} + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + logger.info('PFC-WD stats at the start of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut_list[0].hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut.hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=True, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + logger.info('PFC-WD stats at the end of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) + + for dut in duthosts: + check_fabric_counters(dut) + + finally: + for duthost in dut_list: + config_reload(sonic_host=duthost, config_source='config_db', safe_reload=True) + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_pfcwd_frwd_over_subs_40_09(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + + """ + Purpose of testcase is to test behavior of DUT in PFCWD-FORWARD mode in oversubscription mode. + Each ingress is sending 49% of link capacity traffic and DUT is receiving PAUSE storm on egress link. + DUT should forward for both lossy and lossless traffic without generating PAUSE frames towards IXIA + transmitter. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + + Returns: + N/A + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 3, 'loss_expected': False, 'pfc': True} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, + 'BG_FLOW_AGGR_RATE_PERCENT': 9, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 1, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Two_Ingress_Single_Egress_pfcwd_frwd_40_9_dist'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd_drop': False, + 'enable_pfcwd_fwd': True, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'verify_flows': False, + 'imix': False, + 'test_check': test_check} + + # Selecting only one lossless priority for the test. + test_prio_list = random.sample(lossless_prio_list, 1) + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless priority:{} for the test'.format(test_prio_list)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + logger.info('PFC-WD stats at the start of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut_list[0].hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut.hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=True, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + logger.info('PFC-WD stats at the end of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) + for dut in duthosts: + check_fabric_counters(dut) + + finally: + for duthost in dut_list: + config_reload(sonic_host=duthost, config_source='config_db', safe_reload=True) + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_pfcwd_disable_pause_cngtn(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + + """ + Purpose of the test case is to test oversubscription with two ingresses and single ingress. + Traffic pattern has 18% lossless priority and 27% lossy priority traffic. + Total ingress link is sending only 45% link capacity and hence egress will not be congested. + No losses for both lossless and lossy priority traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + + Returns: + N/A + """ + + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + # pkt_size of 1024B will be used unless imix flag is set. + # With imix flag set, the traffic_generation.py uses IMIX profile. + pkt_size = 1024 + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 0, 'lossy': 0, 'speed_tol': 41, 'loss_expected': False, 'pfc': True} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, + 'BG_FLOW_AGGR_RATE_PERCENT': 60, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 1, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/Single_Ingress_Single_Egress_pause_cngstn_'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd_drop': False, + 'enable_pfcwd_fwd': False, + 'enable_credit_wd': False, + 'stats_interval': 60, + 'background_traffic': True, + 'verify_flows': False, + 'imix': False, + 'test_check': test_check} + # Selecting only one lossless priority for the test. + test_prio_list = random.sample(lossless_prio_list, 1) + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless priority:{} for the test'.format(test_prio_list)) + + snappi_extra_params = SnappiSysTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=True, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + for dut in duthosts: + check_fabric_counters(dut) + + finally: + for duthost in dut_list: + config_reload(sonic_host=duthost, config_source='config_db', safe_reload=True) From 5e97e7cd6d365897a6ef093c9f45514889f38e5d Mon Sep 17 00:00:00 2001 From: amitpawa Date: Wed, 9 Oct 2024 11:02:03 -0400 Subject: [PATCH 09/12] Snappi: Added over_subscribe port map for over-subscribed testcases --- tests/snappi_tests/multidut/systest/test_sys_pfcwd.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/snappi_tests/multidut/systest/test_sys_pfcwd.py b/tests/snappi_tests/multidut/systest/test_sys_pfcwd.py index 1a350506a42..73461506722 100644 --- a/tests/snappi_tests/multidut/systest/test_sys_pfcwd.py +++ b/tests/snappi_tests/multidut/systest/test_sys_pfcwd.py @@ -19,6 +19,7 @@ pytestmark = [pytest.mark.topology('multidut-tgen')] port_map = [[1, 100, 1, 100], [1, 400, 1, 400]] +over_subs_port_map = [[1, 100, 2, 100], [1, 400, 2, 400]] # Testplan: docs/testplan/PFC_Snappi_Additional_Testcases.md # This test-script covers testcase#10: PFCWD-enabled DROP mode test. @@ -364,7 +365,7 @@ def test_pfcwd_frwd_90_10(snappi_api, # noqa: F811 config_reload(sonic_host=duthost, config_source='config_db', safe_reload=True) -@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize('port_map', over_subs_port_map) @pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) def test_pfcwd_drop_over_subs_40_09(snappi_api, # noqa: F811 conn_graph_facts, # noqa: F811 @@ -536,7 +537,7 @@ def test_pfcwd_drop_over_subs_40_09(snappi_api, # noqa: F811 config_reload(sonic_host=duthost, config_source='config_db', safe_reload=True) -@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize('port_map', over_subs_port_map) @pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) def test_pfcwd_frwd_over_subs_40_09(snappi_api, # noqa: F811 conn_graph_facts, # noqa: F811 From a6adbdc8a4e50ccafd644017d8a51056130482ac Mon Sep 17 00:00:00 2001 From: amitpawa Date: Mon, 2 Dec 2024 12:19:26 -0500 Subject: [PATCH 10/12] Modified infra to effectively use existing code for new testcases --- .../snappi_tests/snappi_systest_params.py | 58 ------------------- 1 file changed, 58 deletions(-) delete mode 100644 tests/common/snappi_tests/snappi_systest_params.py diff --git a/tests/common/snappi_tests/snappi_systest_params.py b/tests/common/snappi_tests/snappi_systest_params.py deleted file mode 100644 index 4ce6c49a351..00000000000 --- a/tests/common/snappi_tests/snappi_systest_params.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -The SnappiTestParams module allows for modular pass through of test parameters for all Snappi based tests. -""" - -from tests.common.snappi_tests.common_helpers import packet_capture -from tests.common.snappi_tests.traffic_flow_config import TrafficFlowConfig -from tests.common.snappi_tests.multi_dut_params import MultiDUTParams - - -class SnappiSysTestParams(): - def __init__(self): - """ - Initialize the SnappiTestParams class - - Params: - headroom_test_params (array): 2 element array if the associated pfc pause quanta - results in no packet drop [pfc_delay, headroom_result] - pfc_pause_src_mac (str): PFC pause source MAC address ex. '00:00:00:fa:ce:01' - set_pfc_class_enable_vec (bool): PFC class enable vector setting - packet_capture_type (ENUM): packet capture type ex. packet_capture.IP_CAPTURE - packet_capture_file (str): packet capture file ex. 'capture.pcapng' - packet_capture_ports (list): packet capture ports on ixia chassis ex. ['Port 1', 'Port 2'] - is_snappi_ingress_port_cap (bool): whether or not the packet capture is on the tgen ingress port, if False, - then pcap is on the tgen egress port - base_flow_config (dict): base flow configuration - test_tx_frames (list): number of test frames transmitted for priorities to test ex. [2000, 3000] - for priorities 3 and 4 - multi_dut_params (MultiDUTParams obj): contains details of duthost objects, - multidut_ports and other parameters - test_iterations (int) : No of iterations in the test - for ex. priorities 3 and 4 - gen_background_traffic (bool): whether or not to generate background traffic (default: True) - poll_device_runtime (bool): whether or not to poll the device for stats when traffic is running - (default: False) - for priorities 3 and 4 - gen_background_traffic (bool): whether or not to generate background traffic (default: True) - ecn_params (dict): ECN parameters - Dict values: - kmin: minimum ECN marking threshold - kmax: maximum ECN marking threshold - pmax: maximum ECN marking probability - traffic_flow_config (TrafficFlowConfig obj): traffic flow configuration object - """ - self.headroom_test_params = None - self.pfc_pause_src_mac = None - self.set_pfc_class_enable_vec = True - self.packet_capture_type = packet_capture.NO_CAPTURE - self.packet_capture_file = None - self.packet_capture_ports = None - self.is_snappi_ingress_port_cap = True - self.base_flow_config = [] - self.test_tx_frames = 0 - self.multi_dut_params = MultiDUTParams() - self.test_iterations = 1 - self.gen_background_traffic = True - self.poll_device_runtime = True - self.ecn_params = None - self.traffic_flow_config = TrafficFlowConfig() From ce2518b2e9041483c9795a27c6e7a37585163509 Mon Sep 17 00:00:00 2001 From: amitpawa Date: Wed, 4 Dec 2024 17:35:09 -0500 Subject: [PATCH 11/12] Changed the names and paths of the testcases and helper files --- .../files/pfc_congestion_helper.py} | 87 +++---- .../test_pfc_no_congestion_throughput.py} | 30 +-- .../test_pfc_port_congestion.py} | 55 ++--- .../files/pfcwd_actions_helper.py} | 112 +++++---- .../test_pfcwd_actions.py} | 214 ++++++++++++++++-- 5 files changed, 343 insertions(+), 155 deletions(-) rename tests/snappi_tests/{multidut/systest/files/sys_multidut_helper.py => pfc/files/pfc_congestion_helper.py} (83%) rename tests/snappi_tests/{multidut/systest/test_sys_non_congestion.py => pfc/test_pfc_no_congestion_throughput.py} (97%) rename tests/snappi_tests/{multidut/systest/test_sys_over_subscription.py => pfc/test_pfc_port_congestion.py} (95%) rename tests/snappi_tests/{multidut/systest/files/pfcwd_multidut_helper.py => pfcwd/files/pfcwd_actions_helper.py} (77%) rename tests/snappi_tests/{multidut/systest/test_sys_pfcwd.py => pfcwd/test_pfcwd_actions.py} (81%) diff --git a/tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py b/tests/snappi_tests/pfc/files/pfc_congestion_helper.py similarity index 83% rename from tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py rename to tests/snappi_tests/pfc/files/pfc_congestion_helper.py index 2618b18ee49..1e1cd190c1d 100644 --- a/tests/snappi_tests/multidut/systest/files/sys_multidut_helper.py +++ b/tests/snappi_tests/pfc/files/pfc_congestion_helper.py @@ -12,11 +12,11 @@ traffic_flow_mode, calc_pfc_pause_flow_rate # noqa F401 from tests.common.snappi_tests.port import select_ports, select_tx_port # noqa F401 from tests.common.snappi_tests.snappi_helpers import wait_for_arp # noqa F401 -from tests.common.snappi_tests.traffic_generation import generate_sys_pause_flows, verify_pause_flow, \ - verify_basic_test_flow, verify_background_flow, verify_pause_frame_count_dut, verify_sys_egress_queue_count, \ - verify_in_flight_buffer_pkts, verify_unset_cev_pause_frame_count, run_sys_traffic, new_base_traffic_config, \ - generate_sys_test_flows, generate_sys_background_flows -from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams +from tests.common.snappi_tests.traffic_generation import generate_pause_flows, verify_pause_flow, \ + verify_basic_test_flow, verify_background_flow, verify_pause_frame_count_dut, verify_egress_queue_frame_count, \ + verify_in_flight_buffer_pkts, verify_unset_cev_pause_frame_count, run_traffic_and_collect_stats, \ + multi_base_traffic_config, generate_test_flows, generate_background_flows +from tests.common.snappi_tests.snappi_test_params import SnappiTestParams from tests.common.snappi_tests.read_pcap import validate_pfc_frame logger = logging.getLogger(__name__) @@ -82,7 +82,7 @@ def run_pfc_test(api, port_map = test_def['port_map'] if snappi_extra_params is None: - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() # Traffic flow: # tx_port (TGEN) --- ingress DUT --- egress DUT --- rx_port (TGEN) @@ -126,10 +126,10 @@ def run_pfc_test(api, # Generate base traffic config for i in range(port_map[2]): tx_port_id = i+1 - snappi_extra_params.base_flow_config.append(new_base_traffic_config(testbed_config=testbed_config, - port_config_list=port_config_list, - rx_port_id=rx_port_id, - tx_port_id=tx_port_id)) + snappi_extra_params.base_flow_config_list.append(multi_base_traffic_config(testbed_config=testbed_config, + port_config_list=port_config_list, + rx_port_id=rx_port_id, + tx_port_id=tx_port_id)) speed_str = testbed_config.layer1[0].speed speed_gbps = int(speed_str.split('_')[1]) @@ -153,10 +153,10 @@ def run_pfc_test(api, # Setup capture config if snappi_extra_params.is_snappi_ingress_port_cap: # packet capture is required on the ingress snappi port - snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["rx_port_name"]] + snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config_list["rx_port_name"]] else: # packet capture will be on the egress snappi port - snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["tx_port_name"]] + snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config_list["tx_port_name"]] snappi_extra_params.packet_capture_file = snappi_extra_params.packet_capture_type.value @@ -225,30 +225,30 @@ def run_pfc_test(api, # Generate test flow config based on number of ingress ports # Every ingress port will be used as index. Example - test flow stream 0 - for first ingress. for m in range(port_map[2]): - generate_sys_test_flows(testbed_config=testbed_config, - test_flow_prio_list=test_prio_list, - prio_dscp_map=prio_dscp_map, - snappi_extra_params=snappi_extra_params, - snap_index=m) + generate_test_flows(testbed_config=testbed_config, + test_flow_prio_list=test_prio_list, + prio_dscp_map=prio_dscp_map, + snappi_extra_params=snappi_extra_params, + flow_index=m) if (test_def['background_traffic']): for m in range(port_map[2]): if snappi_extra_params.gen_background_traffic: # Generate background flow config - generate_sys_background_flows(testbed_config=testbed_config, - bg_flow_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - snappi_extra_params=snappi_extra_params, - snap_index=m) + generate_background_flows(testbed_config=testbed_config, + bg_flow_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + snappi_extra_params=snappi_extra_params, + flow_index=m) # Generate pause storm config if (test_traffic_pause): for m in range(port_map[0]): - generate_sys_pause_flows(testbed_config=testbed_config, - pause_prio_list=pause_prio_list, - global_pause=global_pause, - snappi_extra_params=snappi_extra_params, - snap_index=m) + generate_pause_flows(testbed_config=testbed_config, + pause_prio_list=pause_prio_list, + global_pause=global_pause, + snappi_extra_params=snappi_extra_params, + snap_index=m) flows = testbed_config.flows @@ -267,18 +267,19 @@ def run_pfc_test(api, exp_dur_sec = DATA_FLOW_DURATION_SEC + data_flow_delay_sec """ Run traffic """ - tgen_flow_stats, switch_flow_stats, test_stats = run_sys_traffic(rx_duthost=ingress_duthost, - tx_duthost=egress_duthost, - api=api, - config=testbed_config, - data_flow_names=data_flow_names, - all_flow_names=all_flow_names, - exp_dur_sec=exp_dur_sec, - port_map=test_def['port_map'], - fname=fname, - stats_interval=test_def['stats_interval'], - imix=test_def['imix'], - snappi_extra_params=snappi_extra_params) + tgen_flow_stats, switch_flow_stats, test_stats = \ + run_traffic_and_collect_stats(rx_duthost=ingress_duthost, + tx_duthost=egress_duthost, + api=api, + config=testbed_config, + data_flow_names=data_flow_names, + all_flow_names=all_flow_names, + exp_dur_sec=exp_dur_sec, + port_map=test_def['port_map'], + fname=fname, + stats_interval=test_def['stats_interval'], + imix=test_def['imix'], + snappi_extra_params=snappi_extra_params) test_check = test_def['test_check'] if (not test_check['loss_expected']): @@ -364,10 +365,10 @@ def run_pfc_test(api, # Verify in flight TX lossless packets do not leave the DUT when traffic is expected # to be paused, or leave the DUT when the traffic is not expected to be paused - verify_sys_egress_queue_count(duthost=egress_duthost, - switch_flow_stats=switch_flow_stats, - test_traffic_pause=test_traffic_pause, - snappi_extra_params=snappi_extra_params) + verify_egress_queue_frame_count(duthost=egress_duthost, + switch_flow_stats=switch_flow_stats, + test_traffic_pause=test_traffic_pause, + snappi_extra_params=snappi_extra_params) if (test_traffic_pause and test_def['verify_flows']): # Verify in flight TX packets count relative to switch buffer size diff --git a/tests/snappi_tests/multidut/systest/test_sys_non_congestion.py b/tests/snappi_tests/pfc/test_pfc_no_congestion_throughput.py similarity index 97% rename from tests/snappi_tests/multidut/systest/test_sys_non_congestion.py rename to tests/snappi_tests/pfc/test_pfc_no_congestion_throughput.py index 81c46fc6aa8..90901ca5d03 100644 --- a/tests/snappi_tests/multidut/systest/test_sys_non_congestion.py +++ b/tests/snappi_tests/pfc/test_pfc_no_congestion_throughput.py @@ -3,12 +3,12 @@ from tests.common.helpers.assertions import pytest_require, pytest_assert # noqa: F401 from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts_multidut # noqa: F401 from tests.common.snappi_tests.snappi_fixtures import snappi_api_serv_ip, snappi_api_serv_port, \ - snappi_api, cleanup_config, get_snappi_ports_for_rdma, snappi_sys_base_config, \ + snappi_api, cleanup_config, get_snappi_ports_for_rdma, snappi_multi_base_config, \ get_snappi_ports, get_snappi_ports_multi_dut, clear_fabric_counters, check_fabric_counters # noqa: F401 from tests.common.snappi_tests.qos_fixtures import prio_dscp_map, lossless_prio_list, \ lossy_prio_list, all_prio_list # noqa: F401 -from tests.snappi_tests.multidut.systest.files.sys_multidut_helper import run_pfc_test -from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams +from tests.snappi_tests.pfc.files.pfc_congestion_helper import run_pfc_test +from tests.common.snappi_tests.snappi_test_params import SnappiTestParams from tests.snappi_tests.variables import MULTIDUT_PORT_INFO, MULTIDUT_TESTBED import logging @@ -97,9 +97,9 @@ def test_multiple_prio_diff_dist(snappi_api, # noqa: F811 snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, tx_port_count, rx_port_count, MULTIDUT_TESTBED) - testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, - snappi_ports, - snappi_api) + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) # Percentage drop expected for lossless and lossy traffic. # speed_tol is speed tolerance between egress link speed and actual speed. @@ -127,7 +127,7 @@ def test_multiple_prio_diff_dist(snappi_api, # noqa: F811 bg_prio_list = random.sample(lossy_prio_list, 3) logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] @@ -237,9 +237,9 @@ def test_multiple_prio_uni_dist(snappi_api, # noqa: F811 snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, tx_port_count, rx_port_count, MULTIDUT_TESTBED) - testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, - snappi_ports, - snappi_api) + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) # Percentage drop expected for lossless and lossy traffic. # speed_tol is speed tolerance between egress link speed and actual speed. @@ -268,7 +268,7 @@ def test_multiple_prio_uni_dist(snappi_api, # noqa: F811 bg_prio_list = random.sample(lossy_prio_list, 3) logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] @@ -377,9 +377,9 @@ def test_single_lossless_prio(snappi_api, # noqa: F811 snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, tx_port_count, rx_port_count, MULTIDUT_TESTBED) - testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, - snappi_ports, - snappi_api) + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) # Percentage drop expected for lossless and lossy traffic. # speed_tol is speed tolerance between egress link speed and actual speed. @@ -410,7 +410,7 @@ def test_single_lossless_prio(snappi_api, # noqa: F811 bg_prio_list = random.sample(lossy_prio_list, 3) logger.info('Selected lossless priority:{} for the test'.format(test_prio_list)) - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] diff --git a/tests/snappi_tests/multidut/systest/test_sys_over_subscription.py b/tests/snappi_tests/pfc/test_pfc_port_congestion.py similarity index 95% rename from tests/snappi_tests/multidut/systest/test_sys_over_subscription.py rename to tests/snappi_tests/pfc/test_pfc_port_congestion.py index 05f3b89133f..ccb40307e06 100644 --- a/tests/snappi_tests/multidut/systest/test_sys_over_subscription.py +++ b/tests/snappi_tests/pfc/test_pfc_port_congestion.py @@ -3,20 +3,21 @@ from tests.common.helpers.assertions import pytest_require, pytest_assert # noqa: F401 from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts_multidut # noqa: F401 from tests.common.snappi_tests.snappi_fixtures import snappi_api_serv_ip, snappi_api_serv_port, \ - snappi_api, snappi_sys_base_config, cleanup_config, get_snappi_ports_for_rdma, \ + snappi_api, snappi_multi_base_config, cleanup_config, get_snappi_ports_for_rdma, \ get_snappi_ports, get_snappi_ports_multi_dut, clear_fabric_counters, check_fabric_counters # noqa: F401 from tests.common.snappi_tests.qos_fixtures import prio_dscp_map, lossless_prio_list, \ lossy_prio_list, all_prio_list # noqa: F401 from tests.snappi_tests.variables import MULTIDUT_PORT_INFO, MULTIDUT_TESTBED -from tests.snappi_tests.multidut.systest.files.sys_multidut_helper import run_pfc_test -from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams +from tests.snappi_tests.pfc.files.pfc_congestion_helper import run_pfc_test +from tests.common.snappi_tests.snappi_test_params import SnappiTestParams import logging logger = logging.getLogger(__name__) pytestmark = [pytest.mark.topology('multidut-tgen')] -port_map = [[1, 100, 2, 100], [1, 400, 2, 400]] +#port_map = [[1, 100, 2, 100], [1, 400, 2, 400]] +port_map = [[1, 400, 2, 400]] # Testplan: docs/testplan/PFC_Snappi_Additional_Testcases.md # This test-script covers following testcases: @@ -95,9 +96,9 @@ def test_multiple_prio_diff_dist(snappi_api, # noqa: F811 snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, tx_port_count, rx_port_count, MULTIDUT_TESTBED) - testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, - snappi_ports, - snappi_api) + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) # Percentage drop expected for lossless and lossy traffic. # speed_tol is speed tolerance between egress link speed and actual speed. @@ -125,7 +126,7 @@ def test_multiple_prio_diff_dist(snappi_api, # noqa: F811 bg_prio_list = random.sample(lossy_prio_list, 3) logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] @@ -229,14 +230,14 @@ def test_multiple_prio_uni_dist(snappi_api, # noqa: F811 snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, tx_port_count, rx_port_count, MULTIDUT_TESTBED) - testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, - snappi_ports, - snappi_api) + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) # Percentage drop expected for lossless and lossy traffic. # speed_tol is speed tolerance between egress link speed and actual speed. # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 0, 'lossy': 51, 'speed_tol': 51, 'loss_expected': True, 'pfc': True} + test_check = {'lossless': 0, 'lossy': 51, 'speed_tol': 3, 'loss_expected': True, 'pfc': True} test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, 'BG_FLOW_AGGR_RATE_PERCENT': 60, @@ -260,7 +261,7 @@ def test_multiple_prio_uni_dist(snappi_api, # noqa: F811 bg_prio_list = random.sample(lossy_prio_list, 3) logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] @@ -297,7 +298,7 @@ def test_multiple_prio_uni_dist(snappi_api, # noqa: F811 @pytest.mark.parametrize('port_map', port_map) @pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) -def test_multiple_prio_uni_dist_full(snappi_api, # noqa: F811 +def test_multiple_prio_equal_dist(snappi_api, # noqa: F811 conn_graph_facts, # noqa: F811 fanout_graph_facts_multidut, # noqa: F811 duthosts, @@ -366,22 +367,22 @@ def test_multiple_prio_uni_dist_full(snappi_api, # noqa: F811 snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, tx_port_count, rx_port_count, MULTIDUT_TESTBED) - testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, - snappi_ports, - snappi_api) + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) # Percentage drop expected for lossless and lossy traffic. # speed_tol is speed tolerance between egress link speed and actual speed. # loss_expected to check losses on DUT and TGEN. - test_check = {'lossless': 0, 'lossy': 51, 'speed_tol': 51, 'loss_expected': True, 'pfc': True} + test_check = {'lossless': 0, 'lossy': 20, 'speed_tol': 3, 'loss_expected': True, 'pfc': True} - test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, - 'BG_FLOW_AGGR_RATE_PERCENT': 60, + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 30, + 'BG_FLOW_AGGR_RATE_PERCENT': 30, 'data_flow_pkt_size': pkt_size, 'DATA_FLOW_DURATION_SEC': 300, 'data_flow_delay_sec': 0, 'SNAPPI_POLL_DELAY_SEC': 60, - 'test_type': '/tmp/Two_Ingress_Single_Egress_uni_dist_full'+str(port_map[1])+'Gbps', + 'test_type': '/tmp/Two_Ingress_Single_Egress_equal_dist'+str(port_map[1])+'Gbps', 'line_card_choice': testbed_subtype, 'port_map': port_map, 'enable_pfcwd': True, @@ -394,10 +395,10 @@ def test_multiple_prio_uni_dist_full(snappi_api, # noqa: F811 test_prio_list = lossless_prio_list pause_prio_list = test_prio_list - bg_prio_list = random.sample(lossy_prio_list, 3) + bg_prio_list = random.sample(lossy_prio_list, 2) logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] @@ -504,9 +505,9 @@ def test_multiple_prio_non_cngtn(snappi_api, # noqa: F811 snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, tx_port_count, rx_port_count, MULTIDUT_TESTBED) - testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, - snappi_ports, - snappi_api) + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) # Percentage drop expected for lossless and lossy traffic. # speed_tol is speed tolerance between egress link speed and actual speed. @@ -535,7 +536,7 @@ def test_multiple_prio_non_cngtn(snappi_api, # noqa: F811 bg_prio_list = random.sample(lossy_prio_list, 3) logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] diff --git a/tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py b/tests/snappi_tests/pfcwd/files/pfcwd_actions_helper.py similarity index 77% rename from tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py rename to tests/snappi_tests/pfcwd/files/pfcwd_actions_helper.py index 9dbdd06e2ec..1c1e7a44b3e 100644 --- a/tests/snappi_tests/multidut/systest/files/pfcwd_multidut_helper.py +++ b/tests/snappi_tests/pfcwd/files/pfcwd_actions_helper.py @@ -14,9 +14,9 @@ from tests.common.snappi_tests.snappi_helpers import wait_for_arp # noqa F401 from tests.common.snappi_tests.traffic_generation import verify_pause_flow, \ verify_basic_test_flow, verify_background_flow, verify_pause_frame_count_dut, \ - run_sys_traffic, new_base_traffic_config, \ - generate_sys_test_flows, generate_sys_background_flows, generate_sys_pause_flows -from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams + run_traffic_and_collect_stats, multi_base_traffic_config, verify_egress_queue_frame_count, \ + generate_test_flows, generate_background_flows, generate_pause_flows +from tests.common.snappi_tests.snappi_test_params import SnappiTestParams logger = logging.getLogger(__name__) @@ -62,7 +62,7 @@ def run_pfc_test(api, prio_dscp_map (dict): Priority vs. DSCP map (key = priority). test_traffic_pause (bool): if test flows are expected to be paused test_def['enable_pause'] (bool) : if test expects no pause flow traffic. - snappi_extra_params (SnappiSysTestParams obj): additional parameters for Snappi traffic + snappi_extra_params (SnappiTestParams obj): additional parameters for Snappi traffic Returns: N/A @@ -83,7 +83,7 @@ def run_pfc_test(api, port_map = test_def['port_map'] if snappi_extra_params is None: - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() # Traffic flow: # tx_port (TGEN) --- ingress DUT --- egress DUT --- rx_port (TGEN) @@ -127,18 +127,24 @@ def run_pfc_test(api, for i in range(port_map[0]): rx_port_id = i tx_port_id = 2 - snappi_extra_params.base_flow_config.append(new_base_traffic_config(testbed_config=testbed_config, - port_config_list=port_config_list, - rx_port_id=rx_port_id, - tx_port_id=tx_port_id)) + snappi_extra_params.base_flow_config_list.append( + multi_base_traffic_config(testbed_config=testbed_config, + port_config_list=port_config_list, + rx_port_id=rx_port_id, + tx_port_id=tx_port_id + ) + ) else: rx_port_id = 0 for i in range(port_map[2]): tx_port_id = i+1 - snappi_extra_params.base_flow_config.append(new_base_traffic_config(testbed_config=testbed_config, - port_config_list=port_config_list, - rx_port_id=rx_port_id, - tx_port_id=tx_port_id)) + snappi_extra_params.base_flow_config_list.append( + multi_base_traffic_config(testbed_config=testbed_config, + port_config_list=port_config_list, + rx_port_id=rx_port_id, + tx_port_id=tx_port_id + ) + ) speed_str = testbed_config.layer1[0].speed speed_gbps = int(speed_str.split('_')[1]) @@ -162,10 +168,10 @@ def run_pfc_test(api, # Setup capture config if snappi_extra_params.is_snappi_ingress_port_cap: # packet capture is required on the ingress snappi port - snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["rx_port_name"]] + snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config_list["rx_port_name"]] else: # packet capture will be on the egress snappi port - snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config["tx_port_name"]] + snappi_extra_params.packet_capture_ports = [snappi_extra_params.base_flow_config_list["tx_port_name"]] snappi_extra_params.packet_capture_file = snappi_extra_params.packet_capture_type.value @@ -236,30 +242,30 @@ def run_pfc_test(api, # Generate test flow config for m in range(port_map[2]): - generate_sys_test_flows(testbed_config=testbed_config, - test_flow_prio_list=test_prio_list, - prio_dscp_map=prio_dscp_map, - snappi_extra_params=snappi_extra_params, - snap_index=m) + generate_test_flows(testbed_config=testbed_config, + test_flow_prio_list=test_prio_list, + prio_dscp_map=prio_dscp_map, + snappi_extra_params=snappi_extra_params, + flow_index=m) if (test_def['background_traffic']): for m in range(port_map[2]): if snappi_extra_params.gen_background_traffic: # Generate background flow config - generate_sys_background_flows(testbed_config=testbed_config, - bg_flow_prio_list=bg_prio_list, - prio_dscp_map=prio_dscp_map, - snappi_extra_params=snappi_extra_params, - snap_index=m) + generate_background_flows(testbed_config=testbed_config, + bg_flow_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + snappi_extra_params=snappi_extra_params, + flow_index=m) # Generate pause storm config if (test_traffic_pause): for m in range(port_map[0]): - generate_sys_pause_flows(testbed_config=testbed_config, - pause_prio_list=pause_prio_list, - global_pause=global_pause, - snappi_extra_params=snappi_extra_params, - snap_index=m) + generate_pause_flows(testbed_config=testbed_config, + pause_prio_list=pause_prio_list, + global_pause=global_pause, + snappi_extra_params=snappi_extra_params, + flow_index=m) flows = testbed_config.flows @@ -278,34 +284,38 @@ def run_pfc_test(api, exp_dur_sec = DATA_FLOW_DURATION_SEC + data_flow_delay_sec """ Run traffic """ - tgen_flow_stats, switch_flow_stats, test_stats = run_sys_traffic(rx_duthost=ingress_duthost, - tx_duthost=egress_duthost, - api=api, - config=testbed_config, - data_flow_names=data_flow_names, - all_flow_names=all_flow_names, - exp_dur_sec=exp_dur_sec, - port_map=test_def['port_map'], - fname=fname, - stats_interval=test_def['stats_interval'], - imix=test_def['imix'], - snappi_extra_params=snappi_extra_params) + tgen_flow_stats, switch_flow_stats, test_stats = \ + run_traffic_and_collect_stats(rx_duthost=ingress_duthost, + tx_duthost=egress_duthost, + api=api, + config=testbed_config, + data_flow_names=data_flow_names, + all_flow_names=all_flow_names, + exp_dur_sec=exp_dur_sec, + port_map=test_def['port_map'], + fname=fname, + stats_interval=test_def['stats_interval'], + imix=test_def['imix'], + snappi_extra_params=snappi_extra_params) test_check = test_def['test_check'] if (not test_check['loss_expected']): # Check for loss packets on IXIA and DUT. - pytest_assert(test_stats['tgen_loss_pkts'] == 0, 'Loss seen on TGEN') + if (test_def['enable_pfcwd_drop'] or test_def['enable_credit_wd']): + pytest_assert(test_stats['tgen_loss_pkts'] == 0, 'Loss seen on TGEN') pytest_assert(test_stats['dut_loss_pkts'] == 0, 'Loss seen on DUT') # Check for Tx and Rx packets on IXIA for lossless and lossy streams. - pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['tgen_lossless_tx_pkts'], - 'Losses observed in lossless traffic streams') + if (test_def['enable_pfcwd_drop'] or test_def['enable_credit_wd']): + pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['tgen_lossless_tx_pkts'], + 'Losses observed in lossless traffic streams') pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['tgen_lossy_tx_pkts'], 'Losses observed in lossy traffic streams') # Check for Rx packets between IXIA and DUT for lossy and lossless streams. - pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['dut_lossless_pkts'], - 'Losses observed in lossless traffic streams on DUT Tx and IXIA Rx') + if (test_def['enable_pfcwd_drop'] or test_def['enable_credit_wd']): + pytest_assert(test_stats['tgen_lossless_rx_pkts'] == test_stats['dut_lossless_pkts'], + 'Losses observed in lossless traffic streams on DUT Tx and IXIA Rx') pytest_assert(test_stats['tgen_lossy_rx_pkts'] == test_stats['dut_lossy_pkts'], 'Losses observed in lossy traffic streams on DUT Tx and IXIA Rx') else: @@ -367,3 +377,11 @@ def run_pfc_test(api, test_traffic_pause=test_traffic_pause, global_pause=global_pause, snappi_extra_params=snappi_extra_params) + + # Verify in flight TX lossless packets do not leave the DUT when traffic is expected + # to be paused, or leave the DUT when the traffic is not expected to be paused + if (test_traffic_pause and test_def['enable_pfcwd_drop']): + verify_egress_queue_frame_count(duthost=egress_duthost, + switch_flow_stats=switch_flow_stats, + test_traffic_pause=test_traffic_pause, + snappi_extra_params=snappi_extra_params) diff --git a/tests/snappi_tests/multidut/systest/test_sys_pfcwd.py b/tests/snappi_tests/pfcwd/test_pfcwd_actions.py similarity index 81% rename from tests/snappi_tests/multidut/systest/test_sys_pfcwd.py rename to tests/snappi_tests/pfcwd/test_pfcwd_actions.py index 73461506722..49068f75d42 100644 --- a/tests/snappi_tests/multidut/systest/test_sys_pfcwd.py +++ b/tests/snappi_tests/pfcwd/test_pfcwd_actions.py @@ -4,14 +4,14 @@ from tests.common.helpers.assertions import pytest_require, pytest_assert # noqa: F401 from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts_multidut # noqa: F401 from tests.common.snappi_tests.snappi_fixtures import snappi_api_serv_ip, snappi_api_serv_port, \ - snappi_api, snappi_sys_base_config, cleanup_config, get_snappi_ports_for_rdma, \ + snappi_api, snappi_multi_base_config, cleanup_config, get_snappi_ports_for_rdma, \ get_snappi_ports, get_snappi_ports_multi_dut, clear_fabric_counters, check_fabric_counters # noqa: F401 from tests.common.snappi_tests.qos_fixtures import prio_dscp_map, lossless_prio_list, \ lossy_prio_list, all_prio_list # noqa: F401 from tests.common.snappi_tests.common_helpers import get_pfcwd_stats -from tests.snappi_tests.multidut.systest.files.pfcwd_multidut_helper import run_pfc_test +from tests.snappi_tests.pfcwd.files.pfcwd_actions_helper import run_pfc_test from tests.common.config_reload import config_reload -from tests.common.snappi_tests.snappi_systest_params import SnappiSysTestParams +from tests.common.snappi_tests.snappi_test_params import SnappiTestParams from tests.snappi_tests.variables import MULTIDUT_PORT_INFO, MULTIDUT_TESTBED logger = logging.getLogger(__name__) @@ -93,9 +93,9 @@ def test_pfcwd_drop_90_10(snappi_api, # noqa: F811 snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, tx_port_count, rx_port_count, MULTIDUT_TESTBED) - testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, - snappi_ports, - snappi_api) + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) # Percentage drop expected for lossless and lossy traffic. # speed_tol is speed tolerance between egress link speed and actual speed. @@ -125,7 +125,175 @@ def test_pfcwd_drop_90_10(snappi_api, # noqa: F811 bg_prio_list = random.sample(lossy_prio_list, 3) logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() + snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] + snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] + + snappi_extra_params.multi_dut_params.multi_dut_ports = snappi_ports + + if (snappi_ports[0]['peer_device'] == snappi_ports[-1]['peer_device']): + dut_list = [snappi_ports[0]['duthost']] + else: + dut_list = [snappi_ports[0]['duthost'], snappi_ports[-1]['duthost']] + + for dut in duthosts: + clear_fabric_counters(dut) + + logger.info('PFC-WD stats at the start of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut_list[0].hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:{}'.format(pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + logger.info('PFCWD stats for dut:{}, port:{},prio:{}'. + format(dut.hostname, port['peer_port'], prio)) + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats::{}'.format(pfcwd_stats)) + + try: + run_pfc_test(api=snappi_api, + testbed_config=testbed_config, + port_config_list=port_config_list, + conn_data=conn_graph_facts, + fanout_data=fanout_graph_facts_multidut, + global_pause=False, + pause_prio_list=pause_prio_list, + test_prio_list=test_prio_list, + bg_prio_list=bg_prio_list, + prio_dscp_map=prio_dscp_map, + test_traffic_pause=True, + test_def=test_def, + snappi_extra_params=snappi_extra_params) + + logger.info('PFC-WD stats at the end of the test:') + for prio in test_prio_list: + for port in snappi_ports: + if len(dut_list) == 1: + if dut_list[0].hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut_list[0], port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut_list[0].hostname, port['peer_port'], prio, pfcwd_stats)) + else: + for dut in dut_list: + if dut.hostname == port['peer_device']: + pfcwd_stats = get_pfcwd_stats(dut, port['peer_port'], prio) + logger.info('PFCWD Stats:for dut:{}, port:{},prio:{}, stats::{}'. + format(dut.hostname, port['peer_port'], prio, pfcwd_stats)) + + for dut in duthosts: + check_fabric_counters(dut) + + finally: + for duthost in dut_list: + config_reload(sonic_host=duthost, config_source='config_db', safe_reload=True) + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) +def test_pfcwd_drop_uni(snappi_api, # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 + """ + Purpose of the test case is to enable PFCWD in drop mode and send 90% lossless traffic and 10% + lossy traffic and check the behavior. DUT is receiving pause storm on the egress port. DUT should + drop the lossless packets without generating any pause towards IXIA transmitter. No loss for lossy traffic. + + Args: + snappi_api (pytest fixture): SNAPPI session + conn_graph_facts (pytest fixture): connection graph + fanout_graph_facts_multidut_multidut (pytest fixture): fanout graph + duthosts (pytest fixture): list of DUTs + prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority). + lossless_prio_list(list): list of lossless priorities + lossy_prio_list(list): list of lossy priorities. + tbinfo(key): element to identify testbed info name. + get_snappi_ports(pytest fixture): returns list of ports based on linecards selected. + port_map(list): list for port-speed combination. + multidut_port_info : Line card classification along with ports selected as Rx and Tx port. + + Returns: + N/A + """ + + pkt_size = 1024 + # port_map is defined as port-speed combination. + # first two parameters are count of egress links and its speed. + # last two parameters are count of ingress links and its speed. + + for testbed_subtype, rdma_ports in multidut_port_info.items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + tmp_snappi_port_list = get_snappi_ports + snappi_port_list = [] + for item in tmp_snappi_port_list: + if (int(item['speed']) == (port_map[1] * 1000)): + snappi_port_list.append(item) + pytest_assert(MULTIDUT_TESTBED == tbinfo['conf-name'], + "The testbed name from testbed file doesn't match with MULTIDUT_TESTBED in variables.py ") + pytest_assert(len(snappi_port_list) >= tx_port_count + rx_port_count, + "Need Minimum of 2 ports defined in ansible/files/*links.csv file") + + pytest_assert(len(rdma_ports['tx_ports']) >= tx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Tx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + + pytest_assert(len(rdma_ports['rx_ports']) >= rx_port_count, + 'MULTIDUT_PORT_INFO doesn\'t have the required Rx ports defined for \ + testbed {}, subtype {} in variables.py'. + format(MULTIDUT_TESTBED, testbed_subtype)) + logger.info('Running test for testbed subtype: {}'.format(testbed_subtype)) + + snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, + tx_port_count, rx_port_count, MULTIDUT_TESTBED) + + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) + + # Percentage drop expected for lossless and lossy traffic. + # speed_tol is speed tolerance between egress link speed and actual speed. + # loss_expected to check losses on DUT and TGEN. + test_check = {'lossless': 100, 'lossy': 0, 'speed_tol': 50, 'loss_expected': True, 'pfc': True} + + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 40, + 'BG_FLOW_AGGR_RATE_PERCENT': 60, + 'data_flow_pkt_size': pkt_size, + 'DATA_FLOW_DURATION_SEC': 300, + 'data_flow_delay_sec': 1, + 'SNAPPI_POLL_DELAY_SEC': 60, + 'test_type': '/tmp/One_Ingress_Egress_pfcwd_drop_uni_dist'+str(port_map[1])+'Gbps', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd_drop': True, + 'enable_pfcwd_fwd': False, + 'enable_credit_wd': True, + 'stats_interval': 60, + 'background_traffic': True, + 'verify_flows': False, + 'imix': False, + 'test_check': test_check} + + test_prio_list = lossless_prio_list + pause_prio_list = test_prio_list + bg_prio_list = random.sample(lossy_prio_list, 3) + logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) + + snappi_extra_params = SnappiTestParams() snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] @@ -265,9 +433,9 @@ def test_pfcwd_frwd_90_10(snappi_api, # noqa: F811 snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, tx_port_count, rx_port_count, MULTIDUT_TESTBED) - testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, - snappi_ports, - snappi_api) + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) # Percentage drop expected for lossless and lossy traffic. # speed_tol is speed tolerance between egress link speed and actual speed. @@ -297,7 +465,7 @@ def test_pfcwd_frwd_90_10(snappi_api, # noqa: F811 bg_prio_list = random.sample(lossy_prio_list, 3) logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] @@ -436,9 +604,9 @@ def test_pfcwd_drop_over_subs_40_09(snappi_api, # noqa: F811 snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, tx_port_count, rx_port_count, MULTIDUT_TESTBED) - testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, - snappi_ports, - snappi_api) + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) # Percentage drop expected for lossless and lossy traffic. # speed_tol is speed tolerance between egress link speed and actual speed. @@ -469,7 +637,7 @@ def test_pfcwd_drop_over_subs_40_09(snappi_api, # noqa: F811 bg_prio_list = random.sample(lossy_prio_list, 3) logger.info('Selected lossless :{} and lossy priorities:{} for the test'.format(test_prio_list, bg_prio_list)) - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] @@ -609,9 +777,9 @@ def test_pfcwd_frwd_over_subs_40_09(snappi_api, # noqa: F811 snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, tx_port_count, rx_port_count, MULTIDUT_TESTBED) - testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, - snappi_ports, - snappi_api) + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) # Percentage drop expected for lossless and lossy traffic. # speed_tol is speed tolerance between egress link speed and actual speed. @@ -642,7 +810,7 @@ def test_pfcwd_frwd_over_subs_40_09(snappi_api, # noqa: F811 bg_prio_list = random.sample(lossy_prio_list, 3) logger.info('Selected lossless priority:{} for the test'.format(test_prio_list)) - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] @@ -781,9 +949,9 @@ def test_pfcwd_disable_pause_cngtn(snappi_api, # noqa: F811 snappi_ports = get_snappi_ports_for_rdma(snappi_port_list, rdma_ports, tx_port_count, rx_port_count, MULTIDUT_TESTBED) - testbed_config, port_config_list, snappi_ports = snappi_sys_base_config(duthosts, - snappi_ports, - snappi_api) + testbed_config, port_config_list, snappi_ports = snappi_multi_base_config(duthosts, + snappi_ports, + snappi_api) # Percentage drop expected for lossless and lossy traffic. # speed_tol is speed tolerance between egress link speed and actual speed. @@ -813,7 +981,7 @@ def test_pfcwd_disable_pause_cngtn(snappi_api, # noqa: F811 bg_prio_list = random.sample(lossy_prio_list, 3) logger.info('Selected lossless priority:{} for the test'.format(test_prio_list)) - snappi_extra_params = SnappiSysTestParams() + snappi_extra_params = SnappiTestParams() snappi_extra_params.multi_dut_params.duthost1 = snappi_ports[0]['duthost'] snappi_extra_params.multi_dut_params.duthost2 = snappi_ports[-1]['duthost'] From 5d330735cf43e3806667239088d4b53acbf29a8f Mon Sep 17 00:00:00 2001 From: amitpawa Date: Wed, 4 Dec 2024 18:21:08 -0500 Subject: [PATCH 12/12] Fixed flake8 errors for test_pfc_port_congestion.py --- .../pfc/test_pfc_port_congestion.py | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/tests/snappi_tests/pfc/test_pfc_port_congestion.py b/tests/snappi_tests/pfc/test_pfc_port_congestion.py index ccb40307e06..c397464a7f6 100644 --- a/tests/snappi_tests/pfc/test_pfc_port_congestion.py +++ b/tests/snappi_tests/pfc/test_pfc_port_congestion.py @@ -16,8 +16,7 @@ pytestmark = [pytest.mark.topology('multidut-tgen')] -#port_map = [[1, 100, 2, 100], [1, 400, 2, 400]] -port_map = [[1, 400, 2, 400]] +port_map = [[1, 100, 2, 100], [1, 400, 2, 400]] # Testplan: docs/testplan/PFC_Snappi_Additional_Testcases.md # This test-script covers following testcases: @@ -299,16 +298,16 @@ def test_multiple_prio_uni_dist(snappi_api, # noqa: F811 @pytest.mark.parametrize('port_map', port_map) @pytest.mark.parametrize("multidut_port_info", MULTIDUT_PORT_INFO[MULTIDUT_TESTBED]) def test_multiple_prio_equal_dist(snappi_api, # noqa: F811 - conn_graph_facts, # noqa: F811 - fanout_graph_facts_multidut, # noqa: F811 - duthosts, - prio_dscp_map, # noqa: F811 - lossless_prio_list, # noqa: F811 - lossy_prio_list, # noqa: F811 - tbinfo, - get_snappi_ports, # noqa: F811 - port_map, - multidut_port_info): # noqa: F811 + conn_graph_facts, # noqa: F811 + fanout_graph_facts_multidut, # noqa: F811 + duthosts, + prio_dscp_map, # noqa: F811 + lossless_prio_list, # noqa: F811 + lossy_prio_list, # noqa: F811 + tbinfo, + get_snappi_ports, # noqa: F811 + port_map, + multidut_port_info): # noqa: F811 """ Purpose of the test case is to test oversubscription with two ingresses and single ingress.