Beispiel #1
0
def __run_traffic(api, config, data_flow_names, all_flow_names, exp_dur_sec):
    """
    Run traffic and dump per-flow statistics

    Args:
        api (obj): IXIA session
        config (obj): experiment config (testbed config + flow config)
        data_flow_names (list): list of names of data (test and background) flows
        all_flow_names (list): list of names of all the flows
        exp_dur_sec (int): experiment duration in second

    Returns:
        per-flow statistics (list)
    """
    api.set_state(State(ConfigState(config=config, state='set')))
    api.set_state(State(FlowTransmitState(state='start')))
    time.sleep(exp_dur_sec)

    while True:
        rows = api.get_flow_results(FlowRequest(flow_names=data_flow_names))
        """ If all the data flows have stopped """
        transmit_states = [row['transmit'] for row in rows]
        if len(rows) == len(data_flow_names) and\
           list(set(transmit_states)) == ['stopped']:
            time.sleep(IXIA_POLL_DELAY_SEC)
            break
        else:
            time.sleep(1)
    """ Dump per-flow statistics """
    rows = api.get_flow_results(FlowRequest(flow_names=all_flow_names))
    api.set_state(State(FlowTransmitState(state='stop')))

    return rows
def test_pfc_pause_lossy_traffic(api, duthost, lossy_configs, start_delay,
                                 traffic_duration):
    """
    This test case checks the behaviour of the SONiC DUT when it receives 
    a PFC pause frame on lossy priorities.

                                +-----------+
    [Keysight Chassis Tx Port]  |           | [Keysight Chassis Rx Port]
    --------------------------->| SONiC DUT |<---------------------------
    Test Data Traffic +         |           |  PFC pause frame on 
    Background Dada Traffic     +-----------+  "lossy" priorities.

    1. Configure SONiC DUT with multipul lossless priorities. 
    2. On SONiC DUT enable PFC on several lossless priorities e.g priority 
       3 and 4.
    3. On the Keysight chassis Tx port create two flows - a) 'Test Data Traffic'
       and b) 'Background Data traffic'.
    4. Configure 'Test Data Traffic' such that it contains traffic items
       with all lossy priorities.
    5. Configure 'Background Data Traffic' it contains traffic items with
       all lossless priorities.
    6. From Rx port send pause frames on all lossless priorities. Then
       start 'Test Data Traffic' and 'Background Data Traffic'.
    7. Verify the following: 
       (a) When Pause Storm are running, Keysight Rx port is receiving
       both 'Test Data Traffic' and 'Background Data traffic'.
       (b) When Pause Storm are stoped, then also Keysight Rx port is receiving
       both 'Test Data Traffic' and 'Background Data traffic'.
    """
    duthost.shell('sudo pfcwd stop')

    for base_config in lossy_configs:

        # create the configuration
        api.set_config(base_config)

        # start all flows
        api.set_flow_transmit(FlowTransmit(state='start'))

        exp_dur = start_delay + traffic_duration
        logger.info("Traffic is running for %s seconds" % (exp_dur))
        time.sleep(exp_dur)

        # stop all flows
        api.set_flow_transmit(FlowTransmit(state='stop'))

        # Get statistics
        test_stat = api.get_flow_results(FlowRequest())

        for rows in test_stat['rows']:
            tx_frame_index = test_stat['columns'].index('frames_tx')
            rx_frame_index = test_stat['columns'].index('frames_rx')
            caption_index = test_stat['columns'].index('name')
            if ((rows[caption_index] == 'Test Data')
                    or (rows[caption_index] == 'Background Data')):
                if rows[tx_frame_index] != rows[rx_frame_index]:
                    pytest_assert(
                        False,
                        "Not all %s reached Rx End" % (rows[caption_index]))
