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]))
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_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'))