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 #2
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 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 #5
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'))