diff options
Diffstat (limited to 'scripts')
3 files changed, 128 insertions, 28 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 2d7cb269..82aa932d 100755 --- 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 @@ -837,7 +837,7 @@ class STLClient(object): if not rc: return rc - self.supported_cmds = rc.data() + self.supported_cmds = sorted(rc.data()) # create ports for port_id in range(self.system_info["port_count"]): @@ -2831,26 +2831,12 @@ 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): - msg = 'tunables section count must be 1 or exactly as the number of ports: got {0}'.format(len(opts.tunables)) - self.logger.log(msg) - return RC_ERR(msg) - - tunables = opts.tunables - + if type(opts.tunables) is dict: + tunables = opts.tunables + else: + tunables = {} # remove all streams @@ -2858,12 +2844,12 @@ class STLClient(object): # pack the profile try: - for port, t in zip(opts.ports, tunables): + for port in opts.ports: profile = STLProfile.load(opts.file[0], - direction = t.get('direction', port % 2), + direction = tunables.get('direction', port % 2), port_id = port, - **t) + **tunables) self.add_streams(profile.get_streams(), ports = port) 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 b42b56af..8ae86981 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 @@ -217,15 +217,28 @@ def is_valid_file(filename): def decode_tunables (tunable_str): tunables = {} - # split by diaz to tokens - tokens = tunable_str.split('#') + # split by comma to tokens + tokens = tunable_str.split(',') # each token is of form X=Y for token in tokens: - m = re.search('(.*)=(.*)', token) + m = re.search('(\S+)=(.+)', token) if not m: raise argparse.ArgumentTypeError("bad syntax for tunables: {0}".format(token)) - tunables[m.group(1)] = m.group(2) + val = m.group(2) # string + if val.startswith(("'", '"')) and val.endswith(("'", '"')) and len(val) > 1: # need to remove the quotes from value + val = val[1:-1] + elif val.startswith('0x'): # hex + val = int(val, 16) + else: + try: + if '.' in val: # float + val = float(val) + else: # int + val = int(val) + except: + pass + tunables[m.group(1)] = val return tunables @@ -279,9 +292,10 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], 'metavar': 'T1=VAL[,T2=VAL ...]', 'dest': "tunables", 'default': None, + 'action': 'merge', 'type': decode_tunables}), - NO_PROMISCUOUS: ArgumentPack(['--no_prom'], + NO_PROMISCUOUS: ArgumentPack(['--no-prom', '--no_prom'], {'help': "Sets port promiscuous off", 'dest': "prom", 'default': None, @@ -291,6 +305,7 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], {"nargs": '+', 'dest':'ports', 'metavar': 'PORTS', + 'action': 'merge', 'type': int, 'help': "A list of ports on which to apply the command", 'default': []}), @@ -438,6 +453,17 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], } +class _MergeAction(argparse._AppendAction): + def __call__(self, parser, namespace, values, option_string=None): + items = getattr(namespace, self.dest) + if not items: + items = values + elif type(items) is list and type(values) is list: + items.extend(values) + elif type(items) is dict and type(values) is dict: # tunables are dict + items.update(values) + + setattr(namespace, self.dest, items) class CCmdArgParser(argparse.ArgumentParser): @@ -445,7 +471,7 @@ class CCmdArgParser(argparse.ArgumentParser): super(CCmdArgParser, self).__init__(*args, **kwargs) self.stateless_client = stateless_client self.cmd_name = kwargs.get('prog') - + self.register('action', 'merge', _MergeAction) # hook this to the logger def _print_message(self, message, file=None): diff --git a/scripts/stl/bench.py b/scripts/stl/bench.py new file mode 100644 index 00000000..66473597 --- /dev/null +++ b/scripts/stl/bench.py @@ -0,0 +1,88 @@ +from trex_stl_lib.api import * + +class STLBench(object): + ip_range = {} + ip_range['src'] = {'start': '16.0.0.0', 'end': '16.0.255.255'} + ip_range['dst'] = {'start': '48.0.0.0', 'end': '48.0.255.255'} + ports = {'min': 1234, 'max': 65500} + pkt_size = {'min': 64, 'max': 9216} + + def create_stream (self, size, vm): + # Create base packet and pad it to size + base_pkt = Ether()/IP()/UDP() + pad = max(0, size - len(base_pkt) - 4) * 'x' + + pkt = STLPktBuilder(pkt = base_pkt/pad, + vm = vm) + + return STLStream(packet = pkt, + mode = STLTXCont()) + + + def get_streams (self, size=64, vm=None, direction=0, **kwargs): + if direction == 0: + src, dst = self.ip_range['src'], self.ip_range['dst'] + else: + src, dst = self.ip_range['dst'], self.ip_range['src'] + + if not vm or vm == 'none': + vm_var = None + elif vm == 'var1': + vm_var =[ + STLVmFlowVar(name = 'src', min_value = src['start'], max_value = src['end'], size = 4, op = 'inc'), + STLVmWrFlowVar(fv_name = 'src', pkt_offset = 'IP.src'), + STLVmFixIpv4(offset = 'IP') + ] + elif vm == 'var2': + vm_var =[ + STLVmFlowVar(name = 'src', min_value = src['start'], max_value = src['end'], size = 4, op = 'inc'), + STLVmWrFlowVar(fv_name = 'src', pkt_offset = 'IP.src'), + STLVmFlowVar(name = 'dst', min_value = dst['start'], max_value = dst['end'], size = 4, op = 'inc'), + STLVmWrFlowVar(fv_name = 'dst', pkt_offset = 'IP.dst'), + STLVmFixIpv4(offset = 'IP') + ] + elif vm == 'random': + vm_var =[ + STLVmFlowVar(name = 'src', min_value = src['start'], max_value = src['end'], size = 4, op = 'random'), + STLVmWrFlowVar(fv_name = 'src', pkt_offset = 'IP.src'), + STLVmFixIpv4(offset = 'IP') + ] + elif vm == 'tuple': + vm_var =[ + STLVmTupleGen(ip_min = src['start'], ip_max = src['end'], port_min = self.ports['min'], port_max = self.ports['max'], name = 'tuple'), + STLVmWrFlowVar(fv_name = 'tuple.ip', pkt_offset = 'IP.src'), + STLVmWrFlowVar(fv_name = 'tuple.port', pkt_offset = 'UDP.sport'), + STLVmFixIpv4(offset = 'IP') + ] + elif vm == 'size': + size = self.pkt_size['max'] + l3_len_fix = -len(Ether()) + l4_len_fix = l3_len_fix - len(IP()) + vm_var = [ + STLVmFlowVar(name = 'fv_rand', min_value = (self.pkt_size['min'] - 4), max_value = (self.pkt_size['max'] - 4), size = 2, op = 'random'), + STLVmTrimPktSize('fv_rand'), + STLVmWrFlowVar(fv_name = 'fv_rand', pkt_offset = 'IP.len', add_val = l3_len_fix), + STLVmWrFlowVar(fv_name = 'fv_rand', pkt_offset = 'UDP.len', add_val = l4_len_fix), + STLVmFixIpv4(offset = 'IP') + ] + elif vm == 'cached': + vm_raw =[ + STLVmFlowVar(name = 'src', min_value = src['start'], max_value = src['end'], size = 4, op = 'inc'), + STLVmWrFlowVar(fv_name = 'src', pkt_offset = 'IP.src'), + STLVmFixIpv4(offset = 'IP') + ] + vm_var = STLScVmRaw(vm_raw, cache_size = 255); + else: + raise Exception("VM '%s' not available" % vm) + + return [self.create_stream(size, vm_var)] + + + +# dynamic load - used for trex console or simulator +def register(): + return STLBench() + + + + |