Beispiel #3
0
def test_ecn_marking_at_ecress(api, duthost, ecn_marking_at_ecress,
                               start_delay, pause_line_rate, traffic_line_rate,
                               traffic_duration, port_bandwidth, frame_size,
                               ecn_thresholds):

    duthost.shell('sudo pfcwd stop')
    duthost.shell('sudo sudo ecnconfig -p AZURE_LOSSLESS -gmax %s' %
                  (ecn_thresholds))
    duthost.shell('sudo sudo ecnconfig -p AZURE_LOSSLESS -gmin %s' %
                  (ecn_thresholds))

    for base_config in ecn_marking_at_ecress:
        rx_port = base_config.ports[1]
        rx_port.capture = Capture(choice=[], enable=True)

        # create the configuration
        api.set_config(base_config)

        # start capture
        api.set_port_capture(PortCapture(port_names=[rx_port.name]))

        # start all flows
        api.set_flow_transmit(FlowTransmit(state='start'))

        exp_dur = start_delay + traffic_duration
        logger.info("Traffic is running for %s seconds" % (traffic_duration))
        time.sleep(exp_dur)

        # stop all flows
        api.set_flow_transmit(FlowTransmit(state='stop'))

        pcap_bytes = api.get_capture_results(
            CaptureRequest(port_name=rx_port.name))

        # Get statistics
        test_stat = api.get_flow_results(FlowRequest())

        for rows in test_stat['rows']:
            tx_frame_index = test_stat['columns'].index('frames_tx')
            rx_frame_index = test_stat['columns'].index('frames_rx')
            caption_index = test_stat['columns'].index('name')
            if ((rows[caption_index] == 'Test Data')
                    or (rows[caption_index] == 'Background Data')):
                tx_frames = float(rows[tx_frame_index])
                rx_frames = float(rows[rx_frame_index])
                if ((tx_frames != rx_frames) or (rx_frames == 0)):
                    pytest_assert(
                        False,
                        "Not all %s reached Rx End" % (rows[caption_index]))

        # write the pcap bytes to a local file
        with open('%s.pcap' % rx_port.name, 'wb') as fid:
            fid.write(pcap_bytes)

        from scapy.all import PcapReader
        reader = PcapReader('%s.pcap' % rx_port.name)
        for item in reader:
            logger.info(tem.time)
            logger.info(item.show())
def test_pfc_global_pause(api, duthost, global_pause, start_delay,
                          pause_line_rate, traffic_line_rate, traffic_duration,
                          port_bandwidth, frame_size):
    """
                                +-----------+
    [Keysight Chassis Tx Port]  |           | [Keysight Chassis Rx Port]
    --------------------------->| SONiC DUT |<---------------------------
    Test Data Traffic +         |           |  PFC pause frame on 
    Background Dada Traffic     +-----------+  "lossy" priorities.

    """
    duthost.shell('sudo pfcwd stop')

    for base_config in global_pause:

        # create the configuration
        api.set_config(base_config)

        # start all flows
        api.set_flow_transmit(FlowTransmit(state='start'))

        exp_dur = start_delay + traffic_duration
        logger.info("Traffic is running for %s seconds" % (traffic_duration))
        time.sleep(exp_dur)

        api.set_flow_transmit(FlowTransmit(state='stop'))

        # Get statistics
        test_stat = api.get_flow_results(FlowRequest())

        for rows in test_stat['rows']:

            tx_frame_index = test_stat['columns'].index('frames_tx')
            rx_frame_index = test_stat['columns'].index('frames_rx')
            caption_index = test_stat['columns'].index('name')
            if ((rows[caption_index] == 'Test Data')
                    or (rows[caption_index] == 'Background Data')):

                tx_frames = float(rows[tx_frame_index])
                rx_frames = float(rows[rx_frame_index])

                if ((tx_frames != rx_frames) or (rx_frames == 0)):
                    pytest_assert(
                        False,
                        "Not all %s reached Rx End" % (rows[caption_index]))

                rx_bytes = rx_frames * frame_size

                line_rate = traffic_line_rate / 100.0
                exp_rx_bytes = (port_bandwidth * line_rate *
                                traffic_duration) / 8

                tolerance_ratio = rx_bytes / exp_rx_bytes

                if ((tolerance_ratio < TOLERANCE_THRESHOLD)
                        or (tolerance_ratio > 1)):
                    pytest_assert(
                        False,
                        "expected % of packets not received at the RX port")
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): IXIA 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_state(State(ConfigState(config=config, state='set')))
    api.set_state(State(FlowTransmitState(state='start')))

    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:
        rows = api.get_flow_results(FlowRequest(flow_names=all_flow_names))
        """ 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(IXIA_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 """
    rows = api.get_flow_results(FlowRequest(flow_names=all_flow_names))
    api.set_state(State(FlowTransmitState(state='stop')))

    return rows
def __run_traffic(api, config, all_flow_names, exp_dur_sec):
    """
    Run traffic and dump per-flow statistics

    Args:
        api (obj): IXIA session
        config (obj): experiment config (testbed config + flow config)
        all_flow_names (list): list of names of all the flows
        exp_dur_sec (float): experiment duration in second

    Returns:
        per-flow statistics (list)
    """
    api.set_state(State(ConfigState(config=config, state='set')))
    api.set_state(State(FlowTransmitState(state='start')))
    time.sleep(exp_dur_sec)

    attempts = 0
    max_attempts = 20

    while attempts < max_attempts:
        rows = api.get_flow_results(FlowRequest(flow_names=all_flow_names))
        """ 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(IXIA_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 """
    rows = api.get_flow_results(FlowRequest(flow_names=all_flow_names))
    api.set_state(State(FlowTransmitState(state='stop')))

    return rows
