X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=tools%2Fpkt_gen%2Ftrex%2Ftrex.py;h=70864a53abb61b08fc3f9af644ae4be90fec4c52;hb=bee2d008c4f708895ef93a7918c20d546091ac29;hp=ae262306c06e4583660ea2e01cf2a1b2d6614814;hpb=1d095d24b5599b965291fa5f6a3734e3bf5e84af;p=vswitchperf.git diff --git a/tools/pkt_gen/trex/trex.py b/tools/pkt_gen/trex/trex.py index ae262306..70864a53 100644 --- a/tools/pkt_gen/trex/trex.py +++ b/tools/pkt_gen/trex/trex.py @@ -21,14 +21,50 @@ import subprocess import sys from collections import OrderedDict # pylint: disable=unused-import +import netaddr import zmq from conf import settings from conf import merge_spec from core.results.results_constants import ResultsConstants from tools.pkt_gen.trafficgen.trafficgen import ITrafficGenerator -# pylint: disable=wrong-import-position, import-error -sys.path.append(settings.getValue('PATHS')['trafficgen']['trex']['src']['path']) -from trex_stl_lib.api import * +try: + # pylint: disable=wrong-import-position, import-error + sys.path.append(settings.getValue('PATHS')['trafficgen']['Trex']['src']['path']) + from trex_stl_lib.api import * +except ImportError: + # VSPERF performs detection of T-Rex api during testcase initialization. So if + # T-Rex is requsted and API is not available it will fail before this code + # is reached. + # This code can be reached in case that --list-trafficgens is called, but T-Rex + # api is not installed. In this case we can ignore an exception, becuase T-Rex + # import won't be used. + pass + +_EMPTY_STATS = { + 'global': {'bw_per_core': 0.0, + 'cpu_util': 0.0, + 'queue_full': 0.0, + 'rx_bps': 0.0, + 'rx_cpu_util': 0.0, + 'rx_drop_bps': 0.0, + 'rx_pps': 0.0, + 'tx_bps': 0.0, + 'tx_pps': 0.0,}, + 'latency': {}, + 'total': {'ibytes': 0.0, + 'ierrors': 0.0, + 'ipackets': 0.0, + 'obytes': 0.0, + 'oerrors': 0.0, + 'opackets': 0.0, + 'rx_bps': 0.0, + 'rx_bps_L1': 0.0, + 'rx_pps': 0.0, + 'rx_util': 0.0, + 'tx_bps': 0.0, + 'tx_bps_L1': 0.0, + 'tx_pps': 0.0, + 'tx_util': 0.0,}} class Trex(ITrafficGenerator): """Trex Traffic generator wrapper.""" @@ -148,8 +184,46 @@ class Trex(ITrafficGenerator): fsize_no_fcs = frame_size - 4 payload_a = max(0, fsize_no_fcs - len(base_pkt_a)) * 'x' payload_b = max(0, fsize_no_fcs - len(base_pkt_b)) * 'x' - pkt_a = STLPktBuilder(pkt=base_pkt_a/payload_a) - pkt_b = STLPktBuilder(pkt=base_pkt_b/payload_b) + + # Multistream configuration, increments source values only + ms_mod = list() # mod list for incrementing values to be populated based on layer + if traffic['multistream'] > 1: + if traffic['stream_type'].upper() == 'L2': + for _ in [base_pkt_a, base_pkt_b]: + ms_mod += [STLVmFlowVar(name="mac_start", min_value=0, + max_value=traffic['multistream'] - 1, size=4, op="inc"), + STLVmWrFlowVar(fv_name="mac_start", pkt_offset=7)] + elif traffic['stream_type'].upper() == 'L3': + ip_src = {"start": int(netaddr.IPAddress(traffic['l3']['srcip'])), + "end": int(netaddr.IPAddress(traffic['l3']['srcip'])) + traffic['multistream'] - 1} + ip_dst = {"start": int(netaddr.IPAddress(traffic['l3']['dstip'])), + "end": int(netaddr.IPAddress(traffic['l3']['dstip'])) + traffic['multistream'] - 1} + for ip_address in [ip_src, ip_dst]: + ms_mod += [STLVmFlowVar(name="ip_src", min_value=ip_address['start'], + max_value=ip_address['end'], size=4, op="inc"), + STLVmWrFlowVar(fv_name="ip_src", pkt_offset="IP.src")] + elif traffic['stream_type'].upper() == 'L4': + for udpport in [traffic['l4']['srcport'], traffic['l4']['dstport']]: + if udpport + (traffic['multistream'] - 1) > 65535: + start_port = udpport + # find the max/min port number based on the loop around of 65535 to 0 if needed + minimum_value = 65535 - (traffic['multistream'] -1) + maximum_value = 65535 + else: + start_port, minimum_value = udpport, udpport + maximum_value = start_port + (traffic['multistream'] - 1) + ms_mod += [STLVmFlowVar(name="port_src", init_value=start_port, + min_value=minimum_value, max_value=maximum_value, + size=2, op="inc"), + STLVmWrFlowVar(fv_name="port_src", pkt_offset="UDP.sport"),] + + if ms_mod: # multistream detected + pkt_a = STLPktBuilder(pkt=base_pkt_a/payload_a, vm=[ms_mod[0], ms_mod[1]]) + pkt_b = STLPktBuilder(pkt=base_pkt_b/payload_b, vm=[ms_mod[2], ms_mod[3]]) + else: + pkt_a = STLPktBuilder(pkt=base_pkt_a / payload_a) + pkt_b = STLPktBuilder(pkt=base_pkt_b / payload_b) + stream_1 = STLStream(packet=pkt_a, name='stream_1', mode=STLTXCont(percentage=traffic['frame_rate'])) @@ -175,6 +249,10 @@ class Trex(ITrafficGenerator): my_ports = [0, 1] self._stlclient.reset(my_ports) ports_info = self._stlclient.get_port_info(my_ports) + # for SR-IOV + if settings.getValue('TRAFFICGEN_TREX_PROMISCUOUS'): + self._stlclient.set_port_attr(my_ports, promiscuous=True) + packet_1, packet_2 = Trex.create_packets(traffic, ports_info) stream_1, stream_2, stream_1_lat, stream_2_lat = Trex.create_streams(packet_1, packet_2, traffic) self._stlclient.add_streams(stream_1, ports=[0]) @@ -213,13 +291,15 @@ class Trex(ITrafficGenerator): result[ResultsConstants.TX_RATE_PERCENT] = 'Unknown' result[ResultsConstants.THROUGHPUT_RX_PERCENT] = 'Unknown' + if stats["total"]["opackets"]: + result[ResultsConstants.FRAME_LOSS_PERCENT] = ( + '{:.3f}'.format( + float((stats["total"]["opackets"] - stats["total"]["ipackets"]) * 100 / + stats["total"]["opackets"]))) + else: + result[ResultsConstants.FRAME_LOSS_PERCENT] = 100 - result[ResultsConstants.FRAME_LOSS_PERCENT] = ( - '{:.3f}'.format( - float((stats["total"]["opackets"] - stats["total"]["ipackets"]) * 100 / - stats["total"]["opackets"]))) - - if settings.getValue('TRAFFICGEN_TREX_LATENCY_PPS') > 0: + if settings.getValue('TRAFFICGEN_TREX_LATENCY_PPS') > 0 and stats['latency']: result[ResultsConstants.MIN_LATENCY_NS] = ( '{:.3f}'.format( (float(min(stats["latency"][0]["latency"]["total_min"], @@ -266,15 +346,17 @@ class Trex(ITrafficGenerator): raise NotImplementedError( 'Trex stop_cont_traffic method not implemented') - def send_rfc2544_throughput(self, traffic=None, duration=60, - lossrate=0.0, tests=10): + def send_rfc2544_throughput(self, traffic=None, tests=1, duration=60, + lossrate=0.0): """See ITrafficGenerator for description """ self._logger.info("In Trex send_rfc2544_throughput method") self._params.clear() + threshold = settings.getValue('TRAFFICGEN_TREX_RFC2544_TPUT_THRESHOLD') test_lossrate = 0 left = 0 - num_test = 1 + iteration = 1 + stats_ok = _EMPTY_STATS self._params['traffic'] = self.traffic_defaults.copy() if traffic: self._params['traffic'] = merge_spec( @@ -284,13 +366,16 @@ class Trex(ITrafficGenerator): right = traffic['frame_rate'] center = traffic['frame_rate'] - while num_test <= tests: + # Loops until the preconfigured difference between frame rate + # of successful and unsuccessful iterations is reached + while (right - left) > threshold: test_lossrate = ((stats["total"]["opackets"] - stats["total"] ["ipackets"]) * 100) / stats["total"]["opackets"] self._logger.debug("Iteration: %s, frame rate: %s, throughput_rx_fps: %s, frame_loss_percent: %s", - num_test, "{:.3f}".format(new_params['frame_rate']), stats['total']['rx_pps'], + iteration, "{:.3f}".format(new_params['frame_rate']), stats['total']['rx_pps'], "{:.3f}".format(test_lossrate)) if test_lossrate == 0.0 and new_params['frame_rate'] == traffic['frame_rate']: + stats_ok = copy.deepcopy(stats) break elif test_lossrate > lossrate: right = center @@ -299,13 +384,14 @@ class Trex(ITrafficGenerator): new_params['frame_rate'] = center stats = self.generate_traffic(new_params, duration) else: + stats_ok = copy.deepcopy(stats) left = center center = (left+right) / 2 new_params = copy.deepcopy(traffic) new_params['frame_rate'] = center stats = self.generate_traffic(new_params, duration) - num_test += 1 - return self.calculate_results(stats) + iteration += 1 + return self.calculate_results(stats_ok) def start_rfc2544_throughput(self, traffic=None, tests=1, duration=60, lossrate=0.0):