11#include <Python.h>
22
33#include <errno.h>
4+ #include <stddef.h>
5+ #include <stdint.h>
46#include <unistd.h>
57#include <sys/socket.h>
68#include <net/if.h>
@@ -16,6 +18,8 @@ typedef __uint8_t u8;
1618#include "ethtool-copy.h"
1719#include <linux/sockios.h> /* for SIOCETHTOOL */
1820
21+ #define ARRAY_SIZE (arr ) (sizeof(arr) / sizeof((arr)[0]))
22+
1923#define _PATH_PROCNET_DEV "/proc/net/dev"
2024
2125static PyObject * get_active_devices (PyObject * self __unused , PyObject * args __unused )
@@ -405,11 +409,12 @@ static PyObject *get_businfo(PyObject *self __unused, PyObject *args)
405409 return PyString_FromString (((struct ethtool_drvinfo * )buf )-> bus_info );
406410}
407411
408- static int send_command (int cmd , char * devname , struct ethtool_value * eval )
412+ static int send_command (int cmd , char * devname , void * value )
409413{
410414 /* Setup our control structures. */
411415 int fd , err ;
412416 struct ifreq ifr ;
417+ struct ethtool_value * eval = value ;
413418
414419 memset (& ifr , 0 , sizeof (ifr ));
415420 strncpy (& ifr .ifr_name [0 ], devname , IFNAMSIZ );
@@ -436,24 +441,27 @@ static int send_command(int cmd, char *devname, struct ethtool_value *eval)
436441 return err ;
437442}
438443
439- static int get_dev_value (int cmd , PyObject * args , void * value , size_t len )
444+ static int get_dev_value (int cmd , PyObject * args , void * value )
440445{
441446 char * devname ;
442447 int err = -1 ;
443448
444- if (PyArg_ParseTuple (args , "s" , & devname )) {
445- struct ethtool_value eval ;
449+ if (PyArg_ParseTuple (args , "s" , & devname ))
446450 /* Setup our control structures. */
447- err = send_command (cmd , devname , & eval );
448- memcpy (value , & eval .data , len );
449- }
451+ err = send_command (cmd , devname , value );
450452
451453 return err ;
452454}
453455
454456static int get_dev_int_value (int cmd , PyObject * args , int * value )
455457{
456- return get_dev_value (cmd , args , value , sizeof (* value ));
458+ struct ethtool_value eval ;
459+ int rc = get_dev_value (cmd , args , & eval );
460+
461+ if (rc == 0 )
462+ * value = * (int * )& eval .data ;
463+
464+ return rc ;
457465}
458466
459467static int dev_set_int_value (int cmd , PyObject * args )
@@ -519,6 +527,92 @@ static PyObject *get_sg(PyObject *self __unused, PyObject *args)
519527 return Py_BuildValue ("b" , value );
520528}
521529
530+ struct struct_desc {
531+ char * name ;
532+ unsigned short offset ;
533+ unsigned short size ;
534+ };
535+
536+ #define member_desc (type , member_name ) { \
537+ .name = #member_name, \
538+ .offset = offsetof(type, member_name), \
539+ .size = sizeof(((type *)0)->member_name), }
540+
541+ struct struct_desc ethtool_coalesce_desc [] = {
542+ member_desc (struct ethtool_coalesce , rx_coalesce_usecs ),
543+ member_desc (struct ethtool_coalesce , rx_max_coalesced_frames ),
544+ member_desc (struct ethtool_coalesce , rx_coalesce_usecs_irq ),
545+ member_desc (struct ethtool_coalesce , rx_max_coalesced_frames_irq ),
546+ member_desc (struct ethtool_coalesce , tx_coalesce_usecs ),
547+ member_desc (struct ethtool_coalesce , tx_max_coalesced_frames ),
548+ member_desc (struct ethtool_coalesce , tx_coalesce_usecs_irq ),
549+ member_desc (struct ethtool_coalesce , tx_max_coalesced_frames_irq ),
550+ member_desc (struct ethtool_coalesce , stats_block_coalesce_usecs ),
551+ member_desc (struct ethtool_coalesce , use_adaptive_rx_coalesce ),
552+ member_desc (struct ethtool_coalesce , use_adaptive_tx_coalesce ),
553+ member_desc (struct ethtool_coalesce , pkt_rate_low ),
554+ member_desc (struct ethtool_coalesce , rx_coalesce_usecs_low ),
555+ member_desc (struct ethtool_coalesce , rx_max_coalesced_frames_low ),
556+ member_desc (struct ethtool_coalesce , tx_coalesce_usecs_low ),
557+ member_desc (struct ethtool_coalesce , tx_max_coalesced_frames_low ),
558+ member_desc (struct ethtool_coalesce , pkt_rate_high ),
559+ member_desc (struct ethtool_coalesce , rx_coalesce_usecs_high ),
560+ member_desc (struct ethtool_coalesce , rx_max_coalesced_frames_high ),
561+ member_desc (struct ethtool_coalesce , tx_coalesce_usecs_high ),
562+ member_desc (struct ethtool_coalesce , tx_max_coalesced_frames_high ),
563+ member_desc (struct ethtool_coalesce , rate_sample_interval ),
564+ };
565+
566+ static PyObject * __struct_desc_create_dict (struct struct_desc * table ,
567+ int nr_entries , void * values )
568+ {
569+ int i ;
570+ PyObject * dict = PyDict_New ();
571+
572+ if (dict == NULL )
573+ goto out ;
574+
575+ for (i = 0 ; i < nr_entries ; ++ i ) {
576+ struct struct_desc * d = & table [i ];
577+ PyObject * objval = NULL ;
578+ void * val = values + d -> offset ;
579+
580+ switch (d -> size ) {
581+ case sizeof (uint32_t ):
582+ objval = PyInt_FromLong (* (uint32_t * )val );
583+ break ;
584+ }
585+
586+ if (objval == NULL )
587+ goto free_dict ;
588+
589+ if (PyDict_SetItemString (dict , d -> name , objval ) != 0 ) {
590+ Py_DECREF (objval );
591+ goto free_dict ;
592+ }
593+
594+ Py_DECREF (objval );
595+ }
596+ out :
597+ return dict ;
598+ free_dict :
599+ goto out ;
600+ dict = NULL ;
601+ }
602+
603+ #define struct_desc_create_dict (table , values ) \
604+ __struct_desc_create_dict(table, ARRAY_SIZE(table), values)
605+
606+ static PyObject * get_coalesce (PyObject * self __unused , PyObject * args )
607+ {
608+ struct ethtool_coalesce coal ;
609+
610+ if (get_dev_value (ETHTOOL_GCOALESCE , args , & coal ) < 0 )
611+ return NULL ;
612+
613+ return struct_desc_create_dict (ethtool_coalesce_desc , & coal );
614+ }
615+
522616static struct PyMethodDef PyEthModuleMethods [] = {
523617 {
524618 .ml_name = "get_module" ,
@@ -550,6 +644,11 @@ static struct PyMethodDef PyEthModuleMethods[] = {
550644 .ml_meth = (PyCFunction )get_broadcast ,
551645 .ml_flags = METH_VARARGS ,
552646 },
647+ {
648+ .ml_name = "get_coalesce" ,
649+ .ml_meth = (PyCFunction )get_coalesce ,
650+ .ml_flags = METH_VARARGS ,
651+ },
553652 {
554653 .ml_name = "get_devices" ,
555654 .ml_meth = (PyCFunction )get_devices ,
0 commit comments