From: Ido Schimmel <idosch(a)mellanox.com>
While the standard statistics available via netlink provide information
about rx/tx packets/bytes, ethtool statistics provide a much better
visibility into the device, such as per-priority and per-TC counters.
These counters are very useful for debugging purposes and testing and
therefore should be available in LNST recipes.
While each vendor exposes this statistics using a different string, it's
still possible to write generic recipes using them (assuming they are
available). The vendor-specific statistics string can be made available
to the recipe using an alias passed down from the controller. For
example:
$ lnst-ctl -A tx_prio_stats=tx_frames_prio_ run recipe.xml
Signed-off-by: Ido Schimmel <idosch(a)mellanox.com>
---
lnst/Controller/Machine.py | 4 ++++
lnst/Controller/Task.py | 3 +++
lnst/Slave/InterfaceManager.py | 10 ++++++++++
lnst/Slave/NetTestSlave.py | 7 +++++++
4 files changed, 24 insertions(+)
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py
index 1b2b09f..138c841 100644
--- a/lnst/Controller/Machine.py
+++ b/lnst/Controller/Machine.py
@@ -982,6 +982,10 @@ class Interface(object):
self._devlink["port_index"])
return None
+ def get_ethtool_stats(self):
+ return self._machine._rpc_call_x(self._netns, "get_ethtool_stats",
+ self._id)
+
class StaticInterface(Interface):
""" Static interface
diff --git a/lnst/Controller/Task.py b/lnst/Controller/Task.py
index 80f941a..26aa54e 100644
--- a/lnst/Controller/Task.py
+++ b/lnst/Controller/Task.py
@@ -710,6 +710,9 @@ class InterfaceAPI(object):
def get_devlink_port_name(self):
return self._if.get_devlink_port_name()
+ def get_ethtool_stats(self):
+ return self._if.get_ethtool_stats()
+
class ModuleAPI(object):
""" An API class representing a module. """
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py
index 3dc3314..612d04a 100644
--- a/lnst/Slave/InterfaceManager.py
+++ b/lnst/Slave/InterfaceManager.py
@@ -760,3 +760,13 @@ class Device(object):
def slave_del(self, if_id):
if self._conf != None:
self._conf.slave_del(if_id)
+
+ def get_ethtool_stats(self):
+ stdout, _ = exec_cmd("ethtool -S %s" % self._name)
+
+ d = {}
+ # First and last lines don't contain stats.
+ for line in stdout.split('\n')[1:-1]:
+ stat, count = line.split(':')
+ d[stat.strip()] = int(count)
+ return d
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index 9fc08fb..9b130b3 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -924,6 +924,13 @@ class SlaveMethods:
def get_num_cpus(self):
return int(os.sysconf('SC_NPROCESSORS_ONLN'))
+ def get_ethtool_stats(self, if_id):
+ dev = self._if_manager.get_mapped_device(if_id)
+ if not dev:
+ logging.error("Device with id '%s' not found." % if_id)
+ return False
+ return dev.get_ethtool_stats()
+
class ServerHandler(ConnectionHandler):
def __init__(self, addr):
super(ServerHandler, self).__init__()
--
2.7.4