diff options
Diffstat (limited to 'scripts')
4 files changed, 180 insertions, 32 deletions
diff --git a/scripts/automation/trex_control_plane/client/trex_async_client.py b/scripts/automation/trex_control_plane/client/trex_async_client.py index 0a3afbe8..a2bb4752 100644 --- a/scripts/automation/trex_control_plane/client/trex_async_client.py +++ b/scripts/automation/trex_control_plane/client/trex_async_client.py @@ -46,6 +46,9 @@ class CTRexAsyncStats(object): if self.ref_point == None: self.ref_point = self.current + + def clear(self): + self.ref_point = self.current def get(self, field, format = False, suffix = ""): diff --git a/scripts/automation/trex_control_plane/client/trex_stateless_client.py b/scripts/automation/trex_control_plane/client/trex_stateless_client.py index 2db30daf..7be7392e 100755 --- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py +++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py @@ -148,6 +148,13 @@ class Port(object): STATE_STREAMS = 2 STATE_TX = 3 STATE_PAUSE = 4 + PortState = namedtuple('PortState', ['state_id', 'state_name']) + STATES_MAP = {STATE_DOWN: "DOWN", + STATE_IDLE: "IDLE", + STATE_STREAMS: "STREAMS", + STATE_TX: "ACTIVE", + STATE_PAUSE: "PAUSE"} + def __init__ (self, port_id, speed, driver, user, transmit): self.port_id = port_id @@ -399,6 +406,10 @@ class Port(object): return self.ok() + def get_port_state_name(self): + return self.STATES_MAP.get(self.state, "Unknown") + + ################# events handler ###################### def async_event_port_stopped (self): self.state = self.STATE_STREAMS @@ -423,7 +434,8 @@ class CTRexStatelessClient(object): self._async_client = CTRexAsyncClient(server, async_port, self) self.streams_db = CStreamsDB() - self.info_and_stats = trex_stats.CTRexInformationCenter({"server": server, + self.info_and_stats = trex_stats.CTRexInformationCenter(self.user, + {"server": server, "sync_port": sync_port, "async_port": async_port}, self.ports, @@ -885,7 +897,7 @@ class CTRexStatelessClient(object): active_ports = list(set(self.get_active_ports()).intersection(port_id_list)) if not active_ports: - msg = "No active traffic on porvided ports" + msg = "No active traffic on provided ports" print format_text(msg, 'bold') return RC_ERR(msg) @@ -896,6 +908,11 @@ class CTRexStatelessClient(object): return RC_OK() + def cmd_clear(self, port_id_list): + self.info_and_stats.clear(port_id_list) + return RC_OK() + + # pause cmd def cmd_pause (self, port_id_list): @@ -999,16 +1016,13 @@ class CTRexStatelessClient(object): return RC_OK() def cmd_stats(self, port_id_list, stats_mask=set()): - print port_id_list - print stats_mask stats_opts = trex_stats.ALL_STATS_OPTS.intersection(stats_mask) - print stats_opts stats_obj = {} for stats_type in stats_opts: - stats_obj.update(self.info_and_stats.generate_single_statistic(stats_type)) + stats_obj.update(self.info_and_stats.generate_single_statistic(port_id_list, stats_type)) return stats_obj - pass + ############## High Level API With Parser ################ def cmd_start_line (self, line): @@ -1090,6 +1104,19 @@ class CTRexStatelessClient(object): def cmd_reset_line (self, line): return self.cmd_reset() + def cmd_clear_line (self, line): + '''Clear cached local statistics\n''' + # define a parser + parser = parsing_opts.gen_parser(self, + "clear", + self.cmd_clear_line.__doc__, + parsing_opts.PORT_LIST_WITH_ALL) + + opts = parser.parse_args(line.split()) + + if opts is None: + return RC_ERR("bad command line parameters") + return self.cmd_clear(opts.ports) def cmd_stats_line (self, line): '''Fetch statistics from TRex server by port\n''' @@ -1105,10 +1132,11 @@ class CTRexStatelessClient(object): if opts is None: return RC_ERR("bad command line parameters") - print opts - print self.get_global_stats() # determine stats mask - mask = self._get_mask_keys(**self._filter_namespace_args(opts, ['p', 'g', 'ps'])) + mask = self._get_mask_keys(**self._filter_namespace_args(opts, trex_stats.ALL_STATS_OPTS)) + if not mask: + # set to show all stats if no filter was given + mask = trex_stats.ALL_STATS_OPTS # get stats objects, as dictionary stats = self.cmd_stats(opts.ports, mask) # print stats to screen diff --git a/scripts/automation/trex_control_plane/common/trex_stats.py b/scripts/automation/trex_control_plane/common/trex_stats.py index bf5ba2bb..ec455730 100755 --- a/scripts/automation/trex_control_plane/common/trex_stats.py +++ b/scripts/automation/trex_control_plane/common/trex_stats.py @@ -1,6 +1,8 @@ #!/router/bin/python from collections import namedtuple, OrderedDict from client_utils import text_tables +from common.text_opts import format_text +from client.trex_async_client import CTRexAsyncStats import copy GLOBAL_STATS = 'g' @@ -12,7 +14,8 @@ ExportableStats = namedtuple('ExportableStats', ['raw_data', 'text_table']) class CTRexInformationCenter(object): - def __init__(self, connection_info, ports_ref, async_stats_ref): + def __init__(self, username, connection_info, ports_ref, async_stats_ref): + self.user = username self.connection_info = connection_info self.server_version = None self.system_info = None @@ -26,14 +29,20 @@ class CTRexInformationCenter(object): # else: # return None - def generate_single_statistic(self, statistic_type): + def clear(self, port_id_list): + self._async_stats.get_general_stats().clear() + for port_id in port_id_list: + self._async_stats.get_port_stats(port_id).clear() + pass + + def generate_single_statistic(self, port_id_list, statistic_type): if statistic_type == GLOBAL_STATS: return self._generate_global_stats() elif statistic_type == PORT_STATS: - # return generate_global_stats() + return self._generate_port_stats(port_id_list) pass elif statistic_type == PORT_STATUS: - pass + return self._generate_port_status(port_id_list) else: # ignore by returning empty object return {} @@ -43,26 +52,11 @@ class CTRexInformationCenter(object): return_stats_data = \ OrderedDict([("connection", "{host}, Port {port}".format(host=self.connection_info.get("server"), port=self.connection_info.get("sync_port"))), - ("version", self.server_version.get("version", "N/A")), - ("cpu_util", stats_obj.get("m_cpu_util")), + ("version", "{ver}, UUID: {uuid}".format(ver=self.server_version.get("version", "N/A"), + uuid="N/A")), + ("cpu_util", "{0}%".format(stats_obj.get("m_cpu_util"))), ("total_tx", stats_obj.get("m_tx_bps", format=True, suffix="b/sec")), - # {'m_tx_bps': stats_obj.get("m_tx_bps", format= True, suffix= "b/sec"), - # 'm_tx_pps': stats_obj.get("m_tx_pps", format= True, suffix= "pkt/sec"), - # 'm_total_tx_bytes':stats_obj.get_rel("m_total_tx_bytes", - # format= True, - # suffix = "B"), - # 'm_total_tx_pkts': stats_obj.get_rel("m_total_tx_pkts", - # format= True, - # suffix = "pkts")}, ("total_rx", stats_obj.get("m_rx_bps", format=True, suffix="b/sec")), - # {'m_rx_bps': stats_obj.get("m_rx_bps", format= True, suffix= "b/sec"), - # 'm_rx_pps': stats_obj.get("m_rx_pps", format= True, suffix= "pkt/sec"), - # 'm_total_rx_bytes': stats_obj.get_rel("m_total_rx_bytes", - # format= True, - # suffix = "B"), - # 'm_total_rx_pkts': stats_obj.get_rel("m_total_rx_pkts", - # format= True, - # suffix = "pkts")}, ("total_pps", stats_obj.format_num(stats_obj.get("m_tx_pps") + stats_obj.get("m_rx_pps"), suffix="pkt/sec")), ("total_streams", sum([len(port.streams) @@ -81,6 +75,122 @@ class CTRexInformationCenter(object): return {"global_statistics": ExportableStats(return_stats_data, stats_table)} + def _generate_port_stats(self, port_id_list): + relevant_ports = self.__get_relevant_ports(port_id_list) + + return_stats_data = {} + per_field_stats = OrderedDict([("owner", []), + ("active", []), + ("tx-bytes", []), + ("rx-bytes", []), + ("tx-pkts", []), + ("rx-pkts", []), + ("tx-errors", []), + ("rx-errors", []), + ("tx-BW", []), + ("rx-BW", []) + ] + ) + + for port_obj in relevant_ports: + # fetch port data + port_stats = self._async_stats.get_port_stats(port_obj.port_id) + + owner = self.user + active = "YES" if port_obj.is_active() else "NO" + tx_bytes = port_stats.get_rel("obytes", format = True, suffix = "B") + rx_bytes = port_stats.get_rel("ibytes", format = True, suffix = "B") + tx_pkts = port_stats.get_rel("opackets", format = True, suffix = "pkts") + rx_pkts = port_stats.get_rel("ipackets", format = True, suffix = "pkts") + tx_errors = port_stats.get_rel("oerrors", format = True) + rx_errors = port_stats.get_rel("ierrors", format = True) + tx_bw = port_stats.get("m_total_tx_bps", format = True, suffix = "bps") + rx_bw = port_stats.get("m_total_rx_bps", format = True, suffix = "bps") + + # populate to data structures + return_stats_data[port_obj.port_id] = {"owner": owner, + "active": active, + "tx-bytes": tx_bytes, + "rx-bytes": rx_bytes, + "tx-pkts": tx_pkts, + "rx-pkts": rx_pkts, + "tx-errors": tx_errors, + "rx-errors": rx_errors, + "Tx-BW": tx_bw, + "Rx-BW": rx_bw + } + per_field_stats["owner"].append(owner) + per_field_stats["active"].append(active) + per_field_stats["tx-bytes"].append(tx_bytes) + per_field_stats["rx-bytes"].append(rx_bytes) + per_field_stats["tx-pkts"].append(tx_pkts) + per_field_stats["rx-pkts"].append(rx_pkts) + per_field_stats["tx-errors"].append(tx_errors) + per_field_stats["rx-errors"].append(rx_errors) + per_field_stats["tx-BW"].append(tx_bw) + per_field_stats["rx-BW"].append(rx_bw) + + stats_table = text_tables.TRexTextTable() + stats_table.set_cols_align(["l"] + ["r"]*len(relevant_ports)) + stats_table.add_rows([[k] + v + for k, v in per_field_stats.iteritems()], + header=False) + stats_table.header(["port"] + [port.port_id + for port in relevant_ports]) + + return {"port_statistics": ExportableStats(return_stats_data, stats_table)} + + def _generate_port_status(self, port_id_list): + relevant_ports = self.__get_relevant_ports(port_id_list) + + return_stats_data = {} + per_field_status = OrderedDict([("port-type", []), + ("maximum", []), + ("port-status", []) + ] + ) + + for port_obj in relevant_ports: + # fetch port data + port_stats = self._async_stats.get_port_stats(port_obj.port_id) + + + port_type = port_obj.driver + maximum = "{speed} Gb/s".format(speed=port_obj.speed)#CTRexAsyncStats.format_num(port_obj.get_speed_bps(), suffix="bps") + port_status = port_obj.get_port_state_name() + + # populate to data structures + return_stats_data[port_obj.port_id] = {"port-type": port_type, + "maximum": maximum, + "port-status": port_status, + } + per_field_status["port-type"].append(port_type) + per_field_status["maximum"].append(maximum) + per_field_status["port-status"].append(port_status) + + stats_table = text_tables.TRexTextTable() + stats_table.set_cols_align(["l"] + ["c"]*len(relevant_ports)) + stats_table.add_rows([[k] + v + for k, v in per_field_status.iteritems()], + header=False) + stats_table.header(["port"] + [port.port_id + for port in relevant_ports]) + + return {"port_status": ExportableStats(return_stats_data, stats_table)} + + def __get_relevant_ports(self, port_id_list): + # fetch owned ports + ports = [port_obj + for port_obj in self._ports + if port_obj.is_acquired() and port_obj.port_id in port_id_list] + # display only the first FOUR options, by design + if len(ports) > 4: + print format_text("[WARNING]: ", 'magenta', 'bold'), format_text("displaying up to 4 ports", 'magenta') + ports = ports[:4] + return ports + + + class CTRexStatsManager(object): diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 3ddfd8c6..9236ce98 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -350,6 +350,13 @@ class TRexConsole(TRexGeneralCmd): def help_stats(self): self.do_stats("-h") + def do_clear(self, line): + '''Clear cached local statistics\n''' + self.stateless_client.cmd_clear_line(line) + + def help_clear(self): + self.do_clear("-h") + def help_events (self): self.do_events("-h") |