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)
예제 #2
0
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]
예제 #3
0
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
예제 #4
0
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])
예제 #5
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)
예제 #7
0
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)