Instantly share code, notes, and snippets.

@yunazuno /ethtool.py
Last active Jun 17, 2018

Embed
What would you like to do?
ethtool -S in Python
#!/usr/bin/env python
import socket
import fcntl
import struct
import array
SIOCETHTOOL = 0x8946
ETHTOOL_GSTRINGS = 0x0000001b
ETHTOOL_GSSET_INFO = 0x00000037
ETHTOOL_GSTATS = 0x0000001d
ETH_SS_STATS = 0x1
ETH_GSTRING_LEN = 32
class Ethtool(object):
def __init__(self, ifname):
self.ifname = ifname
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
def _send_ioctl(self, data):
ifr = struct.pack('16sP', self.ifname.encode("utf-8"), data.buffer_info()[0])
return fcntl.ioctl(self._sock.fileno(), SIOCETHTOOL, ifr)
def get_gstringset(self, set_id):
sset_info = array.array('B', struct.pack("IIQI", ETHTOOL_GSSET_INFO, 0, 1 << set_id, 0))
self._send_ioctl(sset_info)
sset_mask, sset_len = struct.unpack("8xQI", sset_info)
if sset_mask == 0:
sset_len = 0
strings = array.array("B", struct.pack("III", ETHTOOL_GSTRINGS, ETH_SS_STATS, sset_len))
strings.extend(b'\x00' * sset_len * ETH_GSTRING_LEN)
self._send_ioctl(strings)
for i in range(sset_len):
offset = 12 + ETH_GSTRING_LEN * i
s = strings[offset:offset+ETH_GSTRING_LEN].tobytes().partition(b'\x00')[0].decode("utf-8")
yield s
def get_nic_stats(self):
strings = list(self.get_gstringset(ETH_SS_STATS))
n_stats = len(strings)
stats = array.array("B", struct.pack("II", ETHTOOL_GSTATS, n_stats))
stats.extend(struct.pack('Q', 0) * n_stats)
self._send_ioctl(stats)
for i in range(n_stats):
offset = 8 + 8 * i
value = struct.unpack('Q', stats[offset:offset+8])[0]
yield (strings[i], value)
if __name__ == '__main__':
import sys
ifname = sys.argv[1]
et = Ethtool(ifname)
for k, v in et.get_nic_stats():
print(f"{k}: {v}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment