summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sommerseth <davids@redhat.com>2009-09-04 19:36:23 +0200
committerDavid Sommerseth <davids@redhat.com>2009-09-04 19:36:23 +0200
commit0be405b9c6245b59489b7e6987af0dc56ded1406 (patch)
tree2850c36fde83eae17bb721343d0db9d260039e77
parente957168cde93978d62fc9908325d32ed432fe33e (diff)
downloadpython-ethtool-0be405b9c6245b59489b7e6987af0dc56ded1406.tar.gz
python-ethtool-0be405b9c6245b59489b7e6987af0dc56ded1406.tar.xz
python-ethtool-0be405b9c6245b59489b7e6987af0dc56ded1406.zip
First cut at a python etherinfo class in C. Does nothing useful yet.
-rw-r--r--python-ethtool/etherinfo.h1
-rw-r--r--python-ethtool/etherinfo_obj.c121
-rw-r--r--python-ethtool/etherinfo_obj.h101
-rw-r--r--python-ethtool/etherinfo_struct.h23
-rw-r--r--python-ethtool/ethtool.c19
-rw-r--r--setup.py3
6 files changed, 264 insertions, 4 deletions
diff --git a/python-ethtool/etherinfo.h b/python-ethtool/etherinfo.h
index 6dfd8fa..996bd45 100644
--- a/python-ethtool/etherinfo.h
+++ b/python-ethtool/etherinfo.h
@@ -31,6 +31,7 @@ struct etherinfo {
};
struct etherinfo *get_etherinfo();
+void free_etherinfo(struct etherinfo *ptr);
void dump_etherinfo(FILE *, struct etherinfo *);
#endif
diff --git a/python-ethtool/etherinfo_obj.c b/python-ethtool/etherinfo_obj.c
new file mode 100644
index 0000000..5e9878c
--- /dev/null
+++ b/python-ethtool/etherinfo_obj.c
@@ -0,0 +1,121 @@
+/**
+ * @file etherinfo_obj.c
+ * @author David Sommerseth <davids@redhat.com>
+ * @date Fri Sep 4 18:41:28 2009
+ *
+ * @brief Python ethtool.etherinfo class functions.
+ *
+ */
+
+#include <Python.h>
+#include "structmember.h"
+#include "etherinfo.h"
+#include "etherinfo_struct.h"
+
+
+/**
+ * ethtool.etherinfo deallocator - cleans up when a object is deleted
+ *
+ * @param self etherinfo_py object structure
+ */
+void _ethtool_etherinfo_dealloc(etherinfo_py *self)
+{
+ if( self->info ) {
+ free_etherinfo(self->info);
+ }
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/**
+ * ethtool.etherinfo function, creating a new etherinfo object
+ *
+ * @param type
+ * @param args
+ * @param kwds
+ *
+ * @return Returns in PyObject with the new object on success, otherwise NULL
+ */
+PyObject *_ethtool_etherinfo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ etherinfo_py *self;
+
+ self = (etherinfo_py *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ }
+ return (PyObject *)self;
+}
+
+
+/**
+ * ethtool.etherinfo init (constructor) method. Makes sure the object is initialised correctly.
+ *
+ * @param self
+ * @param args
+ * @param kwds
+ *
+ * @return Returns 0 on success.
+ */
+int _ethtool_etherinfo_init(etherinfo_py *self, PyObject *args, PyObject *kwds)
+{
+ self->info = (struct etherinfo *) malloc(sizeof(struct etherinfo)+2);
+ memset(self->info, 0, sizeof(struct etherinfo)+2);
+ self->info->device = strdup("test");
+ return 0;
+}
+
+
+/**
+ * ethtool.etherinfo function for retrieving data from a Python object.
+ *
+ * @param self
+ * @param attr_o contains the object member request (which element to return)
+ *
+ * @return Returns a PyObject with the value requested on success, otherwise NULL
+ */
+PyObject *_ethtool_etherinfo_getter(etherinfo_py *self, PyObject *attr_o)
+{
+ char *attr = PyString_AsString(attr_o);
+
+ if( !self || !self->info ) {
+ PyErr_SetString(PyExc_AttributeError, "No data available");
+ return NULL;
+ }
+
+ if( strcmp(attr, "device") == 0 ) {
+ return PyString_FromString(self->info->device);
+ } else if( strcmp(attr, "mac_address") == 0 ) {
+ return PyString_FromString(self->info->hwaddress);
+ } else if( strcmp(attr, "ipv4_address") == 0 ) {
+ return PyString_FromString(self->info->ipv4_address);
+ } else if( strcmp(attr, "ipv4_netmask") == 0 ) {
+ return PyInt_FromLong(self->info->ipv4_netmask);
+ } else if( strcmp(attr, "ipv4_broadcast") == 0 ) {
+ return PyString_FromString(self->info->ipv4_broadcast);
+ } else if( strcmp(attr, "ipv6_address") == 0 ) {
+ return PyString_FromString(self->info->ipv6_address);
+ } else if( strcmp(attr, "ipv6_netmask") == 0 ) {
+ return PyInt_FromLong(self->info->ipv6_netmask);
+ }
+ PyErr_SetString(PyExc_AttributeError, "Unknown attribute name");
+ return NULL;
+}
+
+
+/**
+ * ethtool.etherinfo function for setting a value to a object member. This feature is
+ * disabled by always returning -1, as the values are read-only by the user.
+ *
+ * @param self
+ * @param attr_o
+ * @param val_o
+ *
+ * @return Returns always -1 (failure).
+ */
+int _ethtool_etherinfo_setter(etherinfo_py *self, PyObject *attr_o, PyObject *val_o)
+{
+ PyErr_SetString(PyExc_AttributeError, "etherinfo member values are read-only.");
+ return -1;
+}
+
+
diff --git a/python-ethtool/etherinfo_obj.h b/python-ethtool/etherinfo_obj.h
new file mode 100644
index 0000000..dae5352
--- /dev/null
+++ b/python-ethtool/etherinfo_obj.h
@@ -0,0 +1,101 @@
+/**
+ * @file etherinfo_obj.c
+ * @author David Sommerseth <davids@redhat.com>
+ * @date Fri Sep 4 18:41:28 2009
+ *
+ * @brief Python ethtool.etherinfo class functions (header file).
+ *
+ */
+
+#ifndef __ETHERINFO_OBJ_H
+#define __ETHERINFO_OBJ_H
+
+#include <Python.h>
+#include "structmember.h"
+#include "etherinfo.h"
+#include "etherinfo_struct.h"
+
+void _ethtool_etherinfo_dealloc(etherinfo_py *);
+PyObject *_ethtool_etherinfo_new(PyTypeObject *, PyObject *, PyObject *);
+int _ethtool_etherinfo_init(etherinfo_py *, PyObject *, PyObject *);
+PyObject *_ethtool_etherinfo_getter(etherinfo_py *, PyObject *);
+int _ethtool_etherinfo_setter(etherinfo_py *, PyObject *, PyObject *);
+
+/**
+ * This is required by Python, which lists all accessible methods
+ * in the object. But no methods are provided.
+ *
+ */
+static PyMethodDef _ethtool_etherinfo_methods[] = {
+ {NULL} /**< No methods defined */
+};
+
+/**
+ * Defines all accessible object members
+ *
+ */
+static PyMemberDef _ethtool_etherinfo_members[] = {
+ {"device", T_OBJECT_EX, offsetof(etherinfo_py, info), 0,
+ "Device name of the interface"},
+ {"mac_address", T_OBJECT_EX, offsetof(etherinfo_py, info), 0,
+ "MAC address / hardware address of the interface"},
+ {"ipv4_address", T_OBJECT_EX, offsetof(etherinfo_py, info), 0,
+ "IPv4 address"},
+ {"ipv4_netmask", T_INT, offsetof(etherinfo_py, info), 0,
+ "IPv4 netmask in bits"},
+ {"ipv4_broadcast", T_OBJECT_EX, offsetof(etherinfo_py, info), 0,
+ "IPv4 broadcast address"},
+ {"ipv6_address", T_OBJECT_EX, offsetof(etherinfo_py, info), 0,
+ "IPv6 address"},
+ {"ipv6_netmask", T_INT, offsetof(etherinfo_py, info), 0,
+ "IPv6 netmask in bits"},
+ {NULL} /* End of member list */
+};
+
+/**
+ * Definition of the functions a Python class/object requires.
+ *
+ */
+PyTypeObject ethtool_etherinfoType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "ethtool.etherinfo", /*tp_name*/
+ sizeof(etherinfo_py), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)_ethtool_etherinfo_dealloc,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ (getattrofunc)_ethtool_etherinfo_getter, /*tp_getattro*/
+ (setattrofunc)_ethtool_etherinfo_setter, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ "Contains information about a specific ethernet device", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ _ethtool_etherinfo_methods, /* tp_methods */
+ _ethtool_etherinfo_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)_ethtool_etherinfo_init, /* tp_init */
+ 0, /* tp_alloc */
+ _ethtool_etherinfo_new, /* tp_new */
+};
+
+#endif
diff --git a/python-ethtool/etherinfo_struct.h b/python-ethtool/etherinfo_struct.h
new file mode 100644
index 0000000..641dcb4
--- /dev/null
+++ b/python-ethtool/etherinfo_struct.h
@@ -0,0 +1,23 @@
+/**
+ * @file etherinfo_struct.h
+ * @author David Sommerseth <dsommers@wsdsommers.usersys.redhat.com>
+ * @date Fri Sep 4 19:06:06 2009
+ *
+ * @brief Contains the internal ethtool.etherinfo data structure
+ *
+ */
+
+#ifndef _ETHERINFO_STRUCT_H
+#define _ETHERINFO_STRUCT_H
+
+/**
+ * Contains the internal data structure of the
+ * ethtool.etherinfo object.
+ *
+ */
+typedef struct {
+ PyObject_HEAD
+ struct etherinfo *info; /**< Contains information about one ethernet device */
+} etherinfo_py;
+
+#endif
diff --git a/python-ethtool/ethtool.c b/python-ethtool/ethtool.c
index 8d3d37c..cdd8394 100644
--- a/python-ethtool/ethtool.c
+++ b/python-ethtool/ethtool.c
@@ -27,6 +27,7 @@
#include <sys/types.h>
#include "etherinfo.h"
+#include "etherinfo_obj.h"
#ifndef IFF_DYNAMIC
#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/
@@ -45,6 +46,7 @@ typedef __uint8_t u8;
#define _PATH_PROCNET_DEV "/proc/net/dev"
struct etherinfo *ethernet_devices = NULL;
+int etherinfo_cache_dirty = 0;
static PyObject *get_active_devices(PyObject *self __unused, PyObject *args __unused)
{
@@ -225,6 +227,10 @@ static PyObject *get_ipaddresses(PyObject *self __unused, PyObject *args) {
PyObject *devlist = NULL;
struct etherinfo *ethptr = NULL;
+ if( ethernet_devices == NULL ) {
+ ethernet_devices = get_etherinfo();
+ }
+
devlist = PyList_New(0);
for( ethptr = ethernet_devices; ethptr->next != NULL; ethptr = ethptr->next) {
if( ethptr->ipv4_address ) {
@@ -883,10 +889,19 @@ static struct PyMethodDef PyEthModuleMethods[] = {
{ .ml_name = NULL, },
};
+
PyMODINIT_FUNC initethtool(void)
{
PyObject *m;
- m = Py_InitModule("ethtool", PyEthModuleMethods);
+ m = Py_InitModule3("ethtool", PyEthModuleMethods, "Python ethtool module");
+
+ // Prepare the ethtool.etherinfo class
+ if (PyType_Ready(&ethtool_etherinfoType) < 0)
+ return;
+ Py_INCREF(&ethtool_etherinfoType);
+ PyModule_AddObject(m, "etherinfo", (PyObject *)&ethtool_etherinfoType);
+
+ // Setup constants
PyModule_AddIntConstant(m, "IFF_UP", IFF_UP); /* Interface is up. */
PyModule_AddIntConstant(m, "IFF_BROADCAST", IFF_BROADCAST); /* Broadcast address valid. */
PyModule_AddIntConstant(m, "IFF_DEBUG", IFF_DEBUG); /* Turn on debugging. */
@@ -905,7 +920,5 @@ PyMODINIT_FUNC initethtool(void)
PyModule_AddIntConstant(m, "IFF_DYNAMIC", IFF_DYNAMIC); /* Dialup device with changing addresses. */
PyModule_AddIntConstant(m, "AF_INET", AF_INET); /* IPv4 interface */
PyModule_AddIntConstant(m, "AF_INET6", AF_INET6); /* IPv6 interface */
-
- ethernet_devices = get_etherinfo();
}
diff --git a/setup.py b/setup.py
index 662b92c..3098123 100644
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,8 @@
from distutils.core import setup, Extension
ethtool = Extension('ethtool',
- sources = ['python-ethtool/ethtool.c', 'python-ethtool/etherinfo.c'])
+ sources = ['python-ethtool/ethtool.c',
+ 'python-ethtool/etherinfo.c', 'python-ethtool/etherinfo_obj.c'])
# don't reformat this line, Makefile parses it
setup(name='ethtool',