def generate_streams(self, port, chain_id, stream_cfg, l2frame, latency=True, e2e=False): """Create a list of streams corresponding to a given chain and stream config. port: port where the streams originate (0 or 1) chain_id: the chain to which the streams are associated to stream_cfg: stream configuration l2frame: L2 frame size (including 4-byte FCS) or 'IMIX' latency: if True also create a latency stream """ streams = [] pg_id, lat_pg_id = self.get_pg_id(port, chain_id) if l2frame == 'IMIX': for ratio, l2_frame_size in zip(IMIX_RATIOS, IMIX_L2_SIZES): pkt = self._create_pkt(stream_cfg, l2_frame_size) if e2e: streams.append( STLStream(packet=pkt, mode=STLTXCont(pps=ratio))) else: streams.append( STLStream(packet=pkt, flow_stats=STLFlowStats(pg_id=pg_id), mode=STLTXCont(pps=ratio))) if latency: # for IMIX, the latency packets have the average IMIX packet size pkt = self._create_pkt(stream_cfg, IMIX_AVG_L2_FRAME_SIZE) else: l2frame_size = int(l2frame) pkt = self._create_pkt(stream_cfg, l2frame_size) if e2e: streams.append(STLStream(packet=pkt, mode=STLTXCont())) else: streams.append( STLStream(packet=pkt, flow_stats=STLFlowStats(pg_id=pg_id), mode=STLTXCont())) # for the latency stream, the minimum payload is 16 bytes even in case of vlan tagging # without vlan, the min l2 frame size is 64 # with vlan it is 68 # This only applies to the latency stream if latency and stream_cfg['vlan_tag'] and l2frame_size < 68: pkt = self._create_pkt(stream_cfg, 68) if latency: streams.append( STLStream(packet=pkt, flow_stats=STLFlowLatencyStats(pg_id=lat_pg_id), mode=STLTXCont(pps=self.LATENCY_PPS))) return streams
def start(self, args: dict) -> None: pkt = Ether(dst=DEST_MAC) / IP() / TCP() / ("*" * 1500) # Create a traffic stream stream = STLStream(packet=STLPktBuilder(pkt=pkt, vm=[]), mode=STLTXCont()) self.client.add_streams(stream, ports=[0]) logging.info( "Starting traffic, duration: %d sec", args.duration, ) # Start sending traffic self.client.start(SENDER_PORT, mult="100%", duration=args.duration) logging.info("Waiting until all traffic stop") self.client.wait_on_traffic(ports=SENDER_PORT) # Get statistics for TX and RX ports stats = self.client.get_stats() rx_rate_mbps = stats[1]["rx_bps"] / (10**6) assert (SHAPING_RATE_MBPS * 0.95 < rx_rate_mbps < SHAPING_RATE_MBPS ), "The measured RX rate is not close to the port shaping rate" readable_stats_0 = get_readable_port_stats(stats[0]) readable_stats_1 = get_readable_port_stats(stats[1]) print("\n Statistics for TX port: \n") print(readable_stats_0) print("\n Statistics for RX port: \n") print(readable_stats_1)
def create_streams(self): base_pkt = Ether() / IP( src=self.tunables["src_ip"], dst=self.tunables["dst_ip"] ) / UDP(chksum=0) pkt_size = self.tunables["pkt_size"] - 4 # HW will add 4 bytes ethernet FCS pad = self.tunables["pkt_data"] * max(0, pkt_size - len(base_pkt)) pkt = base_pkt / pad return STLStream( packet=STLPktBuilder(pkt=pkt), mode=STLTXCont(pps=self.tunables["pps"]) )
def create_streams(self): base_pkt = (Ether() / IP(src=self.tunables["src_ip"], dst=self.tunables["dst_ip"]) / UDP(chksum=0)) pkt_size = self.tunables[ "pkt_size"] - 4 # HW will add 4 bytes ethernet FCS pad = self.tunables["pkt_data"] * max(0, pkt_size - len(base_pkt)) if len(pad) < 16: raise Exception( "At least 16 bytes payload is needed for latency measurements") pkt = base_pkt / pad stream = STLStream(packet=STLPktBuilder(pkt=pkt), mode=STLTXCont(pps=self.tunables["pps"])) streams = [stream] flow_stats = self.tunables["flow_stats"] if flow_stats == "stats": latency_stream = STLStream( packet=STLPktBuilder(pkt=pkt), mode=STLTXCont(pps=self.tunables["flow_stats_pps"]), flow_stats=STLFlowStats( pg_id=self.tunables["flow_stats_pg_id"]), ) elif flow_stats == "latency": latency_stream = STLStream( packet=STLPktBuilder(pkt=pkt), mode=STLTXCont(pps=self.tunables["flow_stats_pps"]), flow_stats=STLFlowLatencyStats( pg_id=self.tunables["flow_stats_pg_id"]), ) streams.append(latency_stream) elif not flow_stats: pass else: error_msg = ( f"Unknown flow stats type {flow_stats}. Available types: stats, latency" ) raise Exception(error_msg) return streams
def start(self, args) -> None: pkt = ( Ether(src=SOURCE_MAC, dst=DEST_MAC) / IP(src=SOURCE_IP, dst=DEST_IP) / UDP() / ("*" * 1500) ) stream = STLStream(packet=STLPktBuilder(pkt=pkt, vm=[]), mode=STLTXCont()) logging.info("Setting up ports") self.client.add_streams(stream, ports=SENDER_PORTS) pkt_capture_limit = args.duration * 3 logging.info( "Start capturing first %s RX packet from INT collector", pkt_capture_limit ) self.client.set_service_mode(ports=INT_COLLECTPR_PORTS, enabled=True) capture = self.client.start_capture( rx_ports=INT_COLLECTPR_PORTS, limit=pkt_capture_limit, bpf_filter="udp and dst port 32766", ) logging.info( "Starting traffic, duration: %ds, throughput: 100%%", args.duration ) self.client.start(ports=SENDER_PORTS, mult="100%", duration=args.duration) logging.info("Waiting until all traffic stop") self.client.wait_on_traffic(ports=SENDER_PORTS) logging.info("Stop capturing packet from INT collector port") output = "/tmp/congestion-report-{}.pcap".format( datetime.now().strftime("%Y%m%d-%H%M%S") ) self.client.stop_capture(capture["id"], output) analysis_report_pcap(output) list_port_status(self.client.get_stats())
def start(self, args) -> None: pkt = self.get_sample_packet(args.pkt_type) if not pkt: return 1 stream = STLStream(packet=STLPktBuilder(pkt=pkt, vm=[]), mode=STLTXCont()) logging.info("Setting up ports") self.client.add_streams(stream, ports=SENDER_PORTS) pkt_capture_limit = args.duration * 3 logging.info("Start capturing first %s RX packet from INT collector", pkt_capture_limit) self.client.set_service_mode(ports=INT_COLLECTPR_PORTS, enabled=True) capture = self.client.start_capture( rx_ports=INT_COLLECTPR_PORTS, limit=pkt_capture_limit, bpf_filter="udp and dst port 32766", ) logging.info("Starting traffic, duration: %ds, throughput: %s", args.duration, args.mult) self.client.start(ports=SENDER_PORTS, mult=args.mult, duration=args.duration) logging.info("Waiting until all traffic stop") self.client.wait_on_traffic(ports=SENDER_PORTS) logging.info("Stop capturing packet from INT collector port") output = "/tmp/int-single-flow-{}-{}.pcap".format( args.pkt_type, datetime.now().strftime("%Y%m%d-%H%M%S")) logging.info("Capture file {}".format(output)) self.client.stop_capture(capture["id"], output) analysis_report_pcap(output) list_port_status(self.client.get_stats())
def create_stream(self): return STLStream(packet=STLPktBuilder( pkt=Ether() / IP(src="16.0.0.1", dst="48.0.0.1") / UDP(dport=12, sport=1025) / (10 * 'x')), mode=STLTXCont())
def start(self, args: dict) -> None: # create packets pkt1 = Ether(dst=DEST_MAC) / IP(src="16.0.0.1", dst="48.0.0.1") / UDP( dport=12, sport=1025) / ("*" * 1500) pkt2 = Ether(dst=DEST_MAC) / IP(src="16.0.0.2", dst="48.0.0.2") / UDP( dport=12, sport=1025) / ("*" * 1500) pkt3 = Ether(dst=DEST_MAC) / IP(src="16.0.0.3", dst="48.0.0.3") / UDP( dport=12, sport=1025) / ("*" * 1500) #stream list streams = [] # Create a traffic stream # assume s1 is a delay critical stream with QoS s1 = STLStream(packet=STLPktBuilder(pkt=pkt1), mode=STLTXCont(percentage=1), flow_stats=STLFlowLatencyStats(pg_id=1)) # assume s2 is a delay critical stream without QoS s2 = STLStream(packet=STLPktBuilder(pkt=pkt2), mode=STLTXCont(percentage=1), flow_stats=STLFlowLatencyStats(pg_id=2)) # assume s3 is a lower priority stream s3 = STLStream(packet=STLPktBuilder(pkt=pkt3), mode=STLTXCont(percentage=98), flow_stats=STLFlowLatencyStats(pg_id=3)) # prepare ports self.client.reset(ports=[0, 1]) # add sterams streams.append(s1) streams.append(s2) streams.append(s3) self.client.add_streams(streams, ports=[0]) logging.info( "Starting traffic, duration: %d sec", args.duration, ) # Start sending traffic self.client.start(SENDER_PORT, mult="100%", duration=args.duration) pgids = self.client.get_active_pgids() logging.info("Waiting until all traffic stop") self.client.wait_on_traffic(ports=SENDER_PORT) # stats for pg_id 1 and 2 stats = self.client.get_pgid_stats(pgids['latency']) flow_stats_1 = stats['flow_stats'].get(1) flow_stats_2 = stats['flow_stats'].get(2) global_lat_stats = stats['latency'] lat_stats_1 = global_lat_stats.get(1) lat_stats_2 = global_lat_stats.get(2) tx_pkts_1 = flow_stats_1['tx_pkts'].get(0, 0) rx_pkts_1 = flow_stats_1['rx_pkts'].get(1, 0) drops_1 = lat_stats_1['err_cntrs']['dropped'] tx_pkts_2 = flow_stats_2['tx_pkts'].get(0, 0) rx_pkts_2 = flow_stats_2['rx_pkts'].get(1, 0) drops_2 = lat_stats_2['err_cntrs']['dropped'] print( " \n TX and RX flow stats and packets dropped for s1 (i.e., delay critical): " ) print(" tx packets: {0}".format(tx_pkts_1)) print(" tx bytes : {0}".format(tx_pps_1)) print(" rx packets : {0}".format(rx_pkts_1)) print(" drops: {0}".format(drops_1)) print( " \n TX and RX flow stats and packets dropped for s2 (i.e., delay critical): " ) print(" tx packets: {0}".format(tx_pkts_2)) print(" tx bytes : {0}".format(tx_pps_2)) print(" rx packets : {0}".format(rx_pkts_2)) print(" drops: {0}".format(drops_2)) # latency info for s1 lat_1 = lat_stats_1['latency'] avg_1 = lat_1['average'] tot_max_1 = lat_1['total_max'] tot_min_1 = lat_1['total_min'] # latency info for s2 lat_2 = lat_stats_2['latency'] avg_2 = lat_2['average'] tot_max_2 = lat_2['total_max'] tot_min_2 = lat_2['total_min'] print('\n Latency info for s1 (ie., delay critical with QoS):') print(" Maximum latency(usec): {0}".format(tot_max_1)) print(" Minimum latency(usec): {0}".format(tot_min_1)) print(" Average latency(usec): {0}".format(avg_1)) print('\n Latency info for s2 (ie., delay critical without QoS):') print(" Maximum latency(usec): {0}".format(tot_max_2)) print(" Minimum latency(usec): {0}".format(tot_min_2)) print(" Average latency(usec): {0}".format(avg_2)) # max latency difference between delay critcal streams s1 and s2 dc_max_lat_diff = tot_max_2 - tot_max_1 assert ((LATENCY_LP_MAX_USEC - LATENCY_DC_MAX_USEC) <= dc_max_lat_diff), \ "Priority scheduling test failed." # Get statistics for TX and RX ports stats = self.client.get_stats() readable_stats_0 = get_readable_port_stats(stats[0]) readable_stats_1 = get_readable_port_stats(stats[1]) logging.info("Priority scheduling test successfully executed.") print("\n Overall Statistics for TX port: \n") print(readable_stats_0) print("\n Overall Statistics for RX port: \n") print(readable_stats_1)
def runTest(self): n3TEID = 0 startIP = IPv4Address('16.0.0.1') endIP = startIP + UE_COUNT - 1 accessIP = IPv4Address('10.128.13.29') enbIP = IPv4Address( '10.27.19.99' ) # arbitrary ip for non-existent eNodeB for gtpu encap # program UPF for downlink traffic by installing PDRs and FARs print("Installing PDRs and FARs...") for i in range(UE_COUNT): # install N6 DL PDR to match UE dst IP pdrDown = self.createPDR( srcIface=CORE, dstIP=int(startIP + i), srcIfaceMask=0xFF, dstIPMask=0xFFFFFFFF, precedence=255, fseID=n3TEID + i + 1, # start from 1 ctrID=0, farID=i, qerIDList=[N6, 1], needDecap=0, ) self.addPDR(pdrDown) # install N6 DL FAR for encap farDown = self.createFAR( farID=i, fseID=n3TEID + i + 1, # start from 1 applyAction=ACTION_FORWARD, dstIntf=DST_ACCESS, tunnelType=0x1, tunnelIP4Src=int(accessIP), tunnelIP4Dst=int(enbIP), # only one eNB to send to downlink tunnelTEID=0, tunnelPort=GTPU_PORT, ) self.addFAR(farDown) # install N6 DL/UL application QER qer = self.createQER( gate=GATE_UNMETER, qerID=N6, fseID=n3TEID + i + 1, # start from 1 qfi=9, ulGbr=0, ulMbr=0, dlGbr=0, dlMbr=0, burstDurationMs=10, ) self.addApplicationQER(qer) # set up trex to send traffic thru UPF print("Setting up TRex client...") vm = STLVM() vm.var( name="dst", min_value=str(startIP), max_value=str(endIP), size=4, op="random", ) vm.write(fv_name="dst", pkt_offset="IP.dst") vm.fix_chksum() pkt = testutils.simple_udp_packet( pktlen=PKT_SIZE, eth_dst=UPF_DEST_MAC, with_udp_chksum=False, ) stream = STLStream( packet=STLPktBuilder(pkt=pkt, vm=vm), mode=STLTXCont(pps=RATE), ) self.trex_client.add_streams(stream, ports=[BESS_SENDER_PORT]) print("Running traffic...") s_time = time.time() self.trex_client.start(ports=[BESS_SENDER_PORT], mult="1", duration=DURATION) # FIXME: pull QoS metrics at end instead of while traffic running time.sleep(DURATION - 5) if self.trex_client.is_traffic_active(): stats = self.getSessionStats(q=[90, 99, 99.9], quiet=True) preQos = stats["preQos"] postDlQos = stats["postDlQos"] postUlQos = stats["postUlQos"] self.trex_client.wait_on_traffic(ports=[BESS_SENDER_PORT]) print(f"Duration was {time.time() - s_time}") trex_stats = self.trex_client.get_stats() sent_packets = trex_stats['total']['opackets'] recv_packets = trex_stats['total']['ipackets'] # 0% packet loss self.assertEqual( sent_packets, recv_packets, f"Didn't receive all packets; sent {sent_packets}, received {recv_packets}", ) for fseid in postDlQos: lat = fseid['latency']['percentileValuesNs'] jitter = fseid['jitter']['percentileValuesNs'] # 99th %ile latency < 100 us self.assertLessEqual( int(lat[1]) / 1000, 100, f"99th %ile latency was higher than 100 us! Was {int(lat[1]) / 1000} us" ) # 99.9th %ile latency < 200 us self.assertLessEqual( int(lat[2]) / 1000, 200, f"99.9th %ile latency was higher than 200 us! Was {int(lat[2]) / 1000} us" ) # 99th% jitter < 100 us self.assertLessEqual( int(jitter[1]) / 1000, 100, f"99th %ile jitter was higher than 100 us! Was {int(jitter[1]) / 1000} us" ) return
def runTest(self): n3TEID = 0 startIP = IPv4Address('16.0.0.1') endIP = startIP + UE_COUNT - 1 accessIP = IPv4Address('10.128.13.29') enbIP = IPv4Address( '10.27.19.99') # arbitrary ip for nonexistent enodeB # program UPF for downlink traffic by installing PDRs and FARs print("Installing PDRs and FARs...") for i in range(UE_COUNT): # install N6 DL PDR to match UE dst IP pdrDown = self.createPDR( srcIface=CORE, dstIP=int(startIP + i), srcIfaceMask=0xFF, dstIPMask=0xFFFFFFFF, precedence=255, fseID=n3TEID + i + 1, # start from 1 ctrID=0, farID=i, qerIDList=[N6, 1], needDecap=0, ) self.addPDR(pdrDown) # install N6 DL FAR for encap farDown = self.createFAR( farID=i, fseID=n3TEID + i + 1, # start from 1 applyAction=ACTION_FORWARD, dstIntf=DST_ACCESS, tunnelType=0x1, tunnelIP4Src=int(accessIP), tunnelIP4Dst=int(enbIP), # only one eNB to send to downlink tunnelTEID=0, tunnelPort=GTPU_PORT, ) self.addFAR(farDown) # install N6 DL/UL application QER qer = self.createQER( gate=GATE_UNMETER, qerID=N6, fseID=n3TEID + i + 1, # start from 1 qfi=9, ulGbr=0, ulMbr=0, dlGbr=0, dlMbr=0, burstDurationMs=10, ) self.addApplicationQER(qer) # set up trex to send traffic thru UPF print("Setting up TRex client...") vm = STLVM() vm.var( name="dst", min_value=str(startIP), max_value=str(endIP), size=4, op="random", ) vm.write(fv_name="dst", pkt_offset="IP.dst") vm.fix_chksum() pkt = testutils.simple_udp_packet( pktlen=PKT_SIZE, eth_dst=UPF_DEST_MAC, with_udp_chksum=False, ) stream = STLStream( packet=STLPktBuilder(pkt=pkt, vm=vm), mode=STLTXCont(pps=RATE), flow_stats=STLFlowLatencyStats(pg_id=0), ) self.trex_client.add_streams(stream, ports=[BESS_SENDER_PORT]) print("Running traffic...") s_time = time.time() self.trex_client.start( ports=[BESS_SENDER_PORT], mult="1", duration=DURATION, ) self.trex_client.wait_on_traffic(ports=[BESS_SENDER_PORT]) print(f"Duration was {time.time() - s_time}") trex_stats = self.trex_client.get_stats() lat_stats = get_latency_stats(0, trex_stats) flow_stats = get_flow_stats(0, trex_stats) # Verify test results met baseline performance expectations # 0% packet loss self.assertEqual( flow_stats.tx_packets, flow_stats.rx_packets, f"Didn't receive all packets; sent {flow_stats.tx_packets}, received {flow_stats.rx_packets}", ) # 99.9th %ile latency < 1000 us self.assertLessEqual( lat_stats.percentile_99_9, 1000, f"99.9th %ile latency was higher than 1000 us! Was {lat_stats.percentile_99_9} us", ) # jitter < 20 us self.assertLessEqual( lat_stats.jitter, 20, f"Jitter was higher than 20 us! Was {lat_stats.jitter}", ) return
def configure_traffic_stream(self, traffic_flows, nr_of_flows, packet_size, **kwargs): flow_percentage = float(kwargs.pop("percentage", 1000000)) / 10000 trex_dst_mac = kwargs.pop("traffic_dst_mac", '00:00:02:00:00:00') trex_src_mac = kwargs.pop("traffic_src_mac", '00:00:01:00:00:00') l2_macs = kwargs.pop("l2_macs", 1) # # The packet size passed here assumes it includes the checksum, however # the TRex packet size does not. Adjust the size to correct this. # packet_size -= 4 if traffic_flows == TrafficFlowType.none or \ self.__traffic_flows != TrafficFlowType.none: # # We need either a cleanup, or a cleanup before we configure # a new traffic flow type # self._delete_traffic_stream_config() if traffic_flows == TrafficFlowType.l2_mac or \ traffic_flows == TrafficFlowType.l3_ipv4 or \ traffic_flows == TrafficFlowType.nfv_mobile: # # Max flows due to IPv4 address limit, and addresses used for tests # if nr_of_flows > 0x00ffffff: raise ValueError( "To many flows requested, max {} supported!".format( 0x00ffffff)) L2 = Ether(src=trex_src_mac, dst=trex_dst_mac) L3 = IP(src="1.0.0.0", dst="2.0.0.0") L4 = UDP(chksum=0) if (len(str(L2 / L3 / L4)) + 4) > packet_size: # +4 for Ethernet CRC raise ValueError("Packet size ({} bytes) to small for" "requested packet ({} bytes)!".format( packet_size, len(L2 / L3 / L4) + 4)) if traffic_flows == TrafficFlowType.l2_mac: src_base = self._mac_2_int(trex_src_mac) & 0xff000000 dst_base = self._mac_2_int(trex_dst_mac) & 0xff000000 vm = [ # Source MAC address STLVmFlowVar(name="src", min_value=src_base, max_value=src_base + nr_of_flows - 1, size=4, op="inc"), STLVmWrFlowVar(fv_name="src", pkt_offset=8), # Destination MAC address STLVmFlowVar(name="dst", min_value=dst_base, max_value=dst_base + nr_of_flows - 1, size=4, op="inc"), STLVmWrFlowVar(fv_name="dst", pkt_offset=2) ] elif traffic_flows == TrafficFlowType.l3_ipv4: src_end = str( netaddr.IPAddress( int(netaddr.IPAddress('1.0.0.0')) + nr_of_flows - 1)) dst_end = str( netaddr.IPAddress( int(netaddr.IPAddress('2.0.0.0')) + nr_of_flows - 1)) vm = [ # Source IPv4 address STLVmFlowVar(name="src", min_value="1.0.0.0", max_value=src_end, size=4, op="inc"), STLVmWrFlowVar(fv_name="src", pkt_offset="IP.src"), # Destination IPv4 address STLVmFlowVar(name="dst", min_value="2.0.0.0", max_value=dst_end, size=4, op="inc"), STLVmWrFlowVar(fv_name="dst", pkt_offset="IP.dst"), # Checksum STLVmFixIpv4(offset="IP") ] elif traffic_flows == TrafficFlowType.nfv_mobile: src_end = str( netaddr.IPAddress( int(netaddr.IPAddress('1.0.0.0')) + nr_of_flows - 1)) dst_end = str( netaddr.IPAddress( int(netaddr.IPAddress('2.0.0.0')) + nr_of_flows - 1)) vm = [ # Source MAC address STLVmFlowVar(name="srcm", min_value=0x01000001, max_value=0x01000001 + l2_macs - 1, size=4, op="inc"), STLVmWrFlowVar(fv_name="srcm", pkt_offset=8), # Destination MAC address STLVmFlowVar(name="dstm", min_value=0x02000000, max_value=0x02000000 + l2_macs - 1, size=4, op="inc"), STLVmWrFlowVar(fv_name="dstm", pkt_offset=2), # Source IPv4 address STLVmFlowVar(name="src", min_value="1.0.0.0", max_value=src_end, size=4, op="inc"), STLVmWrFlowVar(fv_name="src", pkt_offset="IP.src"), # Destination IPv4 address STLVmFlowVar(name="dst", min_value="2.0.0.0", max_value=dst_end, size=4, op="inc"), STLVmWrFlowVar(fv_name="dst", pkt_offset="IP.dst"), # Checksum STLVmFixIpv4(offset="IP") ] else: raise ValueError( "Unsupported traffic type for T-Rex tester!!!") if traffic_flows == TrafficFlowType.nfv_mobile: stream_percentage = flow_percentage / 2 else: stream_percentage = flow_percentage headers = L2 / L3 / L4 padding = max(0, (packet_size - len(headers))) * 'e' packet = headers / padding trex_packet = STLPktBuilder(pkt=packet, vm=vm) trex_stream = STLStream( packet=trex_packet, mode=STLTXCont(percentage=stream_percentage)) self.__trex_client.add_streams(trex_stream, ports=[self.__trex_port]) # # For nfv_mobile we still need to setup the alternating streams. # if traffic_flows == TrafficFlowType.nfv_mobile: alternate_flows = kwargs.pop("alternate_flows", 200000) stream_percentage = flow_percentage / 2 self.__active_alternate_stream = 0 # # Keep the flows the same as for the Xena version, so the # traffic scripts using this do not have to differentiate # between traffic generator types. # # The Xena uses streams and every stream can generate 64K # flows. To Find the flow start we need the number of base # flows rounded of the next 64K (stream) and use the next one. # # For the individual iterations of the flow set they also # need to start at a 64K boundary. # start_stream_id = self._div_round_up(nr_of_flows, 0x10000) + 1 for alternate_flow_sets in range(0, 3): flow_start = start_stream_id * 0x10000 src_start = str( netaddr.IPAddress( int(netaddr.IPAddress('1.0.0.0')) + flow_start)) src_end = str( netaddr.IPAddress( int(netaddr.IPAddress('1.0.0.0')) + flow_start + alternate_flows - 1)) dst_start = str( netaddr.IPAddress( int(netaddr.IPAddress('2.0.0.0')) + flow_start)) dst_end = str( netaddr.IPAddress( int(netaddr.IPAddress('2.0.0.0')) + flow_start + alternate_flows - 1)) vm = [ # Source MAC address STLVmFlowVar(name="srcm", min_value=0x01000001, max_value=0x01000001 + l2_macs - 1, size=4, op="inc"), STLVmWrFlowVar(fv_name="srcm", pkt_offset=8), # Destination MAC address STLVmFlowVar(name="dstm", min_value=0x02000000, max_value=0x02000000 + l2_macs - 1, size=4, op="inc"), STLVmWrFlowVar(fv_name="dstm", pkt_offset=2), # Source IPv4 address STLVmFlowVar(name="src", min_value=src_start, max_value=src_end, size=4, op="inc"), STLVmWrFlowVar(fv_name="src", pkt_offset="IP.src"), # Destination IPv4 address STLVmFlowVar(name="dst", min_value=dst_start, max_value=dst_end, size=4, op="inc"), STLVmWrFlowVar(fv_name="dst", pkt_offset="IP.dst"), # Checksum STLVmFixIpv4(offset="IP") ] trex_packet = STLPktBuilder(pkt=packet, vm=vm) stream = STLStream( packet=trex_packet, mode=STLTXCont(percentage=stream_percentage), start_paused=False if alternate_flow_sets == 0 else True) self.__alternate_stream_sets.append( self.__trex_client.add_streams( stream, ports=[self.__trex_port])) start_stream_id += self._div_round_up( alternate_flows, 0x10000) self.__traffic_flows = traffic_flows return True elif traffic_flows == TrafficFlowType.none: self.__traffic_flows = traffic_flows return True else: raise ValueError( "Unsupported traffic flow passed for T-Rex tester!") self.__traffic_flows = TrafficFlowType.none return False
def configure_traffic_stream(self, traffic_flows, nr_of_flows, packet_size, **kwargs): flow_percentage = kwargs.pop("percentage", 1000000) / 10000 if traffic_flows == TrafficFlowType.none or \ self.__traffic_flows != TrafficFlowType.none: # # We need either a cleanup, or a cleanup before we configure # a new traffic flow type # self._delete_traffic_stream_config() if traffic_flows == TrafficFlowType.l2_mac or \ traffic_flows == TrafficFlowType.l3_ipv4: # # Max flows due to IPv4 address limit, and addresses used for tests # if nr_of_flows > 0x00ffffff: raise ValueError( "To many flows requested, max {} supported!".format( 0x00ffffff)) L2 = Ether(src="00:00:01:00:00:01", dst="00:00:02:00:00:00") L3 = IP(src="1.0.0.0", dst="2.0.0.0") L4 = UDP(chksum=0) if (len(str(L2 / L3 / L4)) + 4) > packet_size: # +4 for Ethernet CRC raise ValueError( "Packet size ({} bytes) to small for requested " "packet ({} bytes)!".format(packet_size, len(L2 / L3 / L4) + 4)) if traffic_flows == TrafficFlowType.l2_mac: vm = [ # Source MAC address STLVmFlowVar(name="src", min_value=0x01000001, max_value=0x01000001 + nr_of_flows - 1, size=4, op="inc"), STLVmWrFlowVar(fv_name="src", pkt_offset=8), # Destination MAC address STLVmFlowVar(name="dst", min_value=0x02000000, max_value=0x02000000 + nr_of_flows - 1, size=4, op="inc"), STLVmWrFlowVar(fv_name="dst", pkt_offset=2) ] elif traffic_flows == TrafficFlowType.l3_ipv4: src_end = str( netaddr.IPAddress( int(netaddr.IPAddress('1.0.0.0')) + nr_of_flows - 1)) dst_end = str( netaddr.IPAddress( int(netaddr.IPAddress('2.0.0.0')) + nr_of_flows - 1)) vm = [ # Source IPv4 address STLVmFlowVar(name="src", min_value="1.0.0.0", max_value=src_end, size=4, op="inc"), STLVmWrFlowVar(fv_name="src", pkt_offset="IP.src"), # Destination IPv4 address STLVmFlowVar(name="dst", min_value="2.0.0.0", max_value=dst_end, size=4, op="inc"), STLVmWrFlowVar(fv_name="dst", pkt_offset="IP.dst"), # Checksum STLVmFixIpv4(offset="IP") ] else: raise ValueError( "Unsupported traffic type for T-Rex tester!!!") headers = L2 / L3 / L4 padding = max(0, (packet_size - len(headers))) * 'e' packet = headers / padding trex_packet = STLPktBuilder(pkt=packet, vm=vm) trex_stream = STLStream(packet=trex_packet, mode=STLTXCont(percentage=flow_percentage)) self.__trex_client.add_streams(trex_stream, ports=[self.__trex_port]) return True elif traffic_flows == TrafficFlowType.none: return True else: raise ValueError( "Unsupported traffic flow passed for T-Rex tester!") return False