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 | 8 ++++++++
lnst/Slave/NetTestSlave.py | 7 +++++++
4 files changed, 22 insertions(+)
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py
index f81be3b..109cabc 100644
--- a/lnst/Controller/Machine.py
+++ b/lnst/Controller/Machine.py
@@ -980,6 +980,10 @@ class Interface(object):
self._devlink["port_index"])
return None
+ def get_ethtool_stats(self, stats_str):
+ return self._machine._rpc_call_x(self._netns, "get_ethtool_stats",
+ self._id, stats_str)
+
class StaticInterface(Interface):
""" Static interface
diff --git a/lnst/Controller/Task.py b/lnst/Controller/Task.py
index 6a765bb..228d81a 100644
--- a/lnst/Controller/Task.py
+++ b/lnst/Controller/Task.py
@@ -707,6 +707,9 @@ class InterfaceAPI(object):
def get_devlink_port_name(self):
return self._if.get_devlink_port_name()
+ def get_ethtool_stats(self, stats_str):
+ return self._if.get_ethtool_stats(stats_str)
+
class ModuleAPI(object):
""" An API class representing a module. """
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py
index 3dc3314..a69f0a2 100644
--- a/lnst/Slave/InterfaceManager.py
+++ b/lnst/Slave/InterfaceManager.py
@@ -760,3 +760,11 @@ class Device(object):
def slave_del(self, if_id):
if self._conf != None:
self._conf.slave_del(if_id)
+
+ def get_ethtool_stats(self, stats_str):
+ out, _ = exec_cmd("ethtool -S %s" % self._name)
+ match = re.search("^.*%s: ([0-9]*)$" % stats_str, out, re.MULTILINE)
+ if match is not None:
+ return int(match.group(1))
+ else:
+ return None
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index a7e92fa..43af0de 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -903,6 +903,13 @@ class SlaveMethods:
return False
return True
+ def get_ethtool_stats(self, if_id, stats_str):
+ 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(stats_str)
+
def enable_lldpad(self):
exec_cmd("service lldpad start")
return True
--
2.7.4