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