summaryrefslogtreecommitdiffstats
path: root/scripts/automation/trex_control_plane/stl/trex_stl_lib
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2016-08-15 15:33:51 +0300
committerimarom <imarom@cisco.com>2016-08-15 16:33:41 +0300
commit25aa665b7e5a5e8747735aaaa5a00dba11b21067 (patch)
tree75f6fc67584dbcba8a72b44ed5384f24e0eef698 /scripts/automation/trex_control_plane/stl/trex_stl_lib
parentba7b5dff853a3b11b0cc2e7b29cfc1cd99e606f7 (diff)
TUI screen buffer
Diffstat (limited to 'scripts/automation/trex_control_plane/stl/trex_stl_lib')
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py61
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py4
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py4
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py42
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_tables.py9
5 files changed, 92 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 f0201d6c..3bc507e5 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
@@ -690,20 +690,12 @@ class STLClient(object):
rc = RC()
- ports_mask = {}
- for port_id in port_id_list:
- # a pin mode was requested and we have
- # the second port from the group in the start list
- if (core_mask == self.CORE_MASK_PIN) and ( (port_id ^ 0x1) in port_id_list ):
- ports_mask[port_id] = 0x55555555 if( port_id % 2) == 0 else 0xAAAAAAAA
- else:
- ports_mask[port_id] = None
for port_id in port_id_list:
rc.add(self.ports[port_id].start(multiplier,
duration,
force,
- ports_mask[port_id]))
+ core_mask[port_id]))
return rc
@@ -929,6 +921,37 @@ class STLClient(object):
return stats
+ def __decode_core_mask (self, ports, core_mask):
+
+ validate_type('core_mask', core_mask, (int, list))
+
+ # predefined modes
+ if isinstance(core_mask, int):
+ if core_mask not in [self.CORE_MASK_PIN, self.CORE_MASK_SPLIT]:
+ raise STLError("'core_mask' can be either CORE_MASK_PIN, CORE_MASK_SPLIT or a list of masks")
+
+ mask = {}
+ for port in ports:
+ # a pin mode was requested and we have
+ # the second port from the group in the start list
+ if (core_mask == self.CORE_MASK_PIN) and ( (port ^ 0x1) in ports ):
+ mask[port] = 0x55555555 if( port % 2) == 0 else 0xAAAAAAAA
+ else:
+ mask[port] = None
+
+ return mask
+
+ # list of masks
+ elif isinstance(core_mask, list):
+ if not ports:
+ raise STLError("'ports' must be specified explicitly when providing 'core_mask'")
+ if len(ports) != len(core_mask):
+ raise STLError("'core_mask' list must be the same length as 'ports' list")
+
+ return core_mask
+
+
+
############ functions used by other classes but not users ##############
def _validate_port_list (self, port_id_list):
@@ -1950,7 +1973,7 @@ class STLClient(object):
True: Divide bandwidth among the ports
False: Duplicate
- core_mask: CORE_MASK_SPLIT, CORE_MASK_PIN
+ core_mask: CORE_MASK_SPLIT, CORE_MASK_PIN or a list of masks (one per port)
Determine the allocation of cores per port
In CORE_MASK_SPLIT all the traffic will be divided equally between all the cores
associated with each port
@@ -1962,6 +1985,10 @@ class STLClient(object):
"""
+ #########################
+ # decode core mask argument
+ core_mask = self.__decode_core_mask(ports, core_mask)
+ #######################
ports = ports if ports is not None else self.get_acquired_ports()
ports = self._validate_port_list(ports)
@@ -2677,12 +2704,21 @@ class STLClient(object):
parsing_opts.TUNABLES,
parsing_opts.MULTIPLIER_STRICT,
parsing_opts.DRY_RUN,
- parsing_opts.PIN_CORES)
+ parsing_opts.CORE_MASK_GROUP)
opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True)
if not opts:
return opts
+ # core mask
+ if opts.core_mask is not None:
+ core_mask = opts.core_mask
+ else:
+ core_mask = self.CORE_MASK_PIN if opts.pin_cores else self.CORE_MASK_SPLIT
+
+ # just for sanity - will be checked on the API as well
+ self.__decode_core_mask(opts.ports, core_mask)
+
active_ports = list_intersect(self.get_active_ports(), opts.ports)
if active_ports:
if not opts.force:
@@ -2738,12 +2774,13 @@ class STLClient(object):
if opts.dry:
self.validate(opts.ports, opts.mult, opts.duration, opts.total)
else:
+
self.start(opts.ports,
opts.mult,
opts.force,
opts.duration,
opts.total,
- core_mask = self.CORE_MASK_PIN if opts.pin_cores else self.CORE_MASK_SPLIT)
+ core_mask)
return RC_OK()
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
index 556a14d8..2074080a 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
@@ -36,6 +36,8 @@ class Port(object):
STATE_PAUSE = 4
STATE_PCAP_TX = 5
+ MASK_ALL = ((1 << 64) - 1)
+
PortState = namedtuple('PortState', ['state_id', 'state_name'])
STATES_MAP = {STATE_DOWN: "DOWN",
STATE_IDLE: "IDLE",
@@ -406,7 +408,7 @@ class Port(object):
"mul": mul,
"duration": duration,
"force": force,
- "core_mask": mask if mask is not None else ((1 << 64) - 1)}
+ "core_mask": mask if mask is not None else self.MASK_ALL}
# must set this before to avoid race with the async response
last_state = self.state
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
index b321c00b..5e4bdfda 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
@@ -442,10 +442,6 @@ class CTRexInfoGenerator(object):
for i in range(min(14, len(cpu_stats))):
history = cpu_stats[i]["history"]
ports = cpu_stats[i]["ports"]
- if not len(ports) == 2:
- sys.__stdout__.write(str(util_stats["cpu"]))
- exit(-1)
-
avg = int(round(sum(history[:avg_len]) / avg_len))
# decode active ports for core
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 51265252..9ed6c0f8 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
@@ -38,6 +38,7 @@ TUNABLES = 22
REMOTE_FILE = 23
LOCKED = 24
PIN_CORES = 25
+CORE_MASK = 26
GLOBAL_STATS = 50
PORT_STATS = 51
@@ -48,6 +49,8 @@ CPU_STATS = 55
MBUF_STATS = 56
STREAMS_MASK = 60
+CORE_MASK_GROUP = 61
+
# ALL_STREAMS = 61
# STREAM_LIST_WITH_ALL = 62
@@ -193,6 +196,14 @@ def match_multiplier_strict(val):
return val
+def hex_int (val):
+ pattern = r"0x[1-9a-fA-F][0-9a-fA-F]*"
+
+ if not re.match(pattern, val):
+ raise argparse.ArgumentTypeError("{0} is not a valid positive HEX formatted number".format(val))
+
+ return int(val, 16)
+
def is_valid_file(filename):
if not os.path.isfile(filename):
@@ -274,7 +285,7 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
{"nargs": '+',
'dest':'ports',
'metavar': 'PORTS',
- 'type': int,
+ 'type': int,
'help': "A list of ports on which to apply the command",
'default': []}),
@@ -324,12 +335,6 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
'default': False,
'help': "Dry run - no traffic will be injected"}),
- PIN_CORES: ArgumentPack(['--pin'],
- {'action': 'store_true',
- 'dest': 'pin_cores',
- 'default': False,
- 'help': "Pin cores to interfaces - cores will be divided between interfaces (performance boot for symetric profiles)"}),
-
XTERM: ArgumentPack(['-x', '--xterm'],
{'action': 'store_true',
'dest': 'xterm',
@@ -379,6 +384,21 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
'default': []}),
+ PIN_CORES: ArgumentPack(['--pin'],
+ {'action': 'store_true',
+ 'dest': 'pin_cores',
+ 'default': False,
+ 'help': "Pin cores to interfaces - cores will be divided between interfaces (performance boot for symetric profiles)"}),
+
+ CORE_MASK: ArgumentPack(['--core_mask'],
+ {'action': 'store',
+ 'nargs': '+',
+ 'type': hex_int,
+ 'dest': 'core_mask',
+ 'default': None,
+ 'help': "Core mask - only cores responding to the bit mask will be active"}),
+
+
# promiscuous
PROMISCUOUS_SWITCH: ArgumentGroup(MUTEX, [PROMISCUOUS,
NO_PROMISCUOUS],
@@ -398,7 +418,13 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
STREAMS_STATS,
CPU_STATS,
MBUF_STATS],
- {})
+ {}),
+
+
+ CORE_MASK_GROUP: ArgumentGroup(MUTEX, [PIN_CORES,
+ CORE_MASK],
+ {'required': False}),
+
}
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_tables.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_tables.py
index 4b7e9b3e..393ba111 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_tables.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_tables.py
@@ -1,7 +1,10 @@
+from __future__ import print_function
+
import sys
from texttable import Texttable
from .text_opts import format_text
+
class TRexTextTable(Texttable):
def __init__(self):
@@ -21,11 +24,11 @@ class TRexTextInfo(Texttable):
def generate_trex_stats_table():
pass
-def print_table_with_header(texttable_obj, header="", untouched_header=""):
+def print_table_with_header(texttable_obj, header="", untouched_header="", buffer=sys.stdout):
header = header.replace("_", " ").title() + untouched_header
- print(format_text(header, 'cyan', 'underline') + "\n")
+ print(format_text(header, 'cyan', 'underline') + "\n", file=buffer)
- print((texttable_obj.draw() + "\n"))
+ print((texttable_obj.draw() + "\n"), file=buffer)
if __name__ == "__main__":
pass