summaryrefslogtreecommitdiffstats
path: root/scripts/automation/trex_control_plane
diff options
context:
space:
mode:
authorDan Klein <danklein10@gmail.com>2015-11-29 00:25:07 +0200
committerDan Klein <danklein10@gmail.com>2015-11-29 00:25:07 +0200
commita609111bc37ef88f14d4f2ebf7cd186b04b86402 (patch)
tree2b166dca6d9763ae74328a9e279c118f28b9b00a /scripts/automation/trex_control_plane
parent4486f9863e7f541ce5b6b4ff2bce6c6f7c41fcd2 (diff)
Supports all desired stats option, plus clearing option
Diffstat (limited to 'scripts/automation/trex_control_plane')
-rw-r--r--scripts/automation/trex_control_plane/client/trex_async_client.py3
-rwxr-xr-xscripts/automation/trex_control_plane/client/trex_stateless_client.py48
-rwxr-xr-xscripts/automation/trex_control_plane/common/trex_stats.py154
-rwxr-xr-xscripts/automation/trex_control_plane/console/trex_console.py7
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")