diff --git a/tests/common/snappi_tests/common_helpers.py b/tests/common/snappi_tests/common_helpers.py index 55ce452b6df..f849e9882fb 100644 --- a/tests/common/snappi_tests/common_helpers.py +++ b/tests/common/snappi_tests/common_helpers.py @@ -1183,7 +1183,7 @@ def get_interface_stats(duthost, port): def get_queue_count_all_prio(duthost, port): """ - Get the egress queue count in packets and bytes for a given port and priority from SONiC CLI. + Get the egress queue count in packets and bytes for a given port and all priorities. This is the equivalent of the "show queue counters" command. Args: duthost (Ansible host instance): device under test diff --git a/tests/snappi_tests/pfc/files/mixed_speed_multidut_helper.py b/tests/snappi_tests/pfc/files/mixed_speed_multidut_helper.py new file mode 100644 index 00000000000..be69f49aea6 --- /dev/null +++ b/tests/snappi_tests/pfc/files/mixed_speed_multidut_helper.py @@ -0,0 +1,383 @@ +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_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__) + +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 = SnappiTestParams() + + # 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']): + 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_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]) + + 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_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_list["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_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_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_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 + + 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_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') + 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*100, lossy_drop*100)) + if test_def['enable_pfcwd']: + 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_traffic_pause): + pytest_assert(test_stats['lossless_rx_pfc'] > 0, 'Error:No Rx PFCs to DUT from IXIA') + if ((test_stats['lossless_rx_pfc'] != 0) and (not test_def['enable_pfcwd'])): + 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 + # Only true if pfcwd is disabled, else packets will dropped. + 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 + 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/pfc/test_pfc_mixed_speed.py b/tests/snappi_tests/pfc/test_pfc_mixed_speed.py new file mode 100644 index 00000000000..d67e01edab4 --- /dev/null +++ b/tests/snappi_tests/pfc/test_pfc_mixed_speed.py @@ -0,0 +1,424 @@ +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_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.variables import MIXED_SPEED_PORT_INFO, MULTIDUT_TESTBED +from tests.snappi_tests.pfc.files.mixed_speed_multidut_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, 1, 400]] +# Testplan: docs/testplan/PFC_Snappi_Additional_Testcases.md +# This test-script covers testcase#03: DETECT CONGESTION WITH MISMATCHED INGRESS AND EGRESS + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MIXED_SPEED_PORT_INFO[MULTIDUT_TESTBED]) +def test_mixed_speed_diff_dist_over(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 + + """ + Majority traffic is lossless priority traffic. + DUT responds to congestion on ingress side by sending PFCs to IXIA transmitter. + IXIA transmitter slows down lossless traffic. + No Lossy traffic is dropped. + Lossy traffic makes through without any drop. Lossless traffic is adjusted. + Total egress link speed is 100Gbps. + + 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 MIXED_SPEED_PORT_INFO[MULTIDUT_TESTBED].items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + snappi_port_list = get_snappi_ports + 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': 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/Single_400Gbps_Ingress_Single_100Gbps_Egress_diff_dist_', + '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 = 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) + + 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) + + # Check the fabric counter for the line-cards. + 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", MIXED_SPEED_PORT_INFO[MULTIDUT_TESTBED]) +def test_mixed_speed_uni_dist_over(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 + + """ + Traffic is sent to IXIA receiver in equal amount. + DUT responds to congestion on ingress side by sending PFCs to IXIA transmitter. + IXIA transmitter slows down lossless traffic. + Lossy traffic is dropped. + Equal amount of lossless and lossy priority traffic is sent to IXIA receiver. + Total egress link speed is 100Gbps. + + 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 MIXED_SPEED_PORT_INFO[MULTIDUT_TESTBED].items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + snappi_port_list = get_snappi_ports + 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': 0, 'lossy': 77, 'speed_tol': 3, '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/Single_400Gbps_Ingress_Single_100Gbps_Egress_uni_dist_', + '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 = 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) + + 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", MIXED_SPEED_PORT_INFO[MULTIDUT_TESTBED]) +def test_mixed_speed_no_congestion(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 + + """ + Test to have mixed speed ingress and egress without oversubscribing the egress. + Since the total ingress traffic on 400Gbps is less than 100Gbps, + there should be no congestion experienced by DUT. + No packet drops experienced by the DUT. + + 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. + + + + """ + + # 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 MIXED_SPEED_PORT_INFO[MULTIDUT_TESTBED].items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + snappi_port_list = get_snappi_ports + 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': 0, 'lossy': 0, 'speed_tol': 10, 'loss_expected': False, 'pfc': False} + test_def = {'TEST_FLOW_AGGR_RATE_PERCENT': 14, + 'BG_FLOW_AGGR_RATE_PERCENT': 9, + '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_400Gbps_Ingress_Single_100Gbps_Egress_no_cong_', + '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 = 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) + + 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) diff --git a/tests/snappi_tests/pfcwd/test_pfcwd_mixed_speed.py b/tests/snappi_tests/pfcwd/test_pfcwd_mixed_speed.py new file mode 100644 index 00000000000..5e28a51c37f --- /dev/null +++ b/tests/snappi_tests/pfcwd/test_pfcwd_mixed_speed.py @@ -0,0 +1,291 @@ +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_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.variables import MIXED_SPEED_PORT_INFO, MULTIDUT_TESTBED +from tests.snappi_tests.pfc.files.mixed_speed_multidut_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, 1, 400]] +# Testplan: docs/testplan/PFC_Snappi_Additional_Testcases.md +# This test-script covers testcase#03: DETECT CONGESTION WITH MISMATCHED INGRESS AND EGRESS + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MIXED_SPEED_PORT_INFO[MULTIDUT_TESTBED]) +def test_mixed_speed_pfcwd_enable(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 + + """ + Test to oversubscribe the 100Gbps egress link and have PFCWD enabled. + Sending PAUSE frames to egress link for the lossless traffic. + In response to congestion due to PFC storm, DUT drops lossless traffic on egress side. + On ingress side, DUT sends PFCs to slow down IXIA transmitter. + Lossy traffic should be dropped. + DUT allows equal amount of traffic (lossless and lossy priorities) to the egress. + Egress traffic is around 60Gbps of lossy traffic only. + + 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 MIXED_SPEED_PORT_INFO[MULTIDUT_TESTBED].items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + snappi_port_list = get_snappi_ports + 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': 75, 'speed_tol': 40, '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/Single_400Gbps_Ingress_Single_100Gbps_Egress_pause_pfcwd_enable_', + '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 = 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) + + 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: + cleanup_config(dut_list, snappi_ports) + + +@pytest.mark.parametrize('port_map', port_map) +@pytest.mark.parametrize("multidut_port_info", MIXED_SPEED_PORT_INFO[MULTIDUT_TESTBED]) +def test_mixed_speed_pfcwd_disable(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 + + """ + Test to oversubscribe the 100Gbps egress link and have PFCWD disabled. + Sending PAUSE frames to egress link for the lossless traffic. + DUT should send PFCs for the lossless traffic and have zero loss for lossless traffic. + Lossy traffic should be dropped. + DUT allows equal amount of traffic (lossless and lossy priorities) to the egress. + Egress traffic is around 100Gbps. + + 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 MIXED_SPEED_PORT_INFO[MULTIDUT_TESTBED].items(): + tx_port_count = port_map[0] + rx_port_count = port_map[2] + snappi_port_list = get_snappi_ports + 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': 0, 'lossy': 75, 'speed_tol': 3, '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/Single_400Gbps_Ingress_Single_100Gbps_Egress_pause_pfcwd_disable_', + 'line_card_choice': testbed_subtype, + 'port_map': port_map, + 'enable_pfcwd': False, + 'enable_credit_wd': False, + '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 = 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) + + 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: + cleanup_config(dut_list, snappi_ports) diff --git a/tests/snappi_tests/variables.py b/tests/snappi_tests/variables.py index c2cef586681..88e70456f88 100644 --- a/tests/snappi_tests/variables.py +++ b/tests/snappi_tests/variables.py @@ -31,7 +31,20 @@ } }) )} - +# rx port is 400Gbps port receiving traffic in mixed-speed mode. +# tx port is 100Gbps port sending traffic to IXIA. +MIXED_SPEED_PORT_INFO = {MULTIDUT_TESTBED: ( + ({ + 'multiple-dut-any-asic': { + 'rx_ports': [ + {'port_name': 'Ethernet0', 'hostname': "sonic-s6100-dut1"} + ], + 'tx_ports': [ + {'port_name': 'Ethernet0', 'hostname': "sonic-s6100-dut2"} + ] + } + }) +)} ''' In this file user can modify the line_card_choice and it chooses the corresponding hostname and asic values from the config_set hostnames can be modified according to the dut hostname mentioned