Example #1
0
def __run_traffic(api, config, duthost, all_flow_names, pfcwd_start_delay_sec, exp_dur_sec):
    """
    Start traffic at time 0 and enable PFC watchdog at pfcwd_start_delay_sec

    Args:
        api (obj): SNAPPI session
        config (obj): experiment config (testbed config + flow config)
        duthost (Ansible host instance): device under test
        all_flow_names (list): list of names of all the flows
        pfcwd_start_delay_sec (int): PFC watchdog start delay in second
        exp_dur_sec (int): experiment duration in second

    Returns:
        per-flow statistics (list)
    """
    api.set_config(config)

    logger.info('Wait for Arp to Resolve ...')
    wait_for_arp(api, max_attempts=10, poll_interval_sec=2)

    logger.info('Starting transmit on all flows ...')
    ts = api.transmit_state()
    ts.state = ts.START
    api.set_transmit_state(ts)

    time.sleep(pfcwd_start_delay_sec)
    start_pfcwd(duthost)
    time.sleep(exp_dur_sec - pfcwd_start_delay_sec)

    attempts = 0
    max_attempts = 20

    while attempts < max_attempts:
        request = api.metrics_request()
        request.flow.flow_names = all_flow_names
        rows = api.get_metrics(request).flow_metrics
        """ If all the flows have stopped """
        transmit_states = [row.transmit for row in rows]
        if len(rows) == len(all_flow_names) and\
           list(set(transmit_states)) == ['stopped']:
            time.sleep(SNAPPI_POLL_DELAY_SEC)
            break
        else:
            time.sleep(1)
            attempts += 1

    pytest_assert(attempts < max_attempts,
                  "Flows do not stop in {} seconds".format(max_attempts))

    """ Dump per-flow statistics """
    request = api.metrics_request()
    request.flow.flow_names = all_flow_names
    rows = api.get_metrics(request).flow_metrics

    logger.info('Stop transmit on all flows ...')
    ts = api.transmit_state()
    ts.state = ts.STOP
    api.set_transmit_state(ts)

    return rows
Example #2
0
def start_pfcwd_after_test(duthosts, rand_one_dut_hostname):
    """
    Ensure that PFC watchdog is enabled with default setting after tests

    Args:
        duthosts (pytest fixture) : list of DUTs
        rand_one_dut_hostname (pytest fixture): DUT hostname

    Yields:
        N/A
    """
    yield

    duthost = duthosts[rand_one_dut_hostname]
    start_pfcwd(duthost)
def run_pfcwd_multi_node_test(api, testbed_config, port_config_list, 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): 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
        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', 'many to one']
    if pattern not in patterns:
        raise ValueError(
            'invalid traffic pattern passed in "{}", must be {}'.format(
                pattern,
                ' or '.join(['"{}"'.format(src) for src in patterns])))

    pytest_assert(testbed_config is not None,
                  'Fail to get L2/3 testbed config')
    num_ports = len(port_config_list)
    pytest_require(num_ports >= 3, "This test requires at least 3 ports")

    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 """
    test_flow_rate_percent = int(TEST_FLOW_AGGR_RATE_PERCENT / \
                                 (num_ports - 1) / \
                                 len(test_prio_list))

    bg_flow_rate_percent = int(BG_FLOW_AGGR_RATE_PERCENT / \
                               (num_ports - 1) / \
                               len(bg_prio_list))

    __gen_traffic(testbed_config=testbed_config,
                  port_config_list=port_config_list,
                  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,
                  traffic_pattern=pattern)

    flows = testbed_config.flows

    all_flow_names = [flow.name for flow in flows]

    flow_stats = __run_traffic(api=api,
                               config=testbed_config,
                               all_flow_names=all_flow_names,
                               exp_dur_sec=exp_dur_sec)

    speed_str = testbed_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)
Example #4
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): 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
        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

    __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)

    flows = testbed_config.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=testbed_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)
Example #5
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): 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
        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 """
    __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)

    flows = testbed_config.flows

    all_flow_names = [flow.name for flow in flows]

    flow_stats = __run_traffic(api=api,
                               config=testbed_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])