diff options
author | 2016-03-16 20:04:28 +0200 | |
---|---|---|
committer | 2016-03-16 20:04:28 +0200 | |
commit | 027850daba11821c3c4eeb1d3711d5905c1ed95d (patch) | |
tree | 85681ec64d435f4c9bc03deb2e7e16cd3d0f105c /scripts/automation/trex_control_plane/stl/trex_stl_lib | |
parent | daf8476c5602d026364df9816ade07a3d4831a0a (diff) | |
parent | aa334e0ef9258ffc70f0741627861b832d79a69b (diff) |
Merge branch 'master' of csi-sceasr-b32:/auto/proj-pcube-b/apps/PL-b/tools/repo//trex-core
Diffstat (limited to 'scripts/automation/trex_control_plane/stl/trex_stl_lib')
4 files changed, 180 insertions, 18 deletions
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py index f7e63ccf..de07e9e4 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py @@ -1930,6 +1930,7 @@ class STLClient(object): parsing_opts.FORCE, parsing_opts.FILE_PATH, parsing_opts.DURATION, + parsing_opts.TUNABLES, parsing_opts.MULTIPLIER_STRICT, parsing_opts.DRY_RUN) @@ -1950,21 +1951,47 @@ class STLClient(object): else: self.stop(active_ports) + + # default value for tunables (empty) + tunables = [{}] * len(opts.ports) + + # process tunables + if opts.tunables: + + # for one tunable - duplicate for all ports + if len(opts.tunables) == 1: + tunables = opts.tunables * len(opts.ports) + + else: + # must be exact + if len(opts.ports) != len(opts.tunables): + self.logger.log('tunables section count must be 1 or exactly as the number of ports: got {0}'.format(len(opts.tunables))) + return + tunables = opts.tunables + + # remove all streams self.remove_all_streams(opts.ports) # pack the profile try: - profile = STLProfile.load(opts.file[0]) + for port, t in zip(opts.ports, tunables): + + # give priority to the user configuration over default direction + if not 'direction' in t: + t['direction'] = (port % 2) + + profile = STLProfile.load(opts.file[0], **t) + + self.add_streams(profile.get_streams(), ports = port) + except STLError as e: self.logger.log(format_text("\nError while loading profile '{0}'\n".format(opts.file[0]), 'bold')) self.logger.log(e.brief() + "\n") return - self.add_streams(profile.get_streams(), ports = opts.ports) - if opts.dry: self.validate(opts.ports, opts.mult, opts.duration, opts.total) else: @@ -2249,3 +2276,42 @@ class STLClient(object): return + + @__console + def show_profile_line (self, line): + '''Shows profile information''' + + parser = parsing_opts.gen_parser(self, + "port", + self.show_profile_line.__doc__, + parsing_opts.FILE_PATH) + + opts = parser.parse_args(line.split()) + if opts is None: + return + + info = STLProfile.get_info(opts.file[0]) + + self.logger.log(format_text('\nProfile Information:\n', 'bold')) + + # general info + self.logger.log(format_text('\nGeneral Information:', 'underline')) + self.logger.log('Filename: {:^12}'.format(opts.file[0])) + self.logger.log('Stream count: {:^12}'.format(info['stream_count'])) + + # specific info + profile_type = info['type'] + self.logger.log(format_text('\nSpecific Information:', 'underline')) + + if profile_type == 'python': + self.logger.log('Type: {:^12}'.format('Python Module')) + self.logger.log('Tunables: {:^12}'.format(['{0} = {1}'.format(k ,v) for k, v in info['tunables'].iteritems()])) + + elif profile_type == 'yaml': + self.logger.log('Type: {:^12}'.format('YAML')) + + elif profile_type == 'pcap': + self.logger.log('Type: {:^12}'.format('PCAP file')) + + self.logger.log("") + diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py index 614d8b77..00fa6a93 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py @@ -122,7 +122,8 @@ class STLSim(object): mult = "1", duration = -1, mode = 'none', - silent = False): + silent = False, + tunables = None): if not mode in ['none', 'gdb', 'valgrind', 'json', 'yaml','pkt','native']: raise STLArgumentError('mode', mode) @@ -139,9 +140,18 @@ class STLSim(object): stream_list = [x for x in input_list if isinstance(x, STLStream)] # handle YAMLs + if tunables == None: + tunables = {} + else: + tunables = tunables[0] + for input_file in input_files: try: - profile = STLProfile.load(input_file) + if not 'direction' in tunables: + tunables['direction'] = self.port_id % 2 + + profile = STLProfile.load(input_file, **tunables) + except STLError as e: s = format_text("\nError while loading profile '{0}'\n".format(input_file), 'bold') s += "\n" + e.brief() @@ -360,6 +370,13 @@ def setParserOptions(): default = None, type = int) + parser.add_argument("-i", "--port", + help = "Simulate a specific port ID [default is 0]", + dest = "port_id", + default = 0, + type = int) + + parser.add_argument("-r", "--release", help = "runs on release image instead of debug [default is False]", action = "store_true", @@ -388,6 +405,13 @@ def setParserOptions(): default = -1, type = float) + + parser.add_argument('-t', + help = 'sets tunable for a profile', + dest = 'tunables', + default = None, + type = parsing_opts.decode_tunables) + parser.add_argument('-p', '--path', help = "BP sim path", dest = 'bp_sim_path', @@ -465,7 +489,7 @@ def main (args = None): mode = 'none' try: - r = STLSim(bp_sim_path = options.bp_sim_path) + r = STLSim(bp_sim_path = options.bp_sim_path, port_id = options.port_id) r.run(input_list = options.input_file, outfile = options.output_file, @@ -476,7 +500,8 @@ def main (args = None): mult = options.mult, duration = options.duration, mode = mode, - silent = options.silent) + silent = options.silent, + tunables = options.tunables) except KeyboardInterrupt as e: print "\n\n*** Caught Ctrl + C... Exiting...\n\n" diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py index b1bde030..8a42145d 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py @@ -508,7 +508,13 @@ class STLStream(object): def to_code (self): """ convert to Python code as profile """ packet = Ether(self.pkt) - packet.hide_defaults() + layer = packet + while layer: # remove checksums + for chksum_name in ('cksum', 'chksum'): + if chksum_name in layer.fields: + del layer.fields[chksum_name] + layer = layer.payload + packet.hide_defaults() # remove fields with default values payload = packet.getlayer('Raw') packet_command = packet.command() imports_arr = [] @@ -790,7 +796,6 @@ class STLProfile(object): streams : list of :class:`trex_stl_lib.trex_stl_streams.STLStream` a list of stream objects - """ @@ -804,6 +809,7 @@ class STLProfile(object): raise STLArgumentError('streams', streams, valid_values = STLStream) self.streams = streams + self.meta = None def get_streams (self): @@ -825,11 +831,32 @@ class STLProfile(object): yaml_loader = YAMLLoader(yaml_file) streams = yaml_loader.parse() - return STLProfile(streams) + profile = STLProfile(streams) + profile.meta = {'type': 'yaml'} + + return profile + + @staticmethod + def get_module_tunables(module): + # remove self and variables + func = module.register().get_streams + argc = func.__code__.co_argcount + tunables = func.__code__.co_varnames[1:argc] + + # fetch defaults + defaults = func.func_defaults + if len(defaults) != (argc - 1): + raise STLError("Module should provide default values for all arguments on get_streams()") + + output = {} + for t, d in zip(tunables, defaults): + output[t] = d + + return output @staticmethod - def load_py (python_file): + def load_py (python_file, direction = 0, **kwargs): """ load from Python profile """ # check filename @@ -844,9 +871,18 @@ class STLProfile(object): module = __import__(file, globals(), locals(), [], -1) reload(module) # reload the update - streams = module.register().get_streams() + t = STLProfile.get_module_tunables(module) + for arg in kwargs: + if not arg in t: + raise STLError("profile {0} does not support tunable '{1}' - supported tunables are: '{2}'".format(python_file, arg, t)) + + streams = module.register().get_streams(direction = direction, **kwargs) + profile = STLProfile(streams) - return STLProfile(streams) + profile.meta = {'type': 'python', + 'tunables': t} + + return profile except Exception as e: a, b, tb = sys.exc_info() @@ -896,6 +932,8 @@ class STLProfile(object): if ipg_usec < 1: raise STLError("ipg_usec cannot be less than 1 usec: '{0}'".format(ipg_usec)) + if loop_count < 0: + raise STLError("'loop_count' cannot be negative") streams = [] last_ts_usec = 0 @@ -928,20 +966,25 @@ class STLProfile(object): last_ts_usec = ts_usec + + profile = STLProfile(streams) + profile.meta = {'type': 'pcap'} - return STLProfile(streams) + return profile @staticmethod - def load (filename): + def load (filename, direction = 0, **kwargs): """ load a profile by its type supported type are * py * yaml * pcap file that converted to profile automaticly :parameters: - filename : string as filename + filename : string as filename + direction : profile's direction (if supported by the profile) + kwargs : forward those key-value pairs to the profile """ @@ -949,7 +992,7 @@ class STLProfile(object): suffix = x[1] if (len(x) == 2) else None if suffix == 'py': - profile = STLProfile.load_py(filename) + profile = STLProfile.load_py(filename, direction, **kwargs) elif suffix == 'yaml': profile = STLProfile.load_yaml(filename) @@ -960,8 +1003,14 @@ class STLProfile(object): else: raise STLError("unknown profile file type: '{0}'".format(suffix)) + profile.meta['stream_count'] = len(profile.get_streams()) if isinstance(profile.get_streams(), list) else 1 return profile + @staticmethod + def get_info (filename): + profile = STLProfile.load(filename) + return profile.meta + def dump_as_pkt (self): """ dump the profile as scapy packet. in case it is raw convert to scapy and dump it""" cnt=0; @@ -990,7 +1039,7 @@ class STLProfile(object): from trex_stl_lib.api import * class STLS1(object): - def get_streams(self): + def get_streams(self, direction = 0, **kwargs): streams = [] ''' for stream in self.streams: diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py index 0390ac9c..c4f2b358 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py @@ -30,6 +30,7 @@ COUNT = 18 PROMISCUOUS = 19 NO_PROMISCUOUS = 20 PROMISCUOUS_SWITCH = 21 +TUNABLES = 22 GLOBAL_STATS = 50 PORT_STATS = 51 @@ -190,6 +191,19 @@ def is_valid_file(filename): return filename +def decode_tunables_to_dict (**kwargs): + return kwargs + +def decode_tunables (tunable_str): + try: + tunables = [eval('decode_tunables_to_dict({0})'.format(t)) for t in tunable_str.split('#')] + + except (SyntaxError, NameError): + raise argparse.ArgumentTypeError("bad syntax for tunables: {0}".format(tunable_str)) + + return tunables + + OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], {'help': match_multiplier_help, 'dest': "mult", @@ -233,6 +247,14 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], 'default': None, 'action': "store_true"}), + + TUNABLES: ArgumentPack(['-t'], + {'help': "sets tunable for a profile", + 'dest': "tunables", + 'default': None, + 'type': decode_tunables}), + + NO_PROMISCUOUS: ArgumentPack(['--no_prom'], {'help': "sets port promiscuous off", 'dest': "prom", |