def run_pfcwd_runtime_traffic_test(api, testbed_config, conn_data, fanout_data, duthost, dut_port, prio_list, prio_dscp_map): """ Test PFC watchdog's impact on runtime traffic Args: api (obj): IXIA session testbed_config (obj): L2/L3 config of a T0 testbed 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 prio_list (list): priorities of data flows prio_dscp_map (dict): Priority vs. DSCP map (key = priority). Returns: N/A """ pytest_assert(testbed_config is not None, 'Fail to get L2/3 testbed config') stop_pfcwd(duthost) """ Get the ID of the port to test """ port_id = get_dut_port_id(dut_hostname=duthost.hostname, dut_port=dut_port, conn_data=conn_data, fanout_data=fanout_data) pytest_assert(port_id is not None, 'Fail to get ID for port {}'.format(dut_port)) flows = __gen_traffic(testbed_config=testbed_config, port_id=port_id, data_flow_name=DATA_FLOW_NAME, data_flow_dur_sec=DATA_FLOW_DURATION_SEC, data_pkt_size=DATA_PKT_SIZE, prio_list=prio_list, prio_dscp_map=prio_dscp_map) """ Tgen config = testbed config + flow config """ config = testbed_config config.flows = flows all_flow_names = [flow.name for flow in flows] flow_stats = __run_traffic(api=api, config=config, duthost=duthost, all_flow_names=all_flow_names, pfcwd_start_delay_sec=PFCWD_START_DELAY_SEC, exp_dur_sec=DATA_FLOW_DURATION_SEC) speed_str = config.layer1[0].speed speed_gbps = int(speed_str.split('_')[1]) __verify_results(rows=flow_stats, speed_gbps=speed_gbps, data_flow_dur_sec=DATA_FLOW_DURATION_SEC, data_pkt_size=DATA_PKT_SIZE, tolerance=TOLERANCE_THRESHOLD)
def __gen_traffic(testbed_config, dut_hostname, dut_port, conn_data, fanout_data): tx_port_id = get_dut_port_id(dut_hostname=dut_hostname, dut_port=dut_port, conn_data=conn_data, fanout_data=fanout_data) if tx_port_id is None: return None rx_port_id = (tx_port_id + 1) % len(testbed_config.devices) """ Traffic configuraiton """ flow_name = 'Test Flow' rate_percent = 50 duration_sec = 2 pkt_size = 1024 data_endpoint = DeviceTxRx( tx_device_names=[testbed_config.devices[tx_port_id].name], rx_device_names=[testbed_config.devices[rx_port_id].name], ) flow_dscp = Priority(Dscp(phb=FieldPattern(choice=[3, 4]))) flow = Flow(name=flow_name, tx_rx=TxRx(data_endpoint), packet=[ Header(choice=EthernetHeader()), Header(choice=Ipv4Header(priority=flow_dscp)) ], size=Size(pkt_size), rate=Rate('line', rate_percent), duration=Duration( FixedSeconds(seconds=duration_sec, delay=0, delay_unit='nanoseconds'))) return [flow]
def run_ecn_test(api, testbed_config, conn_data, fanout_data, duthost, dut_port, kmin, kmax, pmax, pkt_size, pkt_cnt, lossless_prio, prio_dscp_map, iters): """ Run a ECN test Args: api (obj): IXIA session testbed_config (obj): L2/L3 config of a T0 testbed 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 kmin (int): RED/ECN minimum threshold in bytes kmax (int): RED/ECN maximum threshold in bytes pmax (int): RED/ECN maximum marking probability in percentage pkt_size (int): data packet size in bytes pkt_cnt (int): data packet count lossless_prio (int): lossless priority prio_dscp_map (dict): Priority vs. DSCP map (key = priority). iters (int): # of iterations in the test Returns: Return captured IP packets (list of list) """ pytest_assert(testbed_config is not None, 'Failed to get L2/3 testbed config') stop_pfcwd(duthost) disable_packet_aging(duthost) """ Configure WRED/ECN thresholds """ config_result = config_wred(host_ans=duthost, kmin=kmin, kmax=kmax, pmax=pmax) pytest_assert(config_result is True, 'Failed to configure WRED/ECN at the DUT') """ Enable ECN marking """ enable_ecn(host_ans=duthost, prio=lossless_prio) """ Configure PFC threshold to 2 ^ 3 """ config_result = config_ingress_lossless_buffer_alpha(host_ans=duthost, alpha_log2=3) pytest_assert(config_result is True, 'Failed to configure PFC threshold to 8') """ Get the ID of the port to test """ port_id = get_dut_port_id(dut_hostname=duthost.hostname, dut_port=dut_port, conn_data=conn_data, fanout_data=fanout_data) pytest_assert(port_id is not None, 'Failed to get ID for port {}'.format(dut_port)) """ Generate packet capture config """ capture_config = __config_capture_ip_pkt(testbed_config=testbed_config, port_id=port_id) """ Generate traffic config """ flows = __gen_traffic(testbed_config=testbed_config, port_id=port_id, pause_flow_name=PAUSE_FLOW_NAME, data_flow_name=DATA_FLOW_NAME, prio=lossless_prio, data_pkt_size=pkt_size, data_pkt_cnt=pkt_cnt, data_flow_delay_sec=DATA_START_DELAY_SEC, exp_dur_sec=EXP_DURATION_SEC, prio_dscp_map=prio_dscp_map) """ Tgen config = testbed config + flow config + capture config""" config = testbed_config config.flows = flows config.captures = capture_config """ Run traffic and capture packets """ capture_port_name = capture_config[0].port_names[0] result = [] for i in range(iters): pcap_file_name = '{}-{}.pcap'.format(capture_port_name, i) __run_traffic(api=api, config=config, all_flow_names=[PAUSE_FLOW_NAME, DATA_FLOW_NAME], exp_dur_sec=EXP_DURATION_SEC, capture_port_name=capture_port_name, pcap_file_name=pcap_file_name) result.append(__get_ip_pkts(pcap_file_name)) return result
def run_pfcwd_basic_test(api, testbed_config, port_config_list, conn_data, fanout_data, duthost, dut_port, prio_list, prio_dscp_map, trigger_pfcwd): """ Run a basic PFC watchdog test Args: api (obj): IXIA 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 prio_list (list): priorities of data flows and pause storm prio_dscp_map (dict): Priority vs. DSCP map (key = priority). trigger_pfcwd (bool): if PFC watchdog is expected to be triggered Returns: N/A """ pytest_assert(testbed_config is not None, 'Fail to get L2/3 testbed config') start_pfcwd(duthost) enable_packet_aging(duthost) """ Get the ID of the port to test """ port_id = get_dut_port_id(dut_hostname=duthost.hostname, dut_port=dut_port, conn_data=conn_data, fanout_data=fanout_data) pytest_assert(port_id is not None, 'Fail to get ID for port {}'.format(dut_port)) poll_interval_sec = get_pfcwd_poll_interval(duthost) / 1000.0 detect_time_sec = get_pfcwd_detect_time(host_ans=duthost, intf=dut_port) / 1000.0 restore_time_sec = get_pfcwd_restore_time(host_ans=duthost, intf=dut_port) / 1000.0 if trigger_pfcwd: """ Large enough to trigger PFC watchdog """ pfc_storm_dur_sec = ceil(detect_time_sec + poll_interval_sec + 0.1) flow1_delay_sec = restore_time_sec / 2 flow1_dur_sec = pfc_storm_dur_sec """ Start data traffic 2 after PFC is restored """ flow2_delay_sec = pfc_storm_dur_sec + restore_time_sec + poll_interval_sec flow2_dur_sec = 1 flow1_max_loss_rate = 1 flow1_min_loss_rate = 1 - DEVIATION else: pfc_storm_dur_sec = detect_time_sec * 0.5 flow1_delay_sec = pfc_storm_dur_sec * 0.1 flow1_dur_sec = ceil(pfc_storm_dur_sec) """ Start data traffic 2 after the completion of data traffic 1 """ flow2_delay_sec = flow1_delay_sec + flow1_dur_sec + 0.1 flow2_dur_sec = 1 flow1_max_loss_rate = 0 flow1_min_loss_rate = 0 exp_dur_sec = flow2_delay_sec + flow2_dur_sec + 1 """ Generate traffic config """ flows = __gen_traffic( testbed_config=testbed_config, port_config_list=port_config_list, port_id=port_id, pause_flow_name=PAUSE_FLOW_NAME, pause_flow_dur_sec=pfc_storm_dur_sec, data_flow_name_list=[DATA_FLOW1_NAME, DATA_FLOW2_NAME], data_flow_delay_sec_list=[flow1_delay_sec, flow2_delay_sec], data_flow_dur_sec_list=[flow1_dur_sec, flow2_dur_sec], data_pkt_size=DATA_PKT_SIZE, prio_list=prio_list, prio_dscp_map=prio_dscp_map) """ Tgen config = testbed config + flow config """ config = testbed_config config.flows = flows all_flow_names = [flow.name for flow in flows] flow_stats = __run_traffic(api=api, config=config, all_flow_names=all_flow_names, exp_dur_sec=exp_dur_sec) __verify_results(rows=flow_stats, data_flow_name_list=[DATA_FLOW1_NAME, DATA_FLOW2_NAME], data_flow_min_loss_rate_list=[flow1_min_loss_rate, 0], data_flow_max_loss_rate_list=[flow1_max_loss_rate, 0])
def run_pfc_test(api, testbed_config, port_config_list, conn_data, fanout_data, duthost, dut_port, global_pause, pause_prio_list, test_prio_list, bg_prio_list, prio_dscp_map, test_traffic_pause): """ Run a PFC test Args: api (obj): IXIA 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 Returns: N/A """ pytest_assert(testbed_config is not None, 'Fail to get L2/3 testbed config') stop_pfcwd(duthost) disable_packet_aging(duthost) """ Get the ID of the port to test """ port_id = get_dut_port_id(dut_hostname=duthost.hostname, dut_port=dut_port, conn_data=conn_data, fanout_data=fanout_data) pytest_assert(port_id is not None, 'Fail to get ID for port {}'.format(dut_port)) """ Rate percent must be an integer """ test_flow_rate_percent = int(TEST_FLOW_AGGR_RATE_PERCENT / len(test_prio_list)) bg_flow_rate_percent = int(BG_FLOW_AGGR_RATE_PERCENT / len(bg_prio_list)) """ Generate traffic config """ flows = __gen_traffic(testbed_config=testbed_config, port_config_list=port_config_list, port_id=port_id, duthost=duthost, pause_flow_name=PAUSE_FLOW_NAME, global_pause=global_pause, pause_prio_list=pause_prio_list, test_flow_name=TEST_FLOW_NAME, test_flow_prio_list=test_prio_list, test_flow_rate_percent=test_flow_rate_percent, bg_flow_name=BG_FLOW_NAME, bg_flow_prio_list=bg_prio_list, bg_flow_rate_percent=bg_flow_rate_percent, data_flow_dur_sec=DATA_FLOW_DURATION_SEC, data_flow_delay_sec=DATA_FLOW_DELAY_SEC, data_pkt_size=DATA_PKT_SIZE, prio_dscp_map=prio_dscp_map) """ Tgen config = testbed config + flow config """ config = testbed_config config.flows = flows """ import json config_json = json.dumps(config, indent=2, default=lambda x: x.__dict__) print(config_json) """ 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] """ Run traffic """ flow_stats = __run_traffic(api=api, config=config, data_flow_names=data_flow_names, all_flow_names=all_flow_names, exp_dur_sec=DATA_FLOW_DURATION_SEC+DATA_FLOW_DELAY_SEC) speed_str = config.layer1[0].speed speed_gbps = int(speed_str.split('_')[1]) """ Verify experiment results """ __verify_results(rows=flow_stats, duthost=duthost, pause_flow_name=PAUSE_FLOW_NAME, test_flow_name=TEST_FLOW_NAME, bg_flow_name=BG_FLOW_NAME, data_flow_dur_sec=DATA_FLOW_DURATION_SEC, test_flow_rate_percent=test_flow_rate_percent, bg_flow_rate_percent=bg_flow_rate_percent, data_pkt_size=DATA_PKT_SIZE, speed_gbps=speed_gbps, test_flow_pause=test_traffic_pause, tolerance=TOLERANCE_THRESHOLD)
def run_pfcwd_multi_node_test(api, testbed_config, conn_data, fanout_data, duthost, dut_port, pause_prio_list, test_prio_list, bg_prio_list, prio_dscp_map, trigger_pfcwd, pattern): """ Run PFC watchdog test in a multi-node (>=3) topoology Args: api (obj): IXIA session testbed_config (obj): L2/L3 config of a T0 testbed 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 pause_prio_list (list): priorities to pause for PFC pause storm 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). trigger_pfcwd (bool): if PFC watchdog is expected to be triggered pattern (str): traffic pattern Returns: N/A """ patterns = ['all to all', '2 sender 2 receiver'] pytest_assert( pattern in patterns, 'Unknown pattern {}. We only support {}'.format(pattern, patterns)) pytest_assert(testbed_config is not None, 'Fail to get L2/3 testbed config') num_devices = len(testbed_config.devices) pytest_require(num_devices >= 3, "This test requires at least 3 hosts") start_pfcwd(duthost) enable_packet_aging(duthost) """ Get the ID of the port to test """ port_id = get_dut_port_id(dut_hostname=duthost.hostname, dut_port=dut_port, conn_data=conn_data, fanout_data=fanout_data) pytest_assert(port_id is not None, 'Fail to get ID for port {}'.format(dut_port)) poll_interval_sec = get_pfcwd_poll_interval(duthost) / 1000.0 detect_time_sec = get_pfcwd_detect_time(host_ans=duthost, intf=dut_port) / 1000.0 if trigger_pfcwd: pfc_storm_dur_sec = poll_interval_sec + detect_time_sec else: pfc_storm_dur_sec = 0.5 * detect_time_sec exp_dur_sec = ceil(pfc_storm_dur_sec + 1) """ Generate traffic config """ if pattern == "all to all": test_flow_rate_percent = int(TEST_FLOW_AGGR_RATE_PERCENT / \ (num_devices - 1) / \ len(test_prio_list)) bg_flow_rate_percent = int(BG_FLOW_AGGR_RATE_PERCENT / \ (num_devices - 1) / \ len(bg_prio_list)) flows = __gen_a2a_traffic( testbed_config=testbed_config, port_id=port_id, pause_flow_name=PAUSE_FLOW_NAME, pause_prio_list=pause_prio_list, test_flow_name=TEST_FLOW_NAME, test_flow_prio_list=test_prio_list, test_flow_rate_percent=test_flow_rate_percent, bg_flow_name=BG_FLOW_NAME, bg_flow_prio_list=bg_prio_list, bg_flow_rate_percent=bg_flow_rate_percent, data_flow_dur_sec=exp_dur_sec, pfc_storm_dur_sec=pfc_storm_dur_sec, data_pkt_size=DATA_PKT_SIZE, prio_dscp_map=prio_dscp_map) elif pattern == "2 sender 2 receiver": test_flow_rate_percent = int(TEST_FLOW_AGGR_RATE_PERCENT / \ 2.0 / \ len(test_prio_list)) bg_flow_rate_percent = int(BG_FLOW_AGGR_RATE_PERCENT / \ 2.0 / \ len(bg_prio_list)) flows = __gen_2sender_2receiver_traffic( testbed_config=testbed_config, port_id=port_id, pause_flow_name=PAUSE_FLOW_NAME, pause_prio_list=pause_prio_list, test_flow_name=TEST_FLOW_NAME, test_flow_prio_list=test_prio_list, test_flow_rate_percent=test_flow_rate_percent, bg_flow_name=BG_FLOW_NAME, bg_flow_prio_list=bg_prio_list, bg_flow_rate_percent=bg_flow_rate_percent, data_flow_dur_sec=exp_dur_sec, pfc_storm_dur_sec=pfc_storm_dur_sec, data_pkt_size=DATA_PKT_SIZE, prio_dscp_map=prio_dscp_map) """ Tgen config = testbed config + flow config """ config = testbed_config config.flows = flows all_flow_names = [flow.name for flow in flows] flow_stats = __run_traffic(api=api, config=config, all_flow_names=all_flow_names, exp_dur_sec=exp_dur_sec) speed_str = config.layer1[0].speed speed_gbps = int(speed_str.split('_')[1]) __verify_results(rows=flow_stats, speed_gbps=speed_gbps, pause_flow_name=PAUSE_FLOW_NAME, test_flow_name=TEST_FLOW_NAME, bg_flow_name=BG_FLOW_NAME, test_flow_rate_percent=test_flow_rate_percent, bg_flow_rate_percent=bg_flow_rate_percent, data_flow_dur_sec=exp_dur_sec, data_pkt_size=DATA_PKT_SIZE, trigger_pfcwd=trigger_pfcwd, pause_port_id=port_id, tolerance=TOLERANCE_THRESHOLD)
def run_pfcwd_burst_storm_test(api, testbed_config, port_config_list, conn_data, fanout_data, duthost, dut_port, prio_list, prio_dscp_map): """ Test PFC watchdog under bursty PFC storms Args: api (obj): IXIA 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 prio_list (list): priorities to generate PFC storms and data traffic prio_dscp_map (dict): Priority vs. DSCP map (key = priority). Returns: N/A """ pytest_assert(testbed_config is not None, 'Fail to get L2/3 testbed config') start_pfcwd(duthost) enable_packet_aging(duthost) """ Get the ID of the port to test """ port_id = get_dut_port_id(dut_hostname=duthost.hostname, dut_port=dut_port, conn_data=conn_data, fanout_data=fanout_data) pytest_assert(port_id is not None, 'Fail to get ID for port {}'.format(dut_port)) poll_interval_sec = get_pfcwd_poll_interval(duthost) / 1000.0 detect_time_sec = get_pfcwd_detect_time(host_ans=duthost, intf=dut_port) / 1000.0 restore_time_sec = get_pfcwd_restore_time(host_ans=duthost, intf=dut_port) / 1000.0 burst_cycle_sec = poll_interval_sec + detect_time_sec + restore_time_sec + 0.1 data_flow_dur_sec = ceil(burst_cycle_sec * BURST_EVENTS) pause_flow_dur_sec = poll_interval_sec * 0.5 pause_flow_gap_sec = burst_cycle_sec - pause_flow_dur_sec flows = __gen_traffic(testbed_config=testbed_config, port_config_list=port_config_list, port_id=port_id, pause_flow_prefix=PAUSE_FLOW_PREFIX, pause_flow_dur_sec=pause_flow_dur_sec, pause_flow_count = BURST_EVENTS, pause_flow_gap_sec=pause_flow_gap_sec, data_flow_prefix=DATA_FLOW_PREFIX, data_flow_dur_sec=data_flow_dur_sec, data_pkt_size=DATA_PKT_SIZE, prio_list=prio_list, prio_dscp_map=prio_dscp_map) """ Tgen config = testbed config + flow config """ config = testbed_config config.flows = flows all_flow_names = [flow.name for flow in flows] exp_dur_sec = BURST_EVENTS * poll_interval_sec + 1 flow_stats = __run_traffic(api=api, config=config, all_flow_names=all_flow_names, exp_dur_sec=exp_dur_sec) __verify_results(rows=flow_stats, data_flow_prefix=DATA_FLOW_PREFIX, pause_flow_prefix=PAUSE_FLOW_PREFIX)