diff options
10 files changed, 369 insertions, 151 deletions
diff --git a/api/stl/examples/stl_bi_dir_flows.py b/api/stl/examples/stl_bi_dir_flows.py new file mode 100644 index 00000000..429445e6 --- /dev/null +++ b/api/stl/examples/stl_bi_dir_flows.py @@ -0,0 +1,122 @@ +# include the path of trex_stl_api.py +import sys +sys.path.insert(0, "../") + +from trex_stl_api import * + +import dpkt +import time +import json + + +def simple_burst (): + + # build A side packet + pkt_a = STLPktBuilder() + + pkt_a.add_pkt_layer("l2", dpkt.ethernet.Ethernet()) + pkt_a.add_pkt_layer("l3_ip", dpkt.ip.IP()) + pkt_a.add_pkt_layer("l4_udp", dpkt.udp.UDP()) + pkt_a.set_pkt_payload("somepayload") + pkt_a.set_layer_attr("l3_ip", "len", len(pkt_a.get_layer('l3_ip'))) + + # build B side packet + pkt_b = pkt_a.clone() + + # set IP range for pkt and split it by multiple cores + pkt_a.set_vm_ip_range(ip_layer_name = "l3_ip", + ip_field = "src", + ip_start="10.0.0.1", ip_end="10.0.0.254", + operation = "inc", + split = True) + + pkt_a.set_vm_ip_range(ip_layer_name = "l3_ip", + ip_field = "dst", + ip_start="8.0.0.1", ip_end="8.0.0.254", + operation = "inc") + + + # build B side packet + pkt_b.set_vm_ip_range(ip_layer_name = "l3_ip", + ip_field = "src", + ip_start="8.0.0.1", ip_end="8.0.0.254", + operation = "inc", + split = True) + + pkt_b.set_vm_ip_range(ip_layer_name = "l3_ip", + ip_field = "dst", + ip_start="10.0.0.1", ip_end="10.0.0.254", + operation = "inc") + + + # create client + c = STLClient() + passed = True + + try: + # turn this on for some information + #c.set_verbose("high") + + # create two streams + s1 = STLStream(packet = pkt_a, + mode = STLTXCont(pps = 100)) + + # second stream with a phase of 1ms (inter stream gap) + s2 = STLStream(packet = pkt_b, + isg = 1000, + mode = STLTXCont(pps = 100)) + + + # connect to server + c.connect() + + # prepare our ports (my machine has 0 <--> 1 with static route) + c.reset(ports = [0, 1]) + + # add both streams to ports + c.add_streams(s1, ports = [0]) + c.add_streams(s2, ports = [1]) + + # clear the stats before injecting + c.clear_stats() + + # choose rate and start traffic for 10 seconds on 5 mpps + print "Running 5 Mpps on ports 0, 1 for 10 seconds..." + c.start(ports = [0, 1], mult = "5mpps", duration = 10) + + # block until done + c.wait_on_traffic(ports = [0, 1]) + + # read the stats after the test + stats = c.get_stats() + + print json.dumps(stats["port 0"], indent = 4, separators=(',', ': '), sort_keys = True) + print json.dumps(stats["port 1"], indent = 4, separators=(',', ': '), sort_keys = True) + + lost_a = stats["port 0"]["opackets"] - stats["port 1"]["ipackets"] + lost_b = stats["port 1"]["opackets"] - stats["port 0"]["ipackets"] + + print "\npackets lost from 0 --> 1: {0} pkts".format(lost_a) + print "packets lost from 1 --> 0: {0} pkts".format(lost_b) + + if (lost_a == 0) and (lost_b == 0): + passed = True + else: + passed = False + + except STLError as e: + passed = False + print e + + finally: + c.disconnect() + + if passed: + print "\nTest has passed :-)\n" + else: + print "\nTest has failed :-(\n" + + +# run the tests +simple_burst() + diff --git a/api/stl/examples/stl_simple_burst.py b/api/stl/examples/stl_simple_burst.py index ff159289..3b394d10 100644 --- a/api/stl/examples/stl_simple_burst.py +++ b/api/stl/examples/stl_simple_burst.py @@ -36,11 +36,18 @@ def simple_burst (): passed = True try: + #c.logger.set_verbose(c.logger.VERBOSE_NORMAL) # create two bursts and link them - s1 = STLSingleBurstStream(packet = pkt_bld, total_pkts = 5000) - s2 = STLSingleBurstStream(packet = pkt_bld, total_pkts = 3000, next_stream_id = s1.get_id()) + s1 = STLStream(packet = pkt_bld, + mode = STLTXSingleBurst(total_pkts = 5000) + ) + + s2 = STLStream(packet = pkt_bld, + mode = STLTXSingleBurst(total_pkts = 3000), + next_stream_id = s1.get_id()) + # connect to server c.connect() diff --git a/api/stl/trex_stl_api.py b/api/stl/trex_stl_api.py index 63a0963b..ce818b7a 100644 --- a/api/stl/trex_stl_api.py +++ b/api/stl/trex_stl_api.py @@ -16,8 +16,10 @@ import client.trex_stateless_client STLClient = client.trex_stateless_client.STLClient STLError = common.trex_stl_exceptions.STLError -STLContStream = common.trex_streams.STLContStream -STLSingleBurstStream = common.trex_streams.STLSingleBurstStream -STLMultiBurstStream = common.trex_streams.STLMultiBurstStream -STLPktBuilder = CTRexPktBuilder +STLStream = common.trex_streams.STLStream + +STLTXCont = common.trex_streams.STLTXCont +STLTXSingleBurst = common.trex_streams.STLTXSingleBurst +STLTXMultiBurst = common.trex_streams.STLTXMultiBurst +STLPktBuilder = CTRexPktBuilder diff --git a/scripts/automation/regression/unit_tests/functional_tests/pkt_builder_test.py b/scripts/automation/regression/unit_tests/functional_tests/pkt_builder_test.py index c2946798..d33d92fe 100755 --- a/scripts/automation/regression/unit_tests/functional_tests/pkt_builder_test.py +++ b/scripts/automation/regression/unit_tests/functional_tests/pkt_builder_test.py @@ -262,8 +262,10 @@ class CTRexPktBuilder_Test(pkt_bld_general_test.CGeneralPktBld_Test): self.pkt_bld.add_pkt_layer("l4_tcp", dpkt.tcp.TCP()) self.pkt_bld.set_pkt_payload("HelloWorld") - self.pkt_bld.set_vm_ip_range("l3", "src", - "10.0.0.1", "10.0.0.1", "10.0.0.255", 1, + self.pkt_bld.set_vm_ip_range("l3", + "src", + "10.0.0.1", + "10.0.0.255", "inc") # self.pkt_bld.set_vm_custom_range(layer_name="l3", # hdr_field="tos", @@ -272,15 +274,15 @@ class CTRexPktBuilder_Test(pkt_bld_general_test.CGeneralPktBld_Test): print '' self.pp.pprint(self.pkt_bld.vm.dump()) assert_equal(self.pkt_bld.vm.dump(), - { 'instructions': [ { 'init_value': '167772161', - 'max_value': '167772415', - 'min_value': '167772161', + { 'instructions': [ { 'init_value': 167772161, + 'max_value': 167772415, + 'min_value': 167772161, 'name': 'l3__src', 'op': 'inc', 'size': 4, 'type': 'flow_var'}, - { 'add_value': 1, - 'is_big_endian': False, + { 'add_value': 0, + 'is_big_endian': True, 'name': 'l3__src', 'pkt_offset': 26, 'type': 'write_flow_var'}, @@ -304,15 +306,15 @@ class CTRexPktBuilder_Test(pkt_bld_general_test.CGeneralPktBld_Test): print '' self.pp.pprint(self.pkt_bld.vm.dump()) assert_equal(self.pkt_bld.vm.dump(), - { 'instructions': [ { 'init_value': '167772161', - 'max_value': '167772415', - 'min_value': '167772161', + { 'instructions': [ { 'init_value': 167772161, + 'max_value': 167772415, + 'min_value': 167772161, 'name': 'l3__src', 'op': 'inc', 'size': 4, 'type': 'flow_var'}, { 'add_value': 1, - 'is_big_endian': False, + 'is_big_endian': True, 'name': 'l3__src', 'pkt_offset': 26, 'type': 'write_flow_var'}], @@ -335,15 +337,15 @@ class CTRexPktBuilder_Test(pkt_bld_general_test.CGeneralPktBld_Test): print '' self.pp.pprint(self.pkt_bld.vm.dump()) assert_equal(self.pkt_bld.vm.dump(), - { 'instructions': [ { 'init_value': '65537', - 'max_value': '65551', - 'min_value': '65537', + { 'instructions': [ { 'init_value': 65537, + 'max_value': 65551, + 'min_value': 65537, 'name': 'l3__src', 'op': 'inc', 'size': 4, 'type': 'flow_var'}, { 'add_value': 1, - 'is_big_endian': False, + 'is_big_endian': True, 'name': 'l3__src', 'pkt_offset': 34, 'type': 'write_flow_var'}], @@ -367,15 +369,15 @@ class CTRexPktBuilder_Test(pkt_bld_general_test.CGeneralPktBld_Test): print '' self.pp.pprint(self.pkt_bld.vm.dump()) assert_equal(self.pkt_bld.vm.dump(), - { 'instructions': [ { 'init_value': '10', - 'max_value': '200', - 'min_value': '10', + { 'instructions': [ { 'init_value': 10, + 'max_value': 200, + 'min_value': 10, 'name': 'l3__tos', 'op': 'inc', 'size': 1, 'type': 'flow_var'}, { 'add_value': 2, - 'is_big_endian': False, + 'is_big_endian': True, 'name': 'l3__tos', 'pkt_offset': 15, 'type': 'write_flow_var'}, @@ -390,8 +392,10 @@ class CTRexPktBuilder_Test(pkt_bld_general_test.CGeneralPktBld_Test): self.pkt_bld.add_pkt_layer("l4_tcp", dpkt.tcp.TCP()) self.pkt_bld.set_pkt_payload("HelloWorld") - self.pkt_bld.set_vm_ip_range("l3", "src", - "10.0.0.1", "10.0.0.1", "10.0.0.255", 1, + self.pkt_bld.set_vm_ip_range("l3", + "src", + "10.0.0.1", + "10.0.0.255", "inc") self.pkt_bld.set_vm_custom_range(layer_name="l3", hdr_field="tos", @@ -399,28 +403,29 @@ class CTRexPktBuilder_Test(pkt_bld_general_test.CGeneralPktBld_Test): operation="inc") print '' self.pp.pprint(self.pkt_bld.vm.dump()) + assert_equal(self.pkt_bld.vm.dump(), - {'instructions': [{'init_value': '167772161', - 'max_value': '167772415', - 'min_value': '167772161', + {'instructions': [{'init_value': 167772161, + 'max_value': 167772415, + 'min_value': 167772161, 'name': 'l3__src', 'op': 'inc', 'size': 4, 'type': 'flow_var'}, - {'init_value': '10', - 'max_value': '200', - 'min_value': '10', + {'init_value': 10, + 'max_value': 200, + 'min_value': 10, 'name': 'l3__tos', 'op': 'inc', 'size': 1, 'type': 'flow_var'}, {'add_value': 2, - 'is_big_endian': False, + 'is_big_endian': True, 'name': 'l3__tos', 'pkt_offset': 15, 'type': 'write_flow_var'}, - {'add_value': 1, - 'is_big_endian': False, + {'add_value': 0, + 'is_big_endian': True, 'name': 'l3__src', 'pkt_offset': 26, 'type': 'write_flow_var'}, diff --git a/scripts/automation/regression/unit_tests/functional_tests/vm_test.py b/scripts/automation/regression/unit_tests/functional_tests/vm_test.py index 603c52db..f3948d99 100755 --- a/scripts/automation/regression/unit_tests/functional_tests/vm_test.py +++ b/scripts/automation/regression/unit_tests/functional_tests/vm_test.py @@ -23,9 +23,9 @@ class CTRexVM_Test(pkt_bld_general_test.CGeneralPktBld_Test): # "big_endian": True, "op": "inc", # "split_by_core": False, - "init_value": "5", - "min_value": "1", - "max_value": "100"}) + "init_value": 5, + "min_value": 1, + "max_value": 100}) assert_raises(CTRexPktBuilder.VMFieldNameError, self.vm.add_flow_man_inst, "src_mac", no_field=1) def test_load_flow_man(self): @@ -50,16 +50,16 @@ class CTRexVM_Test(pkt_bld_general_test.CGeneralPktBld_Test): print '' pprint (self.vm.dump()) assert_equal(self.vm.dump(), - {'instructions': [{'init_value': '10', - 'max_value': '100', - 'min_value': '2', + {'instructions': [{'init_value': 10, + 'max_value': 100, + 'min_value': 2, 'name': 'src_ip', 'op': 'dec', 'size': 8, 'type': 'flow_var'}, - {'init_value': '5', - 'max_value': '100', - 'min_value': '1', + {'init_value': 5, + 'max_value': 100, + 'min_value': 1, 'name': 'dst_ip', 'op': 'inc', 'size': 8, diff --git a/scripts/automation/regression/unit_tests/functional_tests/vm_variable_test.py b/scripts/automation/regression/unit_tests/functional_tests/vm_variable_test.py index af56b1b1..699f1d97 100755 --- a/scripts/automation/regression/unit_tests/functional_tests/vm_variable_test.py +++ b/scripts/automation/regression/unit_tests/functional_tests/vm_variable_test.py @@ -50,9 +50,9 @@ class CTRexVMVariable_Test(pkt_bld_general_test.CGeneralPktBld_Test): # "big_endian": True, "op": "inc", # "split_by_core": False, - "init_value": "5", - "min_value": "1", - "max_value": "100"}) + "init_value": 5, + "min_value": 1, + "max_value": 100}) def tearDown(self): pass diff --git a/scripts/automation/trex_control_plane/client/trex_stateless_client.py b/scripts/automation/trex_control_plane/client/trex_stateless_client.py index 65e69938..3d4dbc93 100755 --- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py +++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py @@ -110,6 +110,10 @@ class LoggerApi(object): # default logger - to stdout class DefaultLogger(LoggerApi): + + def __init__ (self): + super(DefaultLogger, self).__init__() + def write (self, msg, newline = True): if newline: print msg @@ -972,17 +976,22 @@ class STLClient(object): Sets verbose level :parameters: - level : enum - LoggerApi.VERBOSE_QUIET - LoggerApi.VERBOSE_NORMAL - LoggerApi.VERBOSE_HIGH + level : str + "high" + "low" + "normal" :raises: None """ def set_verbose (self, level): - self.logger.set_verbose(level) + modes = {'low' : LoggerApi.VERBOSE_QUIET, 'normal': LoggerApi.VERBOSE_REGULAR, 'high': LoggerApi.VERBOSE_HIGH} + + if not level in modes.keys(): + raise STLArgumentError('level', level) + + self.logger.set_verbose(modes[level]) """ diff --git a/scripts/automation/trex_control_plane/client_utils/packet_builder.py b/scripts/automation/trex_control_plane/client_utils/packet_builder.py index c7d3308e..e2a1b116 100755 --- a/scripts/automation/trex_control_plane/client_utils/packet_builder.py +++ b/scripts/automation/trex_control_plane/client_utils/packet_builder.py @@ -36,6 +36,9 @@ class CTRexPktBuilder(object): self.vm = CTRexPktBuilder.CTRexVM() self.metadata = "" + def clone (self): + return copy.deepcopy(self) + def add_pkt_layer(self, layer_name, pkt_layer): """ This method adds additional header to the already existing packet @@ -331,10 +334,8 @@ class CTRexPktBuilder(object): def load_packet_from_byte_list(self, byte_list): - # convert byte array into buffer - byte_list = [ord(c) for c in base64.b64decode(byte_list)] - buf = struct.pack('B'*len(byte_list), *byte_list) + buf = base64.b64decode(byte_list) # thn, load it based on dpkt parsing self.load_packet(dpkt.ethernet.Ethernet(buf)) @@ -381,11 +382,15 @@ class CTRexPktBuilder(object): layer = self._pkt_by_hdr.get(layer_name) return copy.copy(layer) if layer else None + # VM access methods def set_vm_ip_range(self, ip_layer_name, ip_field, - ip_init, ip_start, ip_end, add_value, - operation, is_big_endian=False, val_size=4, - ip_type="ipv4", add_checksum_inst=True): + ip_start, ip_end, operation, + ip_init = None, add_value = 0, + is_big_endian=True, val_size=4, + ip_type="ipv4", add_checksum_inst=True, + split = False): + if ip_field not in ["src", "dst"]: raise ValueError("set_vm_ip_range only available for source ('src') or destination ('dst') ip addresses") # set differences between IPv4 and IPv6 @@ -400,11 +405,18 @@ class CTRexPktBuilder(object): self._verify_layer_prop(ip_layer_name, ip_class) trim_size = ip_addr_size*2 - init_val = int(binascii.hexlify(CTRexPktBuilder._decode_ip_addr(ip_init, ip_type))[-trim_size:], 16) start_val = int(binascii.hexlify(CTRexPktBuilder._decode_ip_addr(ip_start, ip_type))[-trim_size:], 16) end_val = int(binascii.hexlify(CTRexPktBuilder._decode_ip_addr(ip_end, ip_type))[-trim_size:], 16) + + if ip_init == None: + init_val = start_val + else: + init_val = int(binascii.hexlify(CTRexPktBuilder._decode_ip_addr(ip_init, ip_type))[-trim_size:], 16) + + # All validations are done, start adding VM instructions flow_var_name = "{layer}__{field}".format(layer=ip_layer_name, field=ip_field) + hdr_offset, field_abs_offset = self._calc_offset(ip_layer_name, ip_field, ip_addr_size) self.vm.add_flow_man_inst(flow_var_name, size=ip_addr_size, operation=operation, init_value=init_val, @@ -416,6 +428,10 @@ class CTRexPktBuilder(object): if ip_type == "ipv4" and add_checksum_inst: self.vm.add_fix_checksum_inst(self._pkt_by_hdr.get(ip_layer_name), hdr_offset) + if split: + self.vm.set_split_by_var(flow_var_name) + + def set_vm_eth_range(self, eth_layer_name, eth_field, mac_init, mac_start, mac_end, add_value, operation, val_size=4, is_big_endian=False): @@ -440,7 +456,7 @@ class CTRexPktBuilder(object): def set_vm_custom_range(self, layer_name, hdr_field, init_val, start_val, end_val, add_val, val_size, - operation, is_big_endian=False, range_name="", + operation, is_big_endian=True, range_name="", add_checksum_inst=True): # verify input validity for init/start/end values for val in [init_val, start_val, end_val]: @@ -835,6 +851,13 @@ class CTRexPktBuilder(object): else: raise CTRexPktBuilder.VMVarNameExistsError(flow_obj.name) + def set_split_by_var (self, var_name): + if var_name not in self.vm_variables: + raise KeyError("cannot set split by var to an unknown VM var ('{0}')". + format(var_name)) + + self.split_by_var = var_name + def dump(self): """ dumps a VM variables (instructions) and split_by_var into a dict data structure. @@ -958,9 +981,9 @@ class CTRexPktBuilder(object): "size": self.size, "op": self.operation, # "split_by_core": self.split_by_core, - "init_value": str(self.init_value), - "min_value": str(self.min_value), - "max_value": str(self.max_value)} + "init_value": self.init_value, + "min_value": self.min_value, + "max_value": self.max_value} class CTRexVMChecksumInst(CVMAbstractInstruction): diff --git a/scripts/automation/trex_control_plane/common/trex_streams.py b/scripts/automation/trex_control_plane/common/trex_streams.py index 90cb812d..0d77b457 100755 --- a/scripts/automation/trex_control_plane/common/trex_streams.py +++ b/scripts/automation/trex_control_plane/common/trex_streams.py @@ -10,6 +10,8 @@ import struct import copy import os import random +import yaml +import base64 StreamPack = namedtuple('StreamPack', ['stream_id', 'stream']) LoadedStreamList = namedtuple('LoadedStreamList', ['name', 'loaded', 'compiled']) @@ -208,13 +210,17 @@ class CStream(object): "should not be supplied") else: binary = kwargs[k]["binary"] - if isinstance(binary, list): - setattr(self, k, kwargs[k]) + if isinstance(binary, str): + # TODO: load to _pkt_bld_obj also when passed as byte array! - elif isinstance(binary, str) and binary.endswith(".pcap"): - self._pkt_bld_obj.load_packet_from_pcap(binary) - self._pkt_bld_obj.metadata = kwargs[k]["meta"] - self.packet = self._pkt_bld_obj.dump_pkt() + if binary.endswith(".pcap"): + self._pkt_bld_obj.load_packet_from_pcap(binary) + self._pkt_bld_obj.metadata = kwargs[k]["meta"] + self.packet = self._pkt_bld_obj.dump_pkt() + else: + self.packet = {} + self.packet['binary'] = binary + self.packet['meta'] = "" else: raise ValueError("Packet binary attribute has been loaded with unsupported value." @@ -329,11 +335,82 @@ class CStreamsDB(object): ########################### Simple Streams ########################### from trex_stl_exceptions import * +# base class for TX mode +class STLTXMode(object): + def __init__ (self): + self.fields = {} + + def to_json (self): + return self.fields + + +# continuous mode +class STLTXCont(STLTXMode): + + def __init__ (self, pps = 1): + + if not isinstance(pps, (int, float)): + raise STLArgumentError('pps', pps) + + super(STLTXCont, self).__init__() + + self.fields['type'] = 'continuous' + self.fields['pps'] = pps + + +# single burst mode +class STLTXSingleBurst(STLTXMode): + + def __init__ (self, pps = 1, total_pkts = 1): + + if not isinstance(pps, (int, float)): + raise STLArgumentError('pps', pps) + + if not isinstance(total_pkts, int): + raise STLArgumentError('total_pkts', total_pkts) + + super(STLTXSingleBurst, self).__init__() + + self.fields['type'] = 'single_burst' + self.fields['pps'] = pps + self.fields['total_pkts'] = total_pkts + + +# multi burst mode +class STLTXMultiBurst(STLTXMode): + + def __init__ (self, + pps = 1, + pkts_per_burst = 1, + ibg = 0.0, + count = 1): + + if not isinstance(pps, (int, float)): + raise STLArgumentError('pps', pps) + + if not isinstance(pkts_per_burst, int): + raise STLArgumentError('pkts_per_burst', pkts_per_burst) + + if not isinstance(ibg, (int, float)): + raise STLArgumentError('ibg', ibg) + + if not isinstance(count, int): + raise STLArgumentError('count', count) + + super(STLTXMultiBurst, self).__init__() + + self.fields['type'] = 'multi_burst' + self.fields['pps'] = pps + self.fields['pkts_per_burst'] = pkts_per_burst + self.fields['ibg'] = ibg + self.fields['count'] = count + + class STLStream(object): def __init__ (self, packet, - pps = 1, + mode = STLTXCont(1), enabled = True, self_start = True, isg = 0.0, @@ -341,8 +418,8 @@ class STLStream(object): next_stream_id = -1): # type checking - if not isinstance(pps, (int, float)): - raise STLArgumentError('pps', pps) + if not isinstance(mode, STLTXMode): + raise STLArgumentError('mode', mode) if not isinstance(packet, CTRexPktBuilder): raise STLArgumentError('packet', packet) @@ -356,6 +433,9 @@ class STLStream(object): if not isinstance(isg, (int, float)): raise STLArgumentError('isg', isg) + if (type(mode) == STLTXCont) and (next_stream_id != -1): + raise STLError("continuous stream cannot have a next stream ID") + # use a random 31 bit for ID self.stream_id = random.getrandbits(31) @@ -369,8 +449,7 @@ class STLStream(object): self.fields['next_stream_id'] = next_stream_id # mode - self.fields['mode'] = {} - self.fields['mode']['pps'] = pps + self.fields['mode'] = mode.to_json() # packet and VM self.fields['packet'] = packet.dump_pkt() @@ -390,88 +469,44 @@ class STLStream(object): def get_id (self): return self.stream_id + @staticmethod + def dump_to_yaml (yaml_file, stream_list): -# continuous stream -class STLContStream(STLStream): - def __init__ (self, - packet, - pps = 1, - enabled = True, - self_start = True, - isg = 0.0, - rx_stats = None): - - super(STLContStream, self).__init__(packet, - pps, - enabled, - self_start, - isg, - rx_stats, - next_stream_id = -1) - - # type - self.fields['mode']['type'] = "continuous" - - - -# single burst -class STLSingleBurstStream(STLStream): - def __init__ (self, - packet, - total_pkts, - pps = 1, - enabled = True, - self_start = True, - isg = 0.0, - rx_stats = None, - next_stream_id = -1): - + # type check + if isinstance(stream_list, STLStream): + stream_list = [stream_list] - if not isinstance(total_pkts, int): - raise STLArgumentError('total_pkts', total_pkts) + if not all([isinstance(stream, STLStream) for stream in stream_list]): + raise STLArgumentError('stream_list', stream_list) - super(STLSingleBurstStream, self).__init__(packet, - pps, - enabled, - self_start, - isg, - rx_stats, - next_stream_id) - self.fields['mode']['type'] = "single_burst" - self.fields['mode']['total_pkts'] = total_pkts + names = {} + for i, stream in enumerate(stream_list): + names[stream.get_id()] = "stream-{0}".format(i) + yaml_lst = [] + for stream in stream_list: -# multi burst stream -class STLMultiBurstStream(STLStream): - def __init__ (self, - packet, - pkts_per_burst = 1, - pps = 1, - ibg = 0.0, - count = 1, - enabled = True, - self_start = True, - isg = 0.0, - rx_stats = None, - next_stream_id = -1): + fields = dict(stream.fields) + # handle the next stream id + if fields['next_stream_id'] == -1: + del fields['next_stream_id'] - if not isinstance(pkts_per_burst, int): - raise STLArgumentError('pkts_per_burst', pkts_per_burst) + else: + if not stream.get_id() in names: + raise STLError('broken dependencies in stream list') - if not isinstance(count, int): - raise STLArgumentError('count', count) + fields['next_stream'] = names[stream.get_id()] - if not isinstance(ibg, (int, float)): - raise STLArgumentError('ibg', ibg) + # add to list + yaml_lst.append({'name': names[stream.get_id()], 'stream': fields}) - super(STLMultiBurstStream, self).__init__(packet, enabled, self_start, isg, rx_stats) + # write to file + x = yaml.dump(yaml_lst, default_flow_style=False) + with open(yaml_file, 'w') as f: + f.write(x) - self.fields['mode']['type'] = "single_burst" - self.fields['mode']['pkts_per_burst'] = pkts_per_burst - self.fields['mode']['ibg'] = ibg - self.fields['mode']['count'] = count # REMOVE ME when can - convert from stream pack to a simple stream diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 1defc6b2..6a4af350 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -221,7 +221,7 @@ class TRexConsole(TRexGeneralCmd): def get_console_identifier(self): - return "{context}_{server}".format(context=self.__class__.__name__, + return "{context}_{server}".format(context=get_current_user(), server=self.stateless_client.get_connection_info()['server']) def register_main_console_methods(self): @@ -305,12 +305,12 @@ class TRexConsole(TRexGeneralCmd): elif line == "on": self.verbose = True - self.stateless_client.set_verbose(self.stateless_client.logger.VERBOSE_HIGH) + self.stateless_client.set_verbose("high") print format_text("\nverbose set to on\n", 'green', 'bold') elif line == "off": self.verbose = False - self.stateless_client.set_verbose(self.stateless_client.logger.VERBOSE_REGULAR) + self.stateless_client.set_verbose("normal") print format_text("\nverbose set to off\n", 'green', 'bold') else: @@ -515,7 +515,7 @@ class TRexConsole(TRexGeneralCmd): info = self.stateless_client.get_connection_info() - exe = './trex-console -t -q -s {0} -p {1} --async_port {2}'.format(info['server'], info['sync_port'], info['async_port']) + exe = './trex-console --top -t -q -s {0} -p {1} --async_port {2}'.format(info['server'], info['sync_port'], info['async_port']) cmd = ['xterm', '-geometry', '111x42', '-sl', '0', '-title', 'trex_tui', '-e', exe] self.terminal = subprocess.Popen(cmd) @@ -686,6 +686,13 @@ def setParserOptions(): action="store_true", help="Starts with TUI mode", default = False) + parser.add_argument("-x", "--xtui", dest="xtui", + action="store_true", help="Starts with XTERM TUI mode", + default = False) + + parser.add_argument("--top", dest="top", + action="store_true", help="Set the window as always on top", + default = False) parser.add_argument("-q", "--quiet", dest="quiet", action="store_true", help="Starts with all outputs suppressed", @@ -698,6 +705,14 @@ def main(): parser = setParserOptions() options = parser.parse_args() + if options.xtui: + options.tui = True + + # always on top + if options.top: + set_window_always_on_top('trex_tui') + + # Stateless client connection if options.quiet: verbose_level = LoggerApi.VERBOSE_QUIET @@ -742,9 +757,9 @@ def main(): console = TRexConsole(stateless_client, options.verbose) logger.prompt_redraw = console.prompt_redraw + # TUI if options.tui: - set_window_always_on_top('trex_tui') - console.do_tui("") + console.do_tui("-x" if options.xtui else "") else: console.start() |