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
def test_snappi(snappi_api, snappi_testbed_config, conn_graph_facts, fanout_graph_facts, rand_one_dut_lossless_prio, prio_dscp_map): """ Test if we can use Snappi API generate traffic in a testbed Args: snappi_api (pytest fixture): Snappi session snappi_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 = snappi_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 = __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.percentage duration_sec = config.flows[0].duration.fixed_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 """ snappi_api.set_config(config) # """Wait for Arp""" wait_for_arp(snappi_api, max_attempts=10, poll_interval_sec=2) # """ Start traffic """ ts = snappi_api.transmit_state() ts.state = ts.START snappi_api.set_transmit_state(ts) # """ 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: request = snappi_api.metrics_request() request.flow.flow_names = all_flow_names rows = snappi_api.get_metrics(request).flow_metrics """ 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 """ request = snappi_api.metrics_request() request.flow.flow_names = all_flow_names rows = snappi_api.get_metrics(request).flow_metrics ts = snappi_api.transmit_state() ts.state = ts.STOP snappi_api.set_transmit_state(ts) """ 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))
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): SNAPPI 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_config(config) logger.info('Wait for Arp to Resolve ...') wait_for_arp(api, max_attempts=10, poll_interval_sec=2) cs = api.capture_state() cs.port_names = [capture_port_name] cs.state = cs.START api.set_capture_state(cs) logger.info('Starting transmit on all flows ...') ts = api.transmit_state() ts.state = ts.START api.set_transmit_state(ts) time.sleep(exp_dur_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 captured packets """ request = api.capture_request() request.port_name = capture_port_name pcap_bytes = api.get_capture(request) with open(pcap_file_name, 'wb') as fid: fid.write(pcap_bytes.getvalue()) """ Stop all the flows """ logger.info('Stop transmit on all flows ...') ts = api.transmit_state() ts.state = ts.STOP api.set_transmit_state(ts)
def __run_traffic(api, config, data_flow_names, all_flow_names, exp_dur_sec): """ Run traffic and dump per-flow statistics Args: api (obj): snappi 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_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(exp_dur_sec) attempts = 0 max_attempts = 20 while attempts < max_attempts: request = api.metrics_request() request.flow.flow_names = data_flow_names rows = api.get_metrics(request).flow_metrics """ 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(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