summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYaroslav Brustinov <ybrustin@cisco.com>2016-09-30 12:52:29 +0300
committerYaroslav Brustinov <ybrustin@cisco.com>2016-09-30 12:55:16 +0300
commit5591bec0425ea906feb109a1142eca66ac1ce937 (patch)
treec7229138821cd26d6881c2dad63c84702a3869f9
parent2e02d8cb37b98794d2d280f0cdc817752f051e5f (diff)
fix parsing tunables, add support for separate -t in console, add benchmark profile
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py30
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py38
-rw-r--r--scripts/stl/bench.py88
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()
+
+
+
+