summaryrefslogtreecommitdiffstats
path: root/scripts/automation/trex_control_plane/stl/trex_stl_lib
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2016-08-10 17:45:36 +0300
committerimarom <imarom@cisco.com>2016-08-15 16:03:59 +0300
commitba7b5dff853a3b11b0cc2e7b29cfc1cd99e606f7 (patch)
tree25a2d72756217ef5d364a4c9b5a6e5e9a9d165a7 /scripts/automation/trex_control_plane/stl/trex_stl_lib
parentce1de344579505665b88c2d548ca8d2acc135988 (diff)
core mask - first phase
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.py45
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py17
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py39
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py6
4 files changed, 84 insertions, 23 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 611e48f4..f0201d6c 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
@@ -453,6 +453,10 @@ class CCommLink(object):
class STLClient(object):
"""TRex Stateless client object - gives operations per TRex/user"""
+ # different modes for attaching traffic to ports
+ CORE_MASK_SPLIT = 1
+ CORE_MASK_PIN = 2
+
def __init__(self,
username = common.get_current_user(),
server = "localhost",
@@ -675,14 +679,31 @@ class STLClient(object):
return self.ports[port_id].get_stream_id_list()
- def __start (self, multiplier, duration, port_id_list = None, force = False):
+ def __start (self,
+ multiplier,
+ duration,
+ port_id_list,
+ force,
+ core_mask):
port_id_list = self.__ports(port_id_list)
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))
+ rc.add(self.ports[port_id].start(multiplier,
+ duration,
+ force,
+ ports_mask[port_id]))
return rc
@@ -800,13 +821,14 @@ class STLClient(object):
self.server_version = rc.data()
self.global_stats.server_version = rc.data()
-
+
# cache system info
rc = self._transmit("get_system_info")
if not rc:
return rc
self.system_info = rc.data()
+ self.global_stats.system_info = rc.data()
# cache supported commands
rc = self._transmit("get_supported_cmds")
@@ -1901,7 +1923,8 @@ class STLClient(object):
mult = "1",
force = False,
duration = -1,
- total = False):
+ total = False,
+ core_mask = CORE_MASK_SPLIT):
"""
Start traffic on port(s)
@@ -1927,6 +1950,12 @@ class STLClient(object):
True: Divide bandwidth among the ports
False: Duplicate
+ core_mask: CORE_MASK_SPLIT, CORE_MASK_PIN
+ 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
+ In CORE_MASK_PIN, for each dual ports (a group that shares the same cores)
+ the cores will be divided half pinned for each port
:raises:
+ :exc:`STLError`
@@ -1964,7 +1993,7 @@ class STLClient(object):
# start traffic
self.logger.pre_cmd("Starting traffic on port(s) {0}:".format(ports))
- rc = self.__start(mult_obj, duration, ports, force)
+ rc = self.__start(mult_obj, duration, ports, force, core_mask)
self.logger.post_cmd(rc)
if not rc:
@@ -2647,7 +2676,8 @@ class STLClient(object):
parsing_opts.DURATION,
parsing_opts.TUNABLES,
parsing_opts.MULTIPLIER_STRICT,
- parsing_opts.DRY_RUN)
+ parsing_opts.DRY_RUN,
+ parsing_opts.PIN_CORES)
opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True)
if not opts:
@@ -2712,7 +2742,8 @@ class STLClient(object):
opts.mult,
opts.force,
opts.duration,
- opts.total)
+ opts.total,
+ core_mask = self.CORE_MASK_PIN if opts.pin_cores else self.CORE_MASK_SPLIT)
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 d239fc57..556a14d8 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
@@ -100,7 +100,7 @@ class Port(object):
# decorator to check server is readable (port not down and etc.)
def writeable(func):
- def func_wrapper(*args):
+ def func_wrapper(*args, **kwargs):
port = args[0]
if not port.is_up():
@@ -112,7 +112,7 @@ class Port(object):
if not port.is_writeable():
return port.err("{0} - port is not in a writeable state".format(func.__name__))
- return func(*args)
+ return func(*args, **kwargs)
return func_wrapper
@@ -396,16 +396,17 @@ class Port(object):
@writeable
- def start (self, mul, duration, force):
+ def start (self, mul, duration, force, mask):
if self.state == self.STATE_IDLE:
return self.err("unable to start traffic - no streams attached to port")
- params = {"handler": self.handler,
- "port_id": self.port_id,
- "mul": mul,
- "duration": duration,
- "force": force}
+ params = {"handler": self.handler,
+ "port_id": self.port_id,
+ "mul": mul,
+ "duration": duration,
+ "force": force,
+ "core_mask": mask if mask is not None else ((1 << 64) - 1)}
# 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 1bf0a9a4..b321c00b 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
@@ -210,8 +210,11 @@ class CTRexInfoGenerator(object):
("version", "{ver}, UUID: {uuid}".format(ver=global_stats.server_version.get("version", "N/A"),
uuid="N/A")),
- ("cpu_util.", "{0}% {1}".format( format_threshold(round_float(global_stats.get("m_cpu_util")), [85, 100], [0, 85]),
- global_stats.get_trend_gui("m_cpu_util", use_raw = True))),
+ ("cpu_util.", "{0}% @ {2} cores ({3} per port) {1}".format( format_threshold(round_float(global_stats.get("m_cpu_util")), [85, 100], [0, 85]),
+ global_stats.get_trend_gui("m_cpu_util", use_raw = True),
+ global_stats.system_info.get('dp_core_count'),
+ global_stats.system_info.get('dp_core_count_per_port'),
+ )),
("rx_cpu_util.", "{0}% {1}".format( format_threshold(round_float(global_stats.get("m_rx_cpu_util")), [85, 100], [0, 85]),
global_stats.get_trend_gui("m_rx_cpu_util", use_raw = True))),
@@ -234,7 +237,7 @@ class CTRexInfoGenerator(object):
("total_pps", "{0} {1}".format( global_stats.get("m_tx_pps", format=True, suffix="pkt/sec"),
global_stats.get_trend_gui("m_tx_pps"))),
- (" ", ""),
+ #(" ", ""),
("drop_rate", "{0}".format( format_num(global_stats.get("m_rx_drop_bps"),
suffix = 'b/sec',
@@ -422,21 +425,39 @@ class CTRexInfoGenerator(object):
def _generate_cpu_util_stats(self):
util_stats = self._util_stats_ref.get_stats(use_1sec_cache = True)
+
stats_table = text_tables.TRexTextTable()
if util_stats:
if 'cpu' not in util_stats:
raise Exception("Excepting 'cpu' section in stats %s" % util_stats)
cpu_stats = util_stats['cpu']
- hist_len = len(cpu_stats[0])
+ hist_len = len(cpu_stats[0]["history"])
avg_len = min(5, hist_len)
show_len = min(15, hist_len)
stats_table.header(['Thread', 'Avg', 'Latest'] + list(range(-1, 0 - show_len, -1)))
stats_table.set_cols_align(['l'] + ['r'] * (show_len + 1))
- stats_table.set_cols_width([8, 3, 6] + [3] * (show_len - 1))
+ stats_table.set_cols_width([10, 3, 6] + [3] * (show_len - 1))
stats_table.set_cols_dtype(['t'] * (show_len + 2))
+
for i in range(min(14, len(cpu_stats))):
- avg = int(round(sum(cpu_stats[i][:avg_len]) / avg_len))
- stats_table.add_row([i, avg] + cpu_stats[i][:show_len])
+ 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
+ if ports == [-1, -1]:
+ interfaces = "(IDLE)"
+ elif not -1 in ports:
+ interfaces = "({:},{:})".format(ports[0], ports[1])
+ else:
+ interfaces = "({:})".format(ports[0] if ports[0] != -1 else ports[1])
+
+ thread = "{:2} {:^7}".format(i, interfaces)
+ stats_table.add_row([thread, avg] + history[:show_len])
else:
stats_table.add_row(['No Data.'])
return {'cpu_util(%)': ExportableStats(None, stats_table)}
@@ -542,6 +563,7 @@ class CTRexInfoGenerator(object):
per_field_stats = OrderedDict([("owner", []),
("state", []),
("speed", []),
+ ("CPU util.", []),
("--", []),
("Tx bps L2", []),
("Tx bps L1", []),
@@ -1037,7 +1059,8 @@ class CPortStats(CTRexStats):
return {"owner": owner,
"state": "{0}".format(state),
"speed": self._port_obj.get_formatted_speed() if self._port_obj else '',
-
+ "CPU util.": "{0} {1}%".format(self.get_trend_gui("m_cpu_util", use_raw = True),
+ format_threshold(round_float(self.get("m_cpu_util")), [85, 100], [0, 85])) if self._port_obj else '' ,
"--": " ",
"---": " ",
"----": " ",
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 cfe8a93b..51265252 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
@@ -37,6 +37,7 @@ PROMISCUOUS_SWITCH = 21
TUNABLES = 22
REMOTE_FILE = 23
LOCKED = 24
+PIN_CORES = 25
GLOBAL_STATS = 50
PORT_STATS = 51
@@ -323,6 +324,11 @@ 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',