summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xethtool-cmd.py82
-rw-r--r--python-ethtool/ethtool.c115
2 files changed, 188 insertions, 9 deletions
diff --git a/ethtool-cmd.py b/ethtool-cmd.py
index e828bce..f931efa 100755
--- a/ethtool-cmd.py
+++ b/ethtool-cmd.py
@@ -17,6 +17,7 @@ import getopt, ethtool, sys
def usage():
print '''Usage: ethtool [OPTIONS] [<interface>]
-h|--help Give this help list
+ -c|--show-coalesce Show coalesce options
-i|--driver Show driver information
-k|--show-offload Get protocol offload information
-K|--offload Set protocol offload
@@ -27,6 +28,81 @@ tab = ""
def printtab(msg):
print tab + msg
+ethtool_coalesce_msgs = (
+ ( "stats-block-usecs",
+ "stats_block_coalesce_usecs" ),
+ ( "sample-interval",
+ "rate_sample_interval" ),
+ ( "pkt-rate-low",
+ "pkt_rate_low"),
+ ( "pkt-rate-high",
+ "pkt_rate_high"),
+ ( "\n" ),
+ ( "rx-usecs",
+ "rx_coalesce_usecs"),
+ ( "rx-frames",
+ "rx_max_coalesced_frames"),
+ ( "rx-usecs-irq",
+ "rx_coalesce_usecs_irq"),
+ ( "rx-frames-irq",
+ "rx_max_coalesced_frames_irq"),
+ ( "\n" ),
+ ( "tx-usecs",
+ "tx_coalesce_usecs"),
+ ( "tx-frames",
+ "tx_max_coalesced_frames"),
+ ( "tx-usecs-irq",
+ "tx_coalesce_usecs_irq"),
+ ( "tx-frames-irq",
+ "tx_max_coalesced_frames_irq"),
+ ( "\n" ),
+ ( "rx-usecs-low",
+ "rx_coalesce_usecs_low"),
+ ( "rx-frame-low",
+ "rx_max_coalesced_frames_low"),
+ ( "tx-usecs-low",
+ "tx_coalesce_usecs_low"),
+ ( "tx-frame-low",
+ "tx_max_coalesced_frames_low"),
+ ( "\n" ),
+ ( "rx-usecs-high",
+ "rx_coalesce_usecs_high"),
+ ( "rx-frame-high",
+ "rx_max_coalesced_frames_high"),
+ ( "tx-usecs-high",
+ "tx_coalesce_usecs_high"),
+ ( "tx-frame-high",
+ "tx_max_coalesced_frames_high"),
+)
+
+def show_coalesce(interface, args = None):
+ printtab("Coalesce parameters for %s:" % interface)
+ try:
+ coal = ethtool.get_coalesce(interface)
+ except IOError:
+ printtab(" NOT supported!")
+ return
+
+ printtab("Adaptive RX: %s TX: %s" % (coal["use_adaptive_rx_coalesce"] and "on" or "off",
+ coal["use_adaptive_tx_coalesce"] and "on" or "off"))
+
+ printed = [ "use_adaptive_rx_coalesce",
+ "use_adaptive_tx_coalesce" ]
+ for tunable in ethtool_coalesce_msgs:
+ if tunable[0] == '\n':
+ print
+ else:
+ printtab("%s: %s" % (tunable[0], coal[tunable[1]]))
+ printed.append(tunable[1])
+
+ coalkeys = coal.keys()
+ if len(coalkeys) != len(printed):
+ print
+ for tunable in coalkeys:
+ if tunable not in printed:
+ printtab("%s %s" % (tunable, coal[tunable]))
+
+
def show_offload(interface, args = None):
try:
sg = ethtool.get_sg(interface) and "on" or "off"
@@ -101,8 +177,9 @@ def run_cmd_noargs(cmd, args):
def main():
try:
opts, args = getopt.getopt(sys.argv[1:],
- "hikK",
+ "hcikK",
("help",
+ "show-coalesce",
"driver",
"show-offload",
"offload"))
@@ -119,6 +196,9 @@ def main():
if o in ("-h", "--help"):
usage()
return
+ elif o in ("-c", "--show-coalesce"):
+ run_cmd_noargs(show_coalesce, args)
+ break
elif o in ("-i", "--driver"):
run_cmd_noargs(show_driver, args)
break
diff --git a/python-ethtool/ethtool.c b/python-ethtool/ethtool.c
index bf8fc45..4dd8fdf 100644
--- a/python-ethtool/ethtool.c
+++ b/python-ethtool/ethtool.c
@@ -1,6 +1,8 @@
#include <Python.h>
#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
#include <unistd.h>
#include <sys/socket.h>
#include <net/if.h>
@@ -16,6 +18,8 @@ typedef __uint8_t u8;
#include "ethtool-copy.h"
#include <linux/sockios.h> /* for SIOCETHTOOL */
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
#define _PATH_PROCNET_DEV "/proc/net/dev"
static PyObject *get_active_devices(PyObject *self __unused, PyObject *args __unused)
@@ -405,11 +409,12 @@ static PyObject *get_businfo(PyObject *self __unused, PyObject *args)
return PyString_FromString(((struct ethtool_drvinfo *)buf)->bus_info);
}
-static int send_command(int cmd, char *devname, struct ethtool_value *eval)
+static int send_command(int cmd, char *devname, void *value)
{
/* Setup our control structures. */
int fd, err;
struct ifreq ifr;
+ struct ethtool_value *eval = value;
memset(&ifr, 0, sizeof(ifr));
strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
@@ -436,24 +441,27 @@ static int send_command(int cmd, char *devname, struct ethtool_value *eval)
return err;
}
-static int get_dev_value(int cmd, PyObject *args, void *value, size_t len)
+static int get_dev_value(int cmd, PyObject *args, void *value)
{
char *devname;
int err = -1;
- if (PyArg_ParseTuple(args, "s", &devname)) {
- struct ethtool_value eval;
+ if (PyArg_ParseTuple(args, "s", &devname))
/* Setup our control structures. */
- err = send_command(cmd, devname, &eval);
- memcpy(value, &eval.data, len);
- }
+ err = send_command(cmd, devname, value);
return err;
}
static int get_dev_int_value(int cmd, PyObject *args, int *value)
{
- return get_dev_value(cmd, args, value, sizeof(*value));
+ struct ethtool_value eval;
+ int rc = get_dev_value(cmd, args, &eval);
+
+ if (rc == 0)
+ *value = *(int *)&eval.data;
+
+ return rc;
}
static int dev_set_int_value(int cmd, PyObject *args)
@@ -519,6 +527,92 @@ static PyObject *get_sg(PyObject *self __unused, PyObject *args)
return Py_BuildValue("b", value);
}
+struct struct_desc {
+ char *name;
+ unsigned short offset;
+ unsigned short size;
+};
+
+#define member_desc(type, member_name) { \
+ .name = #member_name, \
+ .offset = offsetof(type, member_name), \
+ .size = sizeof(((type *)0)->member_name), }
+
+struct struct_desc ethtool_coalesce_desc[] = {
+ member_desc(struct ethtool_coalesce, rx_coalesce_usecs),
+ member_desc(struct ethtool_coalesce, rx_max_coalesced_frames),
+ member_desc(struct ethtool_coalesce, rx_coalesce_usecs_irq),
+ member_desc(struct ethtool_coalesce, rx_max_coalesced_frames_irq),
+ member_desc(struct ethtool_coalesce, tx_coalesce_usecs),
+ member_desc(struct ethtool_coalesce, tx_max_coalesced_frames),
+ member_desc(struct ethtool_coalesce, tx_coalesce_usecs_irq),
+ member_desc(struct ethtool_coalesce, tx_max_coalesced_frames_irq),
+ member_desc(struct ethtool_coalesce, stats_block_coalesce_usecs),
+ member_desc(struct ethtool_coalesce, use_adaptive_rx_coalesce),
+ member_desc(struct ethtool_coalesce, use_adaptive_tx_coalesce),
+ member_desc(struct ethtool_coalesce, pkt_rate_low),
+ member_desc(struct ethtool_coalesce, rx_coalesce_usecs_low),
+ member_desc(struct ethtool_coalesce, rx_max_coalesced_frames_low),
+ member_desc(struct ethtool_coalesce, tx_coalesce_usecs_low),
+ member_desc(struct ethtool_coalesce, tx_max_coalesced_frames_low),
+ member_desc(struct ethtool_coalesce, pkt_rate_high),
+ member_desc(struct ethtool_coalesce, rx_coalesce_usecs_high),
+ member_desc(struct ethtool_coalesce, rx_max_coalesced_frames_high),
+ member_desc(struct ethtool_coalesce, tx_coalesce_usecs_high),
+ member_desc(struct ethtool_coalesce, tx_max_coalesced_frames_high),
+ member_desc(struct ethtool_coalesce, rate_sample_interval),
+};
+
+static PyObject *__struct_desc_create_dict(struct struct_desc *table,
+ int nr_entries, void *values)
+{
+ int i;
+ PyObject *dict = PyDict_New();
+
+ if (dict == NULL)
+ goto out;
+
+ for (i = 0; i < nr_entries; ++i) {
+ struct struct_desc *d = &table[i];
+ PyObject *objval = NULL;
+ void *val = values + d->offset;
+
+ switch (d->size) {
+ case sizeof(uint32_t):
+ objval = PyInt_FromLong(*(uint32_t *)val);
+ break;
+ }
+
+ if (objval == NULL)
+ goto free_dict;
+
+ if (PyDict_SetItemString(dict, d->name, objval) != 0) {
+ Py_DECREF(objval);
+ goto free_dict;
+ }
+
+ Py_DECREF(objval);
+ }
+out:
+ return dict;
+free_dict:
+ goto out;
+ dict = NULL;
+}
+
+#define struct_desc_create_dict(table, values) \
+ __struct_desc_create_dict(table, ARRAY_SIZE(table), values)
+
+static PyObject *get_coalesce(PyObject *self __unused, PyObject *args)
+{
+ struct ethtool_coalesce coal;
+
+ if (get_dev_value(ETHTOOL_GCOALESCE, args, &coal) < 0)
+ return NULL;
+
+ return struct_desc_create_dict(ethtool_coalesce_desc, &coal);
+}
+
static struct PyMethodDef PyEthModuleMethods[] = {
{
.ml_name = "get_module",
@@ -551,6 +645,11 @@ static struct PyMethodDef PyEthModuleMethods[] = {
.ml_flags = METH_VARARGS,
},
{
+ .ml_name = "get_coalesce",
+ .ml_meth = (PyCFunction)get_coalesce,
+ .ml_flags = METH_VARARGS,
+ },
+ {
.ml_name = "get_devices",
.ml_meth = (PyCFunction)get_devices,
.ml_flags = METH_VARARGS,