summaryrefslogtreecommitdiffstats
path: root/python-ethtool/ethtool.c
diff options
context:
space:
mode:
Diffstat (limited to 'python-ethtool/ethtool.c')
-rw-r--r--python-ethtool/ethtool.c115
1 files changed, 107 insertions, 8 deletions
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,