diff options
author | 2016-08-15 15:33:51 +0300 | |
---|---|---|
committer | 2016-08-15 16:33:41 +0300 | |
commit | 25aa665b7e5a5e8747735aaaa5a00dba11b21067 (patch) | |
tree | 75f6fc67584dbcba8a72b44ed5384f24e0eef698 /scripts/automation/trex_control_plane/stl/trex_stl_lib | |
parent | ba7b5dff853a3b11b0cc2e7b29cfc1cd99e606f7 (diff) |
TUI screen buffer
Diffstat (limited to 'scripts/automation/trex_control_plane/stl/trex_stl_lib')
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 |