Beispiel #7
0
def __run_traffic(api,
                  config,
                  all_flow_names,
                  exp_dur_sec,
                  capture_port_name,
                  pcap_file_name):
    """
    Run traffic and capture packets

    Args:
        api (obj): IXIA session
        config (obj): experiment config
        all_flow_names (list): names of all the flows
        capture_port_name (str): name of the port to capture packets
        pcap_file_name (str): name of the pcap file to store captured packets

    Returns:
        N/A
    """
    api.set_state(State(ConfigState(config=config, state='set')))

    api.set_state(State(PortCaptureState(port_names=[capture_port_name],
                                         state='start')))

    api.set_state(State(FlowTransmitState(state='start')))
    time.sleep(exp_dur_sec)

    attempts = 0
    max_attempts = 20

    while attempts < max_attempts:
        rows = api.get_flow_results(FlowRequest(flow_names=all_flow_names))
        """ 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(IXIA_POLL_DELAY_SEC)
            break
        else:
            time.sleep(1)
            attempts += 1

    """ Dump captured packets """
    pcap_bytes = api.get_capture_results(CaptureRequest(port_name=capture_port_name))
    with open(pcap_file_name, 'wb') as fid:
        fid.write(pcap_bytes)

    """ Stop all the flows """
    api.set_state(State(FlowTransmitState(state='stop')))
def test_get_ingress_results(serializer, options, tx_port, rx_port, api):
    """UDP Flow test traffic configuration
    """
    udp_endpoint = PortTxRx(tx_port_name=tx_port.name,
                            rx_port_names=[rx_port.name])
    udp_header = Udp(src_port=Pattern(Counter(start="12001",
                                              step="2",
                                              count=100),
                                      ingress_result_name='UDP SRC PORT'),
                     dst_port=Pattern("20"))
    udp_flow = Flow(name='UDP Flow',
                    tx_rx=TxRx(udp_endpoint),
                    packet=[
                        Header(Ethernet()),
                        Header(Vlan()),
                        Header(Ipv4()),
                        Header(udp_header)
                    ],
                    size=Size(128),
                    rate=Rate(unit='pps', value=1000),
                    duration=Duration(FixedPackets(packets=10000)))
    config = Config(ports=[tx_port, rx_port],
                    flows=[udp_flow],
                    options=options)
    state = State(ConfigState(config=config, state='set'))
    print(serializer.json(state))
    api.set_state(state)
    state = State(FlowTransmitState(state='start'))
    api.set_state(state)

    from pandas import DataFrame
    request = FlowRequest(ingress_result_names=['UDP SRC PORT'])
    while True:
        results = api.get_flow_results(request)
        df = DataFrame.from_dict(results)
        print(df)
        if df.frames_tx.sum() >= 10000 and df.frames_tx_rate.sum() == 0:
            break
def test_pfcwd_two_senders_two_receivers(api, duthost, pfcwd_configs,
                                         lossless_prio_dscp_map, start_delay,
                                         t_start_pause, t_stop_pause,
                                         t_stop_traffic, storm_detection_time,
                                         storm_restoration_time,
                                         tolerance_percent):
    """
    +-----------------+           +--------------+           +-----------------+       
    | Keysight Port 1 |------ et1 |   SONiC DUT  | et2 ------| Keysight Port 2 | 
    +-----------------+           +--------------+           +-----------------+ 
                                       et3
                                        |
                                        |
                                        |
                                +-----------------+
                                | Keysight Port 3 |
                                +-----------------+

    Configuration:
    1. Configure a single lossless priority value Pi (0 <= i <= 7).
    2. Enable watchdog with default storm detection time (400ms) and restoration time (2sec).
    3. On Keysight Chassis, create bi-directional traffic between Port 1 and Port 2
       with DSCP value mapped to lossless priority Pi
       a. Traffic 1->2
       b. Traffic 2->1
    4. Create bi-directional traffic between Port 2 and Port 3 with DSCP value mapped 
       to lossless priority Pi
       a. Traffic 2->3
       b. Traffic 3->2
    5. Create PFC pause storm: Persistent PFC pause frames from Keysight port 3 to et3 of DUT.
        Priority of the PFC pause frames should be same as that configured in DUT 
        and the inter-frame transmission interval should be lesser than per-frame pause duration.

    # Workflow
    1. At time TstartTraffic , start all the bi-directional lossless traffic items.
    2. At time TstartPause , start PFC pause storm.
    3. At time TstopPause , stop PFC pause storm. (TstopPause - TstartPause)
        should be larger than PFC storm detection time + PFC watchdog polling interval to trigger PFC watchdog.
    4. At time TstopTraffic , stop lossless traffic items. Note that (TstopTraffic - TstopPause) should 
        be larger than PFC storm restoration time to re-enable PFC.
    5. Verify the following:
        --> PFC watchdog is triggered on the corresponding lossless priorities at DUT interface et3.
        --> 'Traffic 1->2' and 'Traffic 2->1' must not experience any packet loss.
            Its throughput should be close to 50% of the line rate.
        --> For 'Traffic 2->3' and 'Traffic 3->2' , between TstartPause and TstopPause , 
            there should be some packet loss.
        --> There should not be any traffic loss after PFC storm restoration time has elapsed.
    """

    #######################################################################
    # DUT Configuration
    #######################################################################
    duthost.shell('sudo pfcwd stop')

    cmd = 'sudo pfcwd start --action drop ports all detection-time {} \
           --restoration-time {}'.format(storm_detection_time,
                                         storm_restoration_time)
    duthost.shell(cmd)

    duthost.shell('pfcwd show config')

    t_btwn_start_pause_and_stop_pause = t_stop_pause - t_start_pause
    t_btwn_stop_pause_and_stop_traffic = t_stop_traffic - t_stop_pause

    prio_list = [prio for prio in lossless_prio_dscp_map]
    #######################################################################
    # TGEN Config and , Repeating TEST for Lossless priority 3 and 4
    #######################################################################

    for prio in prio_list:
        logger.info("Test for priority {}".format(prio))
        configs = pfcwd_configs(prio)
        # Repeat the test for each config with different port combinations
        for config in configs:
            api.set_state(State(ConfigState(config=config, state='set')))

            ##############################################################################################
            # Start all flows
            # 1. check for no loss in the flows Traffic 1->2,Traffic 2->1
            # 2. check for loss in 'Traffic 2->3','Traffic 3->2' during pause storm
            ##############################################################################################
            api.set_state(State(FlowTransmitState(state='start')))

            # Sleeping till t_start_pause as t_start_pause is added as delay for the flow
            time.sleep(start_delay + t_start_pause)

            t_to_stop_pause = datetime.datetime.now() + datetime.timedelta(
                seconds=t_btwn_start_pause_and_stop_pause)

            #Check for traffic observations for two timestamps in t_btwn_start_pause_and_stop_pause
            while True:
                if datetime.datetime.now() >= t_to_stop_pause:
                    break
                else:
                    time.sleep(t_btwn_start_pause_and_stop_pause / 2)
                    # Get statistics
                    test_stat = api.get_flow_results(FlowRequest())
                    for flow in test_stat:
                        if flow['name'] in ['Traffic 1->2', 'Traffic 2->1']:
                            tx_frame_rate = int(flow['frames_tx_rate'])
                            rx_frame_rate = int(flow['frames_rx_rate'])
                            tolerance = (tx_frame_rate *
                                         tolerance_percent) / 100
                            logger.info(
                                "\nTx Frame Rate,Rx Frame Rate of {} during Pause Storm: {},{}"
                                .format(flow['name'], tx_frame_rate,
                                        rx_frame_rate))
                            if tx_frame_rate > (rx_frame_rate + tolerance):
                                pytest_assert(
                                    False,
                                    "Observing loss for %s during pause storm which is not expected"
                                    % (flow['name']))
                        elif flow['name'] in ['Traffic 2->3', 'Traffic 3->2']:
                            tx_frame_rate = int(flow['frames_tx_rate'])
                            rx_frame_rate = int(flow['frames_rx_rate'])
                            logger.info(
                                "\nTx Frame Rate,Rx Frame Rate of {} during Pause Storm: {},{}"
                                .format(flow['name'], tx_frame_rate,
                                        rx_frame_rate))
                            if (tx_frame_rate == 0) or (rx_frame_rate != 0):
                                pytest_assert(
                                    False,
                                    "Expecting loss for %s during pause storm, which didn't occur"
                                    % (flow['name']))

            ###############################################################################################
            # Stop Pause Storm
            # 1. check for no loss in the flows Traffic 1->2,Traffic 2->1
            # 2. check for no loss in 'Traffic 2->3','Traffic 3->2' after stopping Pause Storm
            ###############################################################################################
            # pause storm will stop once loop completes, once the current time reaches t_stop_pause

            api.set_state(
                State(
                    FlowTransmitState(state='stop',
                                      flow_names=['Pause Storm'])))

            # Verification after pause storm is stopped
            t_to_stop_traffic = datetime.datetime.now() + datetime.timedelta(
                seconds=t_btwn_stop_pause_and_stop_traffic)

            #Check for traffic observations for two timestamps in t_btwn_stop_pause_and_stop_traffic
            while True:
                if datetime.datetime.now() >= t_to_stop_traffic:
                    break
                else:
                    time.sleep(t_btwn_stop_pause_and_stop_traffic / 2)
                    # Get statistics
                    test_stat = api.get_flow_results(FlowRequest())

                    for flow in test_stat:
                        if flow['name'] in ['Traffic 1->2', 'Traffic 2->1']:
                            tx_frame_rate = int(flow['frames_tx_rate'])
                            rx_frame_rate = int(flow['frames_rx_rate'])
                            tolerance = (tx_frame_rate *
                                         tolerance_percent) / 100
                            logger.info(
                                "\nTx Frame Rate,Rx Frame Rate of {} after stopping Pause Storm: {},{}"
                                .format(flow['name'], tx_frame_rate,
                                        rx_frame_rate))
                            if tx_frame_rate > (rx_frame_rate + tolerance):
                                pytest_assert(
                                    False,
                                    "Observing loss for %s after pause storm stopped which is not expected"
                                    % (flow['name']))
                        elif flow['name'] in ['Traffic 2->3', 'Traffic 3->2']:
                            tx_frame_rate = int(flow['frames_tx_rate'])
                            rx_frame_rate = int(flow['frames_rx_rate'])
                            tolerance = (tx_frame_rate *
                                         tolerance_percent) / 100
                            logger.info(
                                "\nTx Frame Rate,Rx Frame Rate of {} after stopping Pause Storm: {},{}"
                                .format(flow['name'], tx_frame_rate,
                                        rx_frame_rate))
                            if tx_frame_rate > (rx_frame_rate + tolerance):
                                pytest_assert(
                                    False,
                                    "Observing loss for %s after pause storm stopped which is not expected"
                                    % (flow['name']))

            # stop all flows
            api.set_state(State(FlowTransmitState(state='stop')))
Beispiel #10
0
def test_tgen(traffic_config, ixia_api):
    config = traffic_config

    flow_name = config.flows[0].name
    pkt_size = config.flows[0].size.fixed
    rate_percent = config.flows[0].rate.value
    duration_sec = config.flows[0].duration.seconds.seconds

    port_speed = config.layer1[0].speed
    words = port_speed.split('_')
    pytest_assert(
        len(words) == 3 and words[1].isdigit(),
        'Fail to get port speed from {}'.format(port_speed))

    port_speed_gbps = int(words[1])
    """ Apply configuration """
    ixia_api.set_state(State(ConfigState(config=config, state='set')))
    """ Start traffic """
    ixia_api.set_state(State(FlowTransmitState(state='start')))
    """ Wait for traffic to finish """
    time.sleep(duration_sec)

    while True:
        rows = ixia_api.get_flow_results(FlowRequest(flow_names=[flow_name]))
        if len(rows) == 1 and \
           rows[0]['name'] == flow_name and \
           rows[0]['transmit'] == 'stopped':
            """ Wait for counters to fully propagate """
            time.sleep(2)
            break
        else:
            time.sleep(1)
    """ Dump per-flow statistics """
    rows = ixia_api.get_flow_results(FlowRequest(flow_names=[flow_name]))
    """ Stop traffic """
    ixia_api.set_state(State(FlowTransmitState(state='stop')))
    """ Analyze traffic results """
    pytest_assert(
        len(rows) == 1 and rows[0]['name'] == flow_name,
        'Fail to get results of flow {}'.format(flow_name))

    row = rows[0]
    rx_frames = row['frames_rx']
    tx_frames = row['frames_tx']

    pytest_assert(
        rx_frames == tx_frames,
        'Unexpected packet losses (Tx: {}, Rx: {})'.format(
            tx_frames, rx_frames))

    tput_bps = port_speed_gbps * 1e9 * rate_percent / 100.0
    exp_rx_frames = tput_bps * duration_sec / 8 / pkt_size

    deviation_thresh = 0.05
    ratio = float(exp_rx_frames) / rx_frames
    deviation = abs(ratio - 1)

    pytest_assert(
        deviation <= deviation_thresh,
        'Expected / Actual # of pkts: {} / {}'.format(exp_rx_frames,
                                                      rx_frames))
Beispiel #11
0
def test_tgen(conn_graph_facts, fanout_graph_facts, ixia_api, ixia_testbed,
              enum_dut_portname_oper_up):
    """
    Test if we can use Tgen API generate traffic in a testbed

    Args:
        conn_graph_facts (pytest fixture): connection graph
        fanout_graph_facts (pytest fixture): fanout graph
        ixia_api (pytest fixture): IXIA session
        ixia_testbed (pytest fixture): L2/L3 config of a T0 testbed
        enum_dut_portname_oper_up (str): name of port to test, e.g., 's6100-1|Ethernet0'

    Returns:
        None
    """

    words = enum_dut_portname_oper_up.split('|')
    pytest_require(len(words) == 2, "Fail to parse port name")

    dut_hostname = words[0]
    dut_port = words[1]

    config = ixia_testbed
    config.flows = __gen_traffic(testbed_config=config,
                                 dut_hostname=dut_hostname,
                                 dut_port=dut_port,
                                 conn_data=conn_graph_facts,
                                 fanout_data=fanout_graph_facts)

    flow_name = config.flows[0].name
    pkt_size = config.flows[0].size.fixed
    rate_percent = config.flows[0].rate.value
    duration_sec = config.flows[0].duration.seconds.seconds

    port_speed = config.layer1[0].speed
    words = port_speed.split('_')
    pytest_assert(
        len(words) == 3 and words[1].isdigit(),
        'Fail to get port speed from {}'.format(port_speed))

    port_speed_gbps = int(words[1])
    """ Apply configuration """
    ixia_api.set_state(State(ConfigState(config=config, state='set')))
    """ Start traffic """
    ixia_api.set_state(State(FlowTransmitState(state='start')))
    """ Wait for traffic to finish """
    time.sleep(duration_sec)

    while True:
        rows = ixia_api.get_flow_results(FlowRequest(flow_names=[flow_name]))
        if len(rows) == 1 and \
           rows[0]['name'] == flow_name and \
           rows[0]['transmit'] == 'stopped':
            """ Wait for counters to fully propagate """
            time.sleep(2)
            break
        else:
            time.sleep(1)
    """ Dump per-flow statistics """
    rows = ixia_api.get_flow_results(FlowRequest(flow_names=[flow_name]))
    """ Stop traffic """
    ixia_api.set_state(State(FlowTransmitState(state='stop')))
    """ Analyze traffic results """
    pytest_assert(
        len(rows) == 1 and rows[0]['name'] == flow_name,
        'Fail to get results of flow {}'.format(flow_name))

    row = rows[0]
    rx_frames = row['frames_rx']
    tx_frames = row['frames_tx']

    pytest_assert(
        rx_frames == tx_frames,
        'Unexpected packet losses (Tx: {}, Rx: {})'.format(
            tx_frames, rx_frames))

    tput_bps = port_speed_gbps * 1e9 * rate_percent / 100.0
    exp_rx_frames = tput_bps * duration_sec / 8 / pkt_size

    deviation_thresh = 0.05
    ratio = float(exp_rx_frames) / rx_frames
    deviation = abs(ratio - 1)

    pytest_assert(
        deviation <= deviation_thresh,
        'Expected / Actual # of pkts: {} / {}'.format(exp_rx_frames,
                                                      rx_frames))
Beispiel #12
0
def test_tgen(ixia_api,
              ixia_testbed_config,
              conn_graph_facts,
              fanout_graph_facts,
              rand_one_dut_lossless_prio,
              prio_dscp_map):
    """
    Test if we can use Tgen API generate traffic in a testbed

    Args:
        ixia_api (pytest fixture): IXIA session
        ixia_testbed_config (pytest fixture): testbed configuration information
        conn_graph_facts (pytest fixture): connection graph
        fanout_graph_facts (pytest fixture): fanout graph
        rand_one_dut_lossless_prio (str): name of lossless priority to test
        prio_dscp_map (pytest fixture): priority vs. DSCP map (key = priority)

    Returns:
        N/A
    """

    testbed_config, port_config_list = ixia_testbed_config
    dut_hostname, lossless_prio = rand_one_dut_lossless_prio.split('|')

    pytest_require(len(port_config_list) >= 2, "This test requires at least 2 ports")

    config = testbed_config
    config.flows = __gen_all_to_all_traffic(testbed_config=testbed_config,
                                            port_config_list=port_config_list,
                                            dut_hostname=dut_hostname,
                                            conn_data=conn_graph_facts,
                                            fanout_data=fanout_graph_facts,
                                            priority=int(lossless_prio),
                                            prio_dscp_map=prio_dscp_map)

    pkt_size = config.flows[0].size.fixed
    rate_percent = config.flows[0].rate.value
    duration_sec = config.flows[0].duration.seconds.seconds

    port_speed = config.layer1[0].speed
    words = port_speed.split('_')
    pytest_assert(len(words) == 3 and words[1].isdigit(),
                  'Fail to get port speed from {}'.format(port_speed))

    port_speed_gbps = int(words[1])

    """ Apply configuration """
    ixia_api.set_state(State(ConfigState(config=config, state='set')))

    """ Start traffic """
    ixia_api.set_state(State(FlowTransmitState(state='start')))

    """ Wait for traffic to finish """
    time.sleep(duration_sec)

    attempts = 0
    max_attempts = 20
    all_flow_names = [flow.name for flow in config.flows]

    while attempts < max_attempts:
        rows = ixia_api.get_flow_results(FlowRequest(flow_names=all_flow_names))

        """ If all the data 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(2)
            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 """
    rows = ixia_api.get_flow_results(FlowRequest(flow_names=all_flow_names))
    ixia_api.set_state(State(FlowTransmitState(state='stop')))

    """ Analyze traffic results """
    for row in rows:
        flow_name = row['name']
        rx_frames = row['frames_rx']
        tx_frames = row['frames_tx']

        pytest_assert(rx_frames == tx_frames,
                      'packet losses for {} (Tx: {}, Rx: {})'.\
                      format(flow_name, tx_frames, rx_frames))

        tput_bps = port_speed_gbps * 1e9 * rate_percent / 100.0
        exp_rx_frames = tput_bps * duration_sec / 8 / pkt_size

        deviation_thresh = 0.05
        ratio = float(exp_rx_frames) / rx_frames
        deviation = abs(ratio - 1)

        pytest_assert(deviation <= deviation_thresh,
                      'Expected / Actual # of pkts for flow {}: {} / {}'.\
                      format(flow_name, exp_rx_frames, rx_frames))
Beispiel #13
0
def test_pfc_watch_dog(api, duthost, pfc_watch_dog_config,
                       lossless_prio_dscp_map, pfcwd_params, serializer):
    """
    +-----------------+           +--------------+           +-----------------+       
    | Keysight Port 1 |------ et1 |   SONiC DUT  | et2 ------| Keysight Port 2 | 
    +-----------------+           +--------------+           +-----------------+ 
                                    et3
                                        |
                                        |
                                        |
                                +-----------------+
                                | Keysight Port 3 |
                                +-----------------+

    Configuration:
    1. Configure a single lossless priority value Pi (0 <= i <= 7).
    2. Enable watchdog with default storm detection time (400ms) and restoration time (2sec).
    3. On Keysight Chassis, create bi-directional traffic between Port 1 and Port 2
    with DSCP value mapped to lossless priority Pi
    a. Traffic 1->2
    b. Traffic 2->1
    4. Create bi-directional traffic between Port 2 and Port 3 with DSCP value mapped 
    to lossless priority Pi
    a. Traffic 2->3
    b. Traffic 3->2
    5. Create PFC pause storm: Persistent PFC pause frames from Keysight port 3 to et3 of DUT.
        Priority of the PFC pause frames should be same as that configured in DUT 
        and the inter-frame transmission interval should be lesser than per-frame pause duration.

    # Workflow
    1. At time TstartTraffic , start all the bi-directional lossless traffic items.
    2. At time TstartPause , start PFC pause storm.
    3. At time TstopPause , stop PFC pause storm. (TstopPause - TstartPause) should be larger than 
        PFC storm detection time to trigger PFC watchdog.
    4. At time TstopTraffic , stop lossless traffic items. Note that (TstopTraffic - TstopPause) should 
        be larger than PFC storm restoration time to re-enable PFC.
    5. Verify the following:
        --> PFC watchdog is triggered on the corresponding lossless priorities at DUT interface et3.
        --> 'Traffic 1->2' and 'Traffic 2->1' must not experience any packet loss in both directions. 
            Its throughput should be close to 50% of the line rate.
        --> For 'Traffic 2->3' and 'Traffic 3->2' , between TstartPause and TstopPause , 
            there should be almost 100% packet loss in both directions.
        --> After TstopPause , the traffic throughput should gradually increase and become 50% of line rate in both directions.
        --> There should not be any traffic loss after PFC storm restoration time has elapsed.
    """

    #######################################################################
    # DUT Configuration
    #######################################################################
    duthost.shell('sudo pfcwd stop')

    cmd = 'sudo pfcwd start --action drop ports all detection-time {} \
        --restoration-time {}'.format(pfcwd_params['storm_detection_time'],
                                      pfcwd_params['storm_restoration_time'])
    duthost.shell(cmd)

    duthost.shell('pfcwd show config')

    t_btwn_start_pause_and_stop_pause = pfcwd_params[
        't_stop_pause'] - pfcwd_params['t_start_pause']
    t_btwn_stop_pause_and_stop_traffic = pfcwd_params[
        't_stop_traffic'] - pfcwd_params['t_stop_pause']

    if pfcwd_params['storm_detection_time'] > (
            t_btwn_start_pause_and_stop_pause * 1000):
        pytest_assert(
            False,
            "Storm Detection period should be less than time between Start Pause and Stop Pause"
        )

    if pfcwd_params['storm_restoration_time'] > (
            t_btwn_stop_pause_and_stop_traffic * 1000):
        pytest_assert(
            False,
            "Storm Restoration period should be less than time between Stop Pause and Stop Traffic"
        )

    #######################################################################
    # TGEN Config and , Repeating TEST for Lossless priority 3 and 4
    #######################################################################
    pi_list = [prio for prio in lossless_prio_dscp_map]
    for pi in pi_list:
        config = pfc_watch_dog_config(pi)
        api.set_config(None)
        # print(serializer.json(config))
        api.set_config(config)

        ###############################################################################################
        # Start all flows
        # 1. check for no loss in the flows Traffic 1->2,Traffic 2->1
        # 2. check for loss in 'Traffic 2->3','Traffic 3->2' during pause storm
        ###############################################################################################

        api.set_flow_transmit(FlowTransmit(state='start'))

        # Sleeping till t_start_pause as t_start_pause is added as start_delay to the flow
        time.sleep(pfcwd_params['start_delay'] + pfcwd_params['t_start_pause'])

        t_to_stop_pause = datetime.datetime.now() + datetime.timedelta(
            seconds=t_btwn_start_pause_and_stop_pause)

        #Check for traffic observations for two timestamps in t_btwn_start_pause_and_stop_pause
        while True:
            if datetime.datetime.now() >= t_to_stop_pause:
                break
            else:
                time.sleep(t_btwn_start_pause_and_stop_pause / 2)
                # Get statistics
                test_stat = api.get_flow_results(FlowRequest())

                # Define indices
                tx_frame_rate_index = test_stat['columns'].index(
                    'frames_tx_rate')
                rx_frame_rate_index = test_stat['columns'].index(
                    'frames_rx_rate')
                name_index = test_stat['columns'].index('name')

                for rows in test_stat['rows']:
                    if rows[name_index] in ['Traffic 1->2', 'Traffic 2->1']:
                        tx_frame_rate = int(float(rows[tx_frame_rate_index]))
                        rx_frame_rate = int(float(rows[rx_frame_rate_index]))
                        logger.info(
                            "Tx Frame Rate,Rx Frame Rate of {} during Pause Storm: {},{}"
                            .format(rows[name_index], tx_frame_rate,
                                    rx_frame_rate))
                        if ((tx_frame_rate != rx_frame_rate)
                                or (rx_frame_rate == 0)):
                            pytest_assert(
                                False,
                                "Observing loss for %s during pause storm which is not expected"
                                % (rows[name_index]))
                    elif rows[name_index] in ['Traffic 2->3', 'Traffic 3->2']:
                        tx_frame_rate = int(float(rows[tx_frame_rate_index]))
                        rx_frame_rate = int(float(rows[rx_frame_rate_index]))
                        logger.info(
                            "Tx Frame Rate,Rx Frame Rate of {} during Pause Storm: {},{}"
                            .format(rows[name_index], tx_frame_rate,
                                    rx_frame_rate))
                        if ((tx_frame_rate == 0)
                                or (rx_frame_rate == tx_frame_rate)):
                            pytest_assert(
                                False,
                                "Expecting loss for %s during pause storm, which didn't occur"
                                % (rows[name_index]))

        ###############################################################################################
        # Stop Pause Storm
        # 1. check for no loss in the flows Traffic 1->2,Traffic 2->1
        # 2. check for no loss in 'Traffic 2->3','Traffic 3->2' after stopping Pause Storm
        ###############################################################################################
        # pause storm will stop once loop completes,the current time reaches t_stop_pause
        api.set_flow_transmit(
            FlowTransmit(state='stop', flow_names=['Pause Storm']))

        # Verification after pause storm is stopped
        t_to_stop_traffic = datetime.datetime.now() + datetime.timedelta(
            seconds=t_btwn_stop_pause_and_stop_traffic)

        #Check for traffic observations for two timestamps in t_btwn_stop_pause_and_stop_traffic
        while True:
            if datetime.datetime.now() >= t_to_stop_traffic:
                break
            else:
                time.sleep(t_btwn_stop_pause_and_stop_traffic / 2)
                # Get statistics
                test_stat = api.get_flow_results(FlowRequest())

                # Define indices
                tx_frame_rate_index = test_stat['columns'].index(
                    'frames_tx_rate')
                rx_frame_rate_index = test_stat['columns'].index(
                    'frames_rx_rate')
                name_index = test_stat['columns'].index('name')

                for rows in test_stat['rows']:
                    if rows[name_index] in ['Traffic 1->2', 'Traffic 2->1']:
                        tx_frame_rate = int(float(rows[tx_frame_rate_index]))
                        rx_frame_rate = int(float(rows[rx_frame_rate_index]))
                        logger.info(
                            "Tx Frame Rate,Rx Frame Rate of {} after stopping Pause Storm: {},{}"
                            .format(rows[name_index], tx_frame_rate,
                                    rx_frame_rate))
                        if ((tx_frame_rate != rx_frame_rate)
                                or (rx_frame_rate == 0)):
                            pytest_assert(
                                False,
                                "Observing loss for %s after pause storm stopped which is not expected"
                                % (rows[name_index]))
                    elif rows[name_index] in ['Traffic 2->3', 'Traffic 3->2']:
                        tx_frame_rate = int(float(rows[tx_frame_rate_index]))
                        rx_frame_rate = int(float(rows[rx_frame_rate_index]))
                        logger.info(
                            "Tx Frame Rate,Rx Frame Rate of {} after stopping Pause Storm: {},{}"
                            .format(rows[name_index], tx_frame_rate,
                                    rx_frame_rate))
                        if ((tx_frame_rate != rx_frame_rate)
                                or (rx_frame_rate == 0)):
                            pytest_assert(
                                False,
                                "Observing loss for %s after pause storm stopped which is not expected"
                                % (rows[name_index]))

        # stop all flows
        api.set_flow_transmit(FlowTransmit(state='stop'))