def __gen_all_to_all_traffic(testbed_config, port_config_list, dut_hostname, conn_data, fanout_data, priority, prio_dscp_map): 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 tx_port_name = testbed_config.ports[tx_port_id].name rx_port_name = testbed_config.ports[rx_port_id].name flow = testbed_config.flows.flow( name="Flow {} -> {}".format(tx_port_id, rx_port_id))[-1] flow.tx_rx.port.tx_name = tx_port_name flow.tx_rx.port.rx_name = rx_port_name eth, ipv4 = flow.packet.ethernet().ipv4() eth.src.value = tx_mac eth.dst.value = rx_mac eth.pfc_queue.value = priority ipv4.src.value = tx_port_config.ip ipv4.dst.value = rx_port_config.ip ipv4.priority.choice = ipv4.priority.DSCP ipv4.priority.dscp.phb.values = prio_dscp_map[priority] ipv4.priority.dscp.ecn.value = ( ipv4.priority.dscp.ecn.CAPABLE_TRANSPORT_1) flow.size.fixed = pkt_size flow.rate.percentage = rate_percent flow.duration.fixed_seconds.seconds = duration_sec flow.metrics.enable = True flow.metrics.loss = True return testbed_config
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: N/A """ 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 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) data_flow = testbed_config.flows.flow(name=data_flow_name)[-1] data_flow.tx_rx.port.tx_name = tx_port_name data_flow.tx_rx.port.rx_name = rx_port_name eth, ipv4 = data_flow.packet.ethernet().ipv4() eth.src.value = tx_mac eth.dst.value = rx_mac eth.pfc_queue.value = prio ipv4.src.value = tx_port_config.ip ipv4.dst.value = rx_port_config.ip ipv4.priority.choice = ipv4.priority.DSCP ipv4.priority.dscp.phb.values = prio_dscp_map[prio] ipv4.priority.dscp.ecn.value = ( ipv4.priority.dscp.ecn.CAPABLE_TRANSPORT_1) data_flow.size.fixed = data_pkt_size data_flow.rate.percentage = 100 data_flow.duration.fixed_packets.packets = data_pkt_cnt data_flow.duration.fixed_packets.delay.nanoseconds = int(data_flow_delay_nanosec) data_flow.metrics.enable = True data_flow.metrics.loss = True """ PFC Pause Storm """ pause_time = [] for x in range(8): if x == prio: pause_time.append(int('ffff', 16)) else: pause_time.append(int('0000', 16)) vector = pfc_class_enable_vector([prio]) pause_flow = testbed_config.flows.flow(name=pause_flow_name)[-1] """ Pause frames are sent from the RX port """ pause_flow.tx_rx.port.tx_name = testbed_config.ports[rx_port_id].name pause_flow.tx_rx.port.rx_name = testbed_config.ports[tx_port_id].name pause_pkt = pause_flow.packet.pfcpause()[-1] pause_pkt.src.value = '00:00:fa:ce:fa:ce' pause_pkt.dst.value = '01:80:C2:00:00:01' pause_pkt.class_enable_vector.value = vector pause_pkt.pause_class_0.value = pause_time[0] pause_pkt.pause_class_1.value = pause_time[1] pause_pkt.pause_class_2.value = pause_time[2] pause_pkt.pause_class_3.value = pause_time[3] pause_pkt.pause_class_4.value = pause_time[4] pause_pkt.pause_class_5.value = pause_time[5] pause_pkt.pause_class_6.value = pause_time[6] pause_pkt.pause_class_7.value = pause_time[7] 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.rate.pps = pps pause_flow.size.fixed = 64 pause_flow.duration.fixed_seconds.seconds = exp_dur_sec pause_flow.duration.fixed_seconds.delay.nanoseconds = 0 pause_flow.metrics.enable = True pause_flow.metrics.loss = True
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: N/A """ 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 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: data_flow = testbed_config.flows.flow( name='{} Prio {}'.format(data_flow_name, prio))[-1] data_flow.tx_rx.port.tx_name = tx_port_name data_flow.tx_rx.port.rx_name = rx_port_name eth, ipv4 = data_flow.packet.ethernet().ipv4() eth.src.value = tx_mac eth.dst.value = rx_mac eth.pfc_queue.value = prio ipv4.src.value = tx_port_config.ip ipv4.dst.value = rx_port_config.ip ipv4.priority.choice = ipv4.priority.DSCP ipv4.priority.dscp.phb.values = prio_dscp_map[prio] ipv4.priority.dscp.ecn.value = ( ipv4.priority.dscp.ecn.CAPABLE_TRANSPORT_1) data_flow.size.fixed = data_pkt_size data_flow.rate.percentage = data_flow_rate_percent data_flow.duration.fixed_seconds.seconds = data_flow_dur_sec data_flow.metrics.enable = True data_flow.metrics.loss = True
def __gen_traffic(testbed_config, port_config_list, port_id, pause_flow_prefix, pause_flow_count, pause_flow_dur_sec, pause_flow_gap_sec, data_flow_prefix, data_flow_dur_sec, data_pkt_size, prio_list, prio_dscp_map): """ Generate flow configurations 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_prefix (str): prefix of names of PFC pause storms pause_flow_count (int): number of PFC pause storms pause_flow_dur_sec (float): duration of each PFC pause storm pause_flow_gap_sec (float): gap between PFC pause storms data_flow_prefix (str): prefix of names of data flows data_flow_dur_sec (int): duration of all the data flows data_pkt_size (int): data packet size in bytes prio_list (list): priorities to generate PFC storms and data traffic prio_dscp_map (dict): Priority vs. DSCP map (key = priority). Returns: N/A """ 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 """ Generate long-lived data flows, one for each priority """ data_flow_rate_percent = int(100 / len(prio_list)) tx_port_name = testbed_config.ports[tx_port_id].name rx_port_name = testbed_config.ports[rx_port_id].name for prio in prio_list: data_flow = testbed_config.flows.flow( name='{} Prio {}'.format(data_flow_prefix, prio))[-1] data_flow.tx_rx.port.tx_name = tx_port_name data_flow.tx_rx.port.rx_name = rx_port_name eth, ipv4 = data_flow.packet.ethernet().ipv4() eth.src.value = tx_mac eth.dst.value = rx_mac eth.pfc_queue.value = prio ipv4.src.value = tx_port_config.ip ipv4.dst.value = rx_port_config.ip ipv4.priority.choice = ipv4.priority.DSCP ipv4.priority.dscp.phb.values = prio_dscp_map[prio] ipv4.priority.dscp.ecn.value = ( ipv4.priority.dscp.ecn.CAPABLE_TRANSPORT_1) data_flow.size.fixed = data_pkt_size data_flow.rate.percentage = data_flow_rate_percent data_flow.duration.fixed_seconds.seconds = data_flow_dur_sec data_flow.duration.fixed_seconds.delay.nanoseconds = 0 data_flow.metrics.enable = True data_flow.metrics.loss = True """ Generate a series of PFC storms """ speed_str = testbed_config.layer1[0].speed speed_gbps = int(speed_str.split('_')[1]) pause_dur = 65535 * 64 * 8.0 / (speed_gbps * 1e9) pause_pps = int(2 / pause_dur) pause_pkt_cnt = pause_pps * pause_flow_dur_sec for id in range(pause_flow_count): pause_time = [] for x in range(8): if x in prio_list: pause_time.append(int('ffff', 16)) else: pause_time.append(int('0000', 16)) vector = pfc_class_enable_vector(prio_list) pause_flow = testbed_config.flows.flow( name="{} {}".format(pause_flow_prefix, id))[-1] pause_flow.tx_rx.port.tx_name = testbed_config.ports[rx_port_id].name pause_flow.tx_rx.port.rx_name = testbed_config.ports[tx_port_id].name pause_pkt = pause_flow.packet.pfcpause()[-1] pause_pkt.src.value = '00:00:fa:ce:fa:ce' pause_pkt.dst.value = '01:80:C2:00:00:01' pause_pkt.class_enable_vector.value = vector pause_pkt.pause_class_0.value = pause_time[0] pause_pkt.pause_class_1.value = pause_time[1] pause_pkt.pause_class_2.value = pause_time[2] pause_pkt.pause_class_3.value = pause_time[3] pause_pkt.pause_class_4.value = pause_time[4] pause_pkt.pause_class_5.value = pause_time[5] pause_pkt.pause_class_6.value = pause_time[6] pause_pkt.pause_class_7.value = pause_time[7] pause_flow_start_time = id * (pause_flow_dur_sec + pause_flow_gap_sec) pause_flow.rate.pps = pause_pps pause_flow.size.fixed = 64 pause_flow.duration.fixed_packets.packets = int(pause_pkt_cnt) pause_flow.duration.fixed_packets.delay.nanoseconds = int( sec_to_nanosec(pause_flow_start_time)) pause_flow.metrics.enable = True pause_flow.metrics.loss = True
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: N/A """ """ Generate a PFC pause storm """ pause_port_id = port_id __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) tx_port_id_list, rx_port_id_list = select_ports( port_config_list=port_config_list, pattern=traffic_pattern, rx_port_id=port_id) __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) __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)
def __gen_traffic(testbed_config, port_config_list, port_id, 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 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. """ 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 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: test_flow = testbed_config.flows.flow( name='{} Prio {}'.format(test_flow_name, prio))[-1] test_flow.tx_rx.port.tx_name = tx_port_name test_flow.tx_rx.port.rx_name = rx_port_name eth, ipv4 = test_flow.packet.ethernet().ipv4() eth.src.value = tx_mac eth.dst.value = rx_mac eth.pfc_queue.value = prio ipv4.src.value = tx_port_config.ip ipv4.dst.value = rx_port_config.ip ipv4.priority.choice = ipv4.priority.DSCP ipv4.priority.dscp.phb.values = prio_dscp_map[prio] ipv4.priority.dscp.ecn.value = ( ipv4.priority.dscp.ecn.CAPABLE_TRANSPORT_1) test_flow.size.fixed = data_pkt_size test_flow.rate.percentage = test_flow_rate_percent test_flow.duration.fixed_seconds.seconds = data_flow_dur_sec test_flow.duration.fixed_seconds.delay.nanoseconds = int( data_flow_delay_nanosec) test_flow.metrics.enable = True test_flow.metrics.loss = True """ Background flows """ for prio in bg_flow_prio_list: bg_flow = testbed_config.flows.flow( name='{} Prio {}'.format(bg_flow_name, prio))[-1] bg_flow.tx_rx.port.tx_name = tx_port_name bg_flow.tx_rx.port.rx_name = rx_port_name eth, ipv4 = bg_flow.packet.ethernet().ipv4() eth.src.value = tx_mac eth.dst.value = rx_mac eth.pfc_queue.value = prio ipv4.src.value = tx_port_config.ip ipv4.dst.value = rx_port_config.ip ipv4.priority.choice = ipv4.priority.DSCP ipv4.priority.dscp.phb.values = prio_dscp_map[prio] ipv4.priority.dscp.ecn.value = ( ipv4.priority.dscp.ecn.CAPABLE_TRANSPORT_1) bg_flow.size.fixed = data_pkt_size bg_flow.rate.percentage = bg_flow_rate_percent bg_flow.duration.fixed_seconds.seconds = data_flow_dur_sec bg_flow.duration.fixed_seconds.delay.nanoseconds = int( data_flow_delay_nanosec) bg_flow.metrics.enable = True bg_flow.metrics.loss = True """ Pause storm """ pause_flow = testbed_config.flows.flow(name=pause_flow_name)[-1] pause_flow.tx_rx.port.tx_name = testbed_config.ports[rx_port_id].name pause_flow.tx_rx.port.rx_name = testbed_config.ports[tx_port_id].name if global_pause: pause_pkt = pause_flow.packet.ethernetpause()[-1] pause_pkt.src.value = '00:00:fa:ce:fa:ce' pause_pkt.dst.value = '01:80:C2:00:00:01' else: pause_time = [] for x in range(8): if x in pause_prio_list: pause_time.append(int('ffff', 16)) else: pause_time.append(int('0000', 16)) vector = pfc_class_enable_vector(pause_prio_list) pause_pkt = pause_flow.packet.pfcpause()[-1] pause_pkt.src.value = '00:00:fa:ce:fa:ce' pause_pkt.dst.value = '01:80:C2:00:00:01' pause_pkt.class_enable_vector.value = vector pause_pkt.pause_class_0.value = pause_time[0] pause_pkt.pause_class_1.value = pause_time[1] pause_pkt.pause_class_2.value = pause_time[2] pause_pkt.pause_class_3.value = pause_time[3] pause_pkt.pause_class_4.value = pause_time[4] pause_pkt.pause_class_5.value = pause_time[5] pause_pkt.pause_class_6.value = pause_time[6] pause_pkt.pause_class_7.value = pause_time[7] """ Pause frames are sent from the RX port """ 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.rate.pps = pps pause_flow.size.fixed = 64 pause_flow.duration.choice = pause_flow.duration.CONTINUOUS pause_flow.duration.continuous.delay.nanoseconds = 0 pause_flow.metrics.enable = True pause_flow.metrics.loss = True