def __gen_all_to_all_traffic(testbed_config, port_config_list, dut_hostname, conn_data, fanout_data, priority, prio_dscp_map): flows = [] rate_percent = 100 / (len(port_config_list) - 1) duration_sec = 2 pkt_size = 1024 tx_port_id_list, rx_port_id_list = select_ports(port_config_list=port_config_list, pattern="all to all", rx_port_id=0) for tx_port_id in tx_port_id_list: for rx_port_id in rx_port_id_list: if tx_port_id == rx_port_id: continue tx_port_config = next((x for x in port_config_list if x.id == tx_port_id), None) rx_port_config = next((x for x in port_config_list if x.id == rx_port_id), None) tx_mac = tx_port_config.mac if tx_port_config.gateway == rx_port_config.gateway and \ tx_port_config.prefix_len == rx_port_config.prefix_len: """ If soruce and destination port are in the same subnet """ rx_mac = rx_port_config.mac else: rx_mac = tx_port_config.gateway_mac data_endpoint = PortTxRx(tx_port_name=testbed_config.ports[tx_port_id].name, rx_port_name=testbed_config.ports[rx_port_id].name) eth_hdr = EthernetHeader(src=FieldPattern(tx_mac), dst=FieldPattern(rx_mac), pfc_queue=FieldPattern([priority])) ip_prio = Priority(Dscp(phb=FieldPattern(choice=prio_dscp_map[priority]), ecn=FieldPattern(choice=Dscp.ECN_CAPABLE_TRANSPORT_1))) ipv4_hdr = Ipv4Header(src=FieldPattern(tx_port_config.ip), dst=FieldPattern(rx_port_config.ip), priority=ip_prio) flow_name = "Flow {} -> {}".format(tx_port_id, rx_port_id) flow = Flow( name=flow_name, tx_rx=TxRx(data_endpoint), packet=[Header(choice=eth_hdr), Header(choice=ipv4_hdr)], size=Size(pkt_size), rate=Rate('line', rate_percent), duration=Duration(FixedSeconds(seconds=duration_sec)) ) flows.append(flow) return flows
def __gen_traffic(testbed_config, port_config_list, port_id, pause_flow_name, pause_flow_dur_sec, data_flow_name_list, data_flow_delay_sec_list, data_flow_dur_sec_list, data_pkt_size, prio_list, prio_dscp_map): """ Generate configurations of flows, including data flows and pause storm. Args: testbed_config (obj): testbed L1/L2/L3 configuration port_config_list (list): list of port configuration port_id (int): ID of DUT port to test. pause_flow_name (str): name of pause storm pause_flow_dur_sec (float): duration of pause storm in second data_flow_name_list (list): list of data flow names data_flow_delay_sec_list (list): list of data flow start delays in second data_flow_dur_sec_list (list): list of data flow durations in second data_pkt_size (int): size of data packets in byte prio_list (list): priorities of data flows and pause storm prio_dscp_map (dict): Priority vs. DSCP map (key = priority). Returns: flows configurations (list): the list should have configurations of len(prio_list) * 2 data flows, and a pause storm. """ result = list() rx_port_id = port_id tx_port_id_list, rx_port_id_list = select_ports( port_config_list=port_config_list, pattern="many to one", rx_port_id=rx_port_id) pytest_assert(len(tx_port_id_list) > 0, "Cannot find any TX ports") tx_port_id = select_tx_port(tx_port_id_list=tx_port_id_list, rx_port_id=rx_port_id) pytest_assert(tx_port_id is not None, "Cannot find a suitable TX port") tx_port_config = next((x for x in port_config_list if x.id == tx_port_id), None) rx_port_config = next((x for x in port_config_list if x.id == rx_port_id), None) tx_mac = tx_port_config.mac if tx_port_config.gateway == rx_port_config.gateway and \ tx_port_config.prefix_len == rx_port_config.prefix_len: """ If soruce and destination port are in the same subnet """ rx_mac = rx_port_config.mac else: rx_mac = tx_port_config.gateway_mac """ PFC storm """ pause_time = [] for x in range(8): if x in prio_list: pause_time.append('ffff') else: pause_time.append('0000') vector = pfc_class_enable_vector(prio_list) pause_pkt = Header( PfcPause( dst=FieldPattern(choice='01:80:C2:00:00:01'), src=FieldPattern(choice='00:00:fa:ce:fa:ce'), class_enable_vector=FieldPattern(choice=vector), pause_class_0=FieldPattern(choice=pause_time[0]), pause_class_1=FieldPattern(choice=pause_time[1]), pause_class_2=FieldPattern(choice=pause_time[2]), pause_class_3=FieldPattern(choice=pause_time[3]), pause_class_4=FieldPattern(choice=pause_time[4]), pause_class_5=FieldPattern(choice=pause_time[5]), pause_class_6=FieldPattern(choice=pause_time[6]), pause_class_7=FieldPattern(choice=pause_time[7]), )) pause_endpoint = PortTxRx( tx_port_name=testbed_config.ports[rx_port_id].name, rx_port_name=testbed_config.ports[tx_port_id].name) speed_str = testbed_config.layer1[0].speed speed_gbps = int(speed_str.split('_')[1]) pause_dur = 65535 * 64 * 8.0 / (speed_gbps * 1e9) pps = int(2 / pause_dur) pause_pkt_cnt = pps * pause_flow_dur_sec pause_flow = Flow(name=pause_flow_name, tx_rx=TxRx(pause_endpoint), packet=[pause_pkt], size=Size(64), rate=Rate('pps', value=pps), duration=Duration( FixedPackets(packets=pause_pkt_cnt, delay=0))) result.append(pause_flow) data_endpoint = PortTxRx( tx_port_name=testbed_config.ports[tx_port_id].name, rx_port_name=testbed_config.ports[rx_port_id].name) data_flow_rate_percent = int(100 / len(prio_list)) """ For each data flow """ for i in range(len(data_flow_name_list)): """ For each priority """ for prio in prio_list: eth_hdr = EthernetHeader(src=FieldPattern(tx_mac), dst=FieldPattern(rx_mac), pfc_queue=FieldPattern([prio])) ip_prio = Priority( Dscp(phb=FieldPattern(choice=prio_dscp_map[prio]), ecn=FieldPattern(choice=Dscp.ECN_CAPABLE_TRANSPORT_1))) ipv4_hdr = Ipv4Header(src=FieldPattern(tx_port_config.ip), dst=FieldPattern(rx_port_config.ip), priority=ip_prio) data_flow = Flow( name='{} Prio {}'.format(data_flow_name_list[i], prio), tx_rx=TxRx(data_endpoint), packet=[Header(choice=eth_hdr), Header(choice=ipv4_hdr)], size=Size(data_pkt_size), rate=Rate('line', data_flow_rate_percent), duration=Duration( FixedSeconds(seconds=data_flow_dur_sec_list[i], delay=sec_to_nanosec( data_flow_delay_sec_list[i]), delay_unit='nanoseconds'))) result.append(data_flow) return result
def __gen_traffic(testbed_config, port_config_list, port_id, duthost, pause_flow_name, global_pause, pause_prio_list, test_flow_name, test_flow_prio_list, test_flow_rate_percent, bg_flow_name, bg_flow_prio_list, bg_flow_rate_percent, data_flow_dur_sec, data_flow_delay_sec, data_pkt_size, prio_dscp_map): """ Generate configurations of flows, including test flows, background flows and pause storm. Test flows and background flows are also known as data flows. Args: testbed_config (obj): testbed L1/L2/L3 configuration port_config_list (list): list of port configuration port_id (int): ID of DUT port to test duthost (Ansible host instance): device under test pause_flow_name (str): name of pause storm global_pause (bool): if pause frame is IEEE 802.3X pause pause_prio_list (list): priorities to pause for pause frames test_flow_name (str): name of test flows test_prio_list (list): priorities of test flows test_flow_rate_percent (int): rate percentage for each test flow bg_flow_name (str): name of background flows bg_prio_list (list): priorities of background flows bg_flow_rate_percent (int): rate percentage for each background flow data_flow_dur_sec (int): duration of data flows in second data_flow_delay_sec (int): start delay of data flows in second data_pkt_size (int): packet size of data flows in byte prio_dscp_map (dict): Priority vs. DSCP map (key = priority). Returns: flows configurations (list): the list should have configurations of len(test_flow_prio_list) test flow, len(bg_flow_prio_list) background flows and a pause storm. """ result = list() rx_port_id = port_id tx_port_id_list, rx_port_id_list = select_ports(port_config_list=port_config_list, duthost=duthost, pattern="many to one", rx_port_id=rx_port_id) pytest_assert(len(tx_port_id_list) > 0, "Cannot find any TX ports") tx_port_id = select_tx_port(tx_port_id_list=tx_port_id_list, rx_port_id=rx_port_id) pytest_assert(tx_port_id is not None, "Cannot find a suitable TX port") tx_port_config = next((x for x in port_config_list if x.id == tx_port_id), None) rx_port_config = next((x for x in port_config_list if x.id == rx_port_id), None) tx_mac = tx_port_config.mac if tx_port_config.gateway == rx_port_config.gateway and \ tx_port_config.prefix_len == rx_port_config.prefix_len: """ If soruce and destination port are in the same subnet """ rx_mac = rx_port_config.mac else: rx_mac = tx_port_config.gateway_mac data_endpoint = PortTxRx(tx_port_name=testbed_config.ports[tx_port_id].name, rx_port_name=testbed_config.ports[rx_port_id].name) data_flow_delay_nanosec = sec_to_nanosec(data_flow_delay_sec) """ Test flows """ for prio in test_flow_prio_list: eth_hdr = EthernetHeader(src=FieldPattern(tx_mac), dst=FieldPattern(rx_mac), pfc_queue=FieldPattern([prio])) ip_prio = Priority(Dscp(phb=FieldPattern(choice=prio_dscp_map[prio]), ecn=FieldPattern(choice=Dscp.ECN_CAPABLE_TRANSPORT_1))) ipv4_hdr = Ipv4Header(src=FieldPattern(tx_port_config.ip), dst=FieldPattern(rx_port_config.ip), priority=ip_prio) test_flow = Flow( name='{} Prio {}'.format(test_flow_name, prio), tx_rx=TxRx(data_endpoint), packet=[Header(choice=eth_hdr), Header(choice=ipv4_hdr)], size=Size(data_pkt_size), rate=Rate('line', test_flow_rate_percent), duration=Duration(FixedSeconds(seconds=data_flow_dur_sec, delay=data_flow_delay_nanosec, delay_unit='nanoseconds')) ) result.append(test_flow) """ Background flows """ for prio in bg_flow_prio_list: eth_hdr = EthernetHeader(src=FieldPattern(tx_mac), dst=FieldPattern(rx_mac), pfc_queue=FieldPattern([prio])) ip_prio = Priority(Dscp(phb=FieldPattern(choice=prio_dscp_map[prio]), ecn=FieldPattern(choice=Dscp.ECN_CAPABLE_TRANSPORT_1))) ipv4_hdr = Ipv4Header(src=FieldPattern(tx_port_config.ip), dst=FieldPattern(rx_port_config.ip), priority=ip_prio) bg_flow = Flow( name='{} Prio {}'.format(bg_flow_name, prio), tx_rx=TxRx(data_endpoint), packet=[Header(choice=eth_hdr), Header(choice=ipv4_hdr)], size=Size(data_pkt_size), rate=Rate('line', bg_flow_rate_percent), duration=Duration(FixedSeconds(seconds=data_flow_dur_sec, delay=data_flow_delay_nanosec, delay_unit='nanoseconds')) ) result.append(bg_flow) """ Pause storm """ if global_pause: pause_pkt = Header(EthernetPause( dst=FieldPattern(choice='01:80:C2:00:00:01'), src=FieldPattern(choice='00:00:fa:ce:fa:ce') )) else: pause_time = [] for x in range(8): if x in pause_prio_list: pause_time.append('ffff') else: pause_time.append('0000') vector = pfc_class_enable_vector(pause_prio_list) pause_pkt = Header(PfcPause( dst=FieldPattern(choice='01:80:C2:00:00:01'), src=FieldPattern(choice='00:00:fa:ce:fa:ce'), class_enable_vector=FieldPattern(choice=vector), pause_class_0=FieldPattern(choice=pause_time[0]), pause_class_1=FieldPattern(choice=pause_time[1]), pause_class_2=FieldPattern(choice=pause_time[2]), pause_class_3=FieldPattern(choice=pause_time[3]), pause_class_4=FieldPattern(choice=pause_time[4]), pause_class_5=FieldPattern(choice=pause_time[5]), pause_class_6=FieldPattern(choice=pause_time[6]), pause_class_7=FieldPattern(choice=pause_time[7]), )) """ Pause frames are sent from the RX port """ pause_endpoint = PortTxRx(tx_port_name=testbed_config.ports[rx_port_id].name, rx_port_name=testbed_config.ports[tx_port_id].name) speed_str = testbed_config.layer1[0].speed speed_gbps = int(speed_str.split('_')[1]) pause_dur = 65535 * 64 * 8.0 / (speed_gbps * 1e9) pps = int(2 / pause_dur) pause_flow = Flow( name=pause_flow_name, tx_rx=TxRx(pause_endpoint), packet=[pause_pkt], size=Size(64), rate=Rate('pps', value=pps), duration=Duration(Continuous(delay=0, delay_unit='nanoseconds')) ) result.append(pause_flow) return result
def __gen_traffic(testbed_config, port_config_list, port_id, pause_flow_name, data_flow_name, prio, data_pkt_size, data_pkt_cnt, data_flow_delay_sec, exp_dur_sec, prio_dscp_map): """ Generate configurations of flows, including a data flow and a PFC pause storm. Args: testbed_config (obj): testbed L1/L2/L3 configuration port_config_list (list): list of port configuration port_id (int): ID of DUT port to test pause_flow_name (str): name of the pause storm data_flow_name (str): name of the data flow prio (int): priority of the data flow and PFC pause storm data_pkt_size (int): packet size of the data flow in byte data_pkt_cnt (int): # of packets of the data flow data_flow_delay_sec (float): start delay of the data flow in second exp_dur_sec (float): experiment duration in second prio_dscp_map (dict): Priority vs. DSCP map (key = priority). Returns: Configurations of the data flow and the PFC pause storm (list) """ result = list() rx_port_id = port_id tx_port_id_list, rx_port_id_list = select_ports( port_config_list=port_config_list, pattern="many to one", rx_port_id=rx_port_id) pytest_assert(len(tx_port_id_list) > 0, "Cannot find any TX ports") tx_port_id = select_tx_port(tx_port_id_list=tx_port_id_list, rx_port_id=rx_port_id) pytest_assert(tx_port_id is not None, "Cannot find a suitable TX port") tx_port_config = next((x for x in port_config_list if x.id == tx_port_id), None) rx_port_config = next((x for x in port_config_list if x.id == rx_port_id), None) tx_mac = tx_port_config.mac if tx_port_config.gateway == rx_port_config.gateway and \ tx_port_config.prefix_len == rx_port_config.prefix_len: """ If soruce and destination port are in the same subnet """ rx_mac = rx_port_config.mac else: rx_mac = tx_port_config.gateway_mac data_endpoint = PortTxRx( tx_port_name=testbed_config.ports[tx_port_id].name, rx_port_name=testbed_config.ports[rx_port_id].name) data_flow_delay_nanosec = sec_to_nanosec(data_flow_delay_sec) eth_hdr = EthernetHeader(src=FieldPattern(tx_mac), dst=FieldPattern(rx_mac), pfc_queue=FieldPattern([prio])) ip_prio = Priority( Dscp(phb=FieldPattern(choice=prio_dscp_map[prio]), ecn=FieldPattern(choice=Dscp.ECN_CAPABLE_TRANSPORT_1))) ipv4_hdr = Ipv4Header(src=FieldPattern(tx_port_config.ip), dst=FieldPattern(rx_port_config.ip), priority=ip_prio) data_flow = Flow(name=data_flow_name, tx_rx=TxRx(data_endpoint), packet=[Header(choice=eth_hdr), Header(choice=ipv4_hdr)], size=Size(data_pkt_size), rate=Rate('line', 100), duration=Duration( FixedPackets(packets=data_pkt_cnt, delay=data_flow_delay_nanosec, delay_unit='nanoseconds'))) result.append(data_flow) """ PFC Pause Storm """ pause_time = [] for x in range(8): if x == prio: pause_time.append('ffff') else: pause_time.append('0000') vector = pfc_class_enable_vector([prio]) pause_pkt = Header( PfcPause( dst=FieldPattern(choice='01:80:C2:00:00:01'), src=FieldPattern(choice='00:00:fa:ce:fa:ce'), class_enable_vector=FieldPattern(choice=vector), pause_class_0=FieldPattern(choice=pause_time[0]), pause_class_1=FieldPattern(choice=pause_time[1]), pause_class_2=FieldPattern(choice=pause_time[2]), pause_class_3=FieldPattern(choice=pause_time[3]), pause_class_4=FieldPattern(choice=pause_time[4]), pause_class_5=FieldPattern(choice=pause_time[5]), pause_class_6=FieldPattern(choice=pause_time[6]), pause_class_7=FieldPattern(choice=pause_time[7]), )) """ Pause frames are sent from the RX port """ pause_endpoint = PortTxRx( tx_port_name=testbed_config.ports[rx_port_id].name, rx_port_name=testbed_config.ports[tx_port_id].name) speed_str = testbed_config.layer1[0].speed speed_gbps = int(speed_str.split('_')[1]) pause_dur = 65535 * 64 * 8.0 / (speed_gbps * 1e9) pps = int(2 / pause_dur) pause_flow = Flow(name=pause_flow_name, tx_rx=TxRx(pause_endpoint), packet=[pause_pkt], size=Size(64), rate=Rate('pps', value=pps), duration=Duration( FixedSeconds(seconds=exp_dur_sec, delay=0, delay_unit='nanoseconds'))) result.append(pause_flow) return result
def __gen_traffic(testbed_config, port_config_list, port_id, data_flow_name, data_flow_dur_sec, data_pkt_size, prio_list, prio_dscp_map): """ Generate configurations of flows Args: testbed_config (obj): testbed L1/L2/L3 configuration port_config_list (list): list of port configuration port_id (int): ID of DUT port to test. data_flow_name (str): data flow name data_flow_dur_sec (int): duration of data flows in second data_pkt_size (int): size of data packets in byte prio_list (list): priorities of data flows prio_dscp_map (dict): Priority vs. DSCP map (key = priority). Returns: flows configurations (list): the list should have configurations of len(prio_list) data flows """ result = list() rx_port_id = port_id tx_port_id_list, rx_port_id_list = select_ports( port_config_list=port_config_list, pattern="many to one", rx_port_id=rx_port_id) pytest_assert(len(tx_port_id_list) > 0, "Cannot find any TX ports") tx_port_id = select_tx_port(tx_port_id_list=tx_port_id_list, rx_port_id=rx_port_id) pytest_assert(tx_port_id is not None, "Cannot find a suitable TX port") tx_port_config = next((x for x in port_config_list if x.id == tx_port_id), None) rx_port_config = next((x for x in port_config_list if x.id == rx_port_id), None) tx_mac = tx_port_config.mac if tx_port_config.gateway == rx_port_config.gateway and \ tx_port_config.prefix_len == rx_port_config.prefix_len: """ If soruce and destination port are in the same subnet """ rx_mac = rx_port_config.mac else: rx_mac = tx_port_config.gateway_mac data_endpoint = PortTxRx( tx_port_name=testbed_config.ports[tx_port_id].name, rx_port_name=testbed_config.ports[rx_port_id].name) data_flow_rate_percent = int(100 / len(prio_list)) """ For each priority """ for prio in prio_list: eth_hdr = EthernetHeader(src=FieldPattern(tx_mac), dst=FieldPattern(rx_mac), pfc_queue=FieldPattern([prio])) ip_prio = Priority( Dscp(phb=FieldPattern(choice=prio_dscp_map[prio]), ecn=FieldPattern(choice=Dscp.ECN_CAPABLE_TRANSPORT_1))) ipv4_hdr = Ipv4Header(src=FieldPattern(tx_port_config.ip), dst=FieldPattern(rx_port_config.ip), priority=ip_prio) data_flow = Flow( name='{} Prio {}'.format(data_flow_name, prio), tx_rx=TxRx(data_endpoint), packet=[Header(choice=eth_hdr), Header(choice=ipv4_hdr)], size=Size(data_pkt_size), rate=Rate('line', data_flow_rate_percent), duration=Duration(FixedSeconds(seconds=data_flow_dur_sec))) result.append(data_flow) return result
def __gen_traffic(testbed_config, port_config_list, port_id, pause_flow_name, pause_prio_list, test_flow_name, test_flow_prio_list, test_flow_rate_percent, bg_flow_name, bg_flow_prio_list, bg_flow_rate_percent, data_flow_dur_sec, pfc_storm_dur_sec, data_pkt_size, prio_dscp_map, traffic_pattern): """ Generate configurations of flows under all to all traffic pattern, including test flows, background flows and pause storm. Test flows and background flows are also known as data flows. Args: testbed_config (obj): testbed L1/L2/L3 configuration port_config_list (list): list of port configuration port_id (int): ID of DUT port to test. pause_flow_name (str): name of pause storm pause_prio_list (list): priorities to pause for PFC frames test_flow_name (str): name prefix of test flows test_prio_list (list): priorities of test flows test_flow_rate_percent (int): rate percentage for each test flow bg_flow_name (str): name prefix of background flows bg_prio_list (list): priorities of background flows bg_flow_rate_percent (int): rate percentage for each background flow data_flow_dur_sec (int): duration of data flows in second pfc_storm_dur_sec (float): duration of the pause storm in second data_pkt_size (int): packet size of data flows in byte prio_dscp_map (dict): Priority vs. DSCP map (key = priority). traffic_pattern (str): traffic pattern, "many to one" or "all to all" Returns: flows configurations (list) """ result = list() """ Generate a PFC pause storm """ pause_port_id = port_id pause_flow = __gen_pause_flow(testbed_config=testbed_config, port_config_list=port_config_list, src_port_id=pause_port_id, flow_name=pause_flow_name, pause_prio_list=pause_prio_list, flow_dur_sec=pfc_storm_dur_sec) result.append(pause_flow) tx_port_id_list, rx_port_id_list = select_ports( port_config_list=port_config_list, pattern=traffic_pattern, rx_port_id=port_id) test_flows = __gen_data_flows(testbed_config=testbed_config, port_config_list=port_config_list, src_port_id_list=tx_port_id_list, dst_port_id_list=rx_port_id_list, flow_name_prefix=TEST_FLOW_NAME, flow_prio_list=test_flow_prio_list, flow_rate_percent=test_flow_rate_percent, flow_dur_sec=data_flow_dur_sec, data_pkt_size=data_pkt_size, prio_dscp_map=prio_dscp_map) result.extend(test_flows) bg_flows = __gen_data_flows(testbed_config=testbed_config, port_config_list=port_config_list, src_port_id_list=tx_port_id_list, dst_port_id_list=rx_port_id_list, flow_name_prefix=BG_FLOW_NAME, flow_prio_list=bg_flow_prio_list, flow_rate_percent=bg_flow_rate_percent, flow_dur_sec=data_flow_dur_sec, data_pkt_size=data_pkt_size, prio_dscp_map=prio_dscp_map) result.extend(bg_flows) return result