Skip to content

Commit 54a6b0b

Browse files
author
David Sommerseth
committed
Merge struct etherinfo and etherinfo_py
Make things more "pythonic" and avoid another layer of wrapping by removing the struct etherinfo. Move that information to the main Python object instead. This simplifies the object creation and handling too, as now all strings are python objects. Also update some of the documentation blocks along the way. Signed-off-by: David Sommerseth <davids@redhat.com>
1 parent d4bc3a5 commit 54a6b0b

File tree

5 files changed

+80
-148
lines changed

5 files changed

+80
-148
lines changed

python-ethtool/etherinfo.c

Lines changed: 28 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,6 @@
4141
*
4242
*/
4343

44-
/**
45-
* Frees the memory used by struct etherinfo
46-
*
47-
* @param ptr Pointer to a struct etherninfo element
48-
*/
49-
void free_etherinfo(struct etherinfo *ptr)
50-
{
51-
if( ptr == NULL ) { // Just for safety
52-
return;
53-
}
54-
55-
Py_XDECREF(ptr->device);
56-
Py_XDECREF(ptr->hwaddress);
57-
58-
free(ptr);
59-
}
60-
6144

6245
/**
6346
* libnl callback function. Does the real parsing of a record returned by NETLINK. This function
@@ -68,7 +51,7 @@ void free_etherinfo(struct etherinfo *ptr)
6851
*/
6952
static void callback_nl_link(struct nl_object *obj, void *arg)
7053
{
71-
struct etherinfo *ethi = (struct etherinfo *) arg;
54+
etherinfo_py *ethi = (etherinfo_py *) arg;
7255
struct rtnl_link *link = (struct rtnl_link *) obj;
7356
char hwaddr[130];
7457

@@ -125,12 +108,12 @@ static void callback_nl_address(struct nl_object *obj, void *arg)
125108
/**
126109
* Sets the etherinfo.index member to the corresponding device set in etherinfo.device
127110
*
128-
* @param ethinf A pointer a struct etherinfo element which contains the device name
129-
* and a place to save the corresponding index value.
111+
* @param self A pointer the current etherinfo_py Python object which contains the device name
112+
* and the place where to save the corresponding index value.
130113
*
131114
* @return Returns 1 on success, otherwise 0.
132115
*/
133-
static int _set_device_index(struct etherinfo *ethinf)
116+
static int _set_device_index(etherinfo_py *self)
134117
{
135118
struct nl_cache *link_cache;
136119
struct rtnl_link *link;
@@ -139,19 +122,19 @@ static int _set_device_index(struct etherinfo *ethinf)
139122
* As we don't expect it to change, we're reusing a "cached"
140123
* interface index if we have that
141124
*/
142-
if( ethinf->index < 0 ) {
125+
if( self->index < 0 ) {
143126
if( rtnl_link_alloc_cache(get_nlc(), AF_UNSPEC, &link_cache) < 0) {
144127
return 0;
145128
}
146129

147-
link = rtnl_link_get_by_name(link_cache, PyString_AsString(ethinf->device));
130+
link = rtnl_link_get_by_name(link_cache, PyString_AsString(self->device));
148131
if( !link ) {
149132
nl_cache_free(link_cache);
150133
return 0;
151134
}
152135

153-
ethinf->index = rtnl_link_get_ifindex(link);
154-
if( ethinf->index < 0 ) {
136+
self->index = rtnl_link_get_ifindex(link);
137+
if( self->index < 0 ) {
155138
rtnl_link_put(link);
156139
nl_cache_free(link_cache);
157140
return 0;
@@ -169,26 +152,31 @@ static int _set_device_index(struct etherinfo *ethinf)
169152
*
170153
*/
171154

155+
/**
156+
* Populate the etherinfo_py Python object with link information for the current device
157+
*
158+
* @param self Pointer to the device object, a etherinfo_py Python object
159+
*
160+
* @return Returns 1 on success, otherwise 0
161+
*/
172162
int get_etherinfo_link(etherinfo_py *self)
173163
{
174164
struct nl_cache *link_cache;
175165
struct rtnl_link *link;
176-
struct etherinfo *ethinf = NULL;
177166

178-
if( !self || !self->ethinfo ) {
167+
if( !self ) {
179168
return 0;
180169
}
181-
ethinf = self->ethinfo;
182170

183171
/* Open a NETLINK connection on-the-fly */
184172
if( !open_netlink(self) ) {
185173
PyErr_Format(PyExc_RuntimeError,
186174
"Could not open a NETLINK connection for %s",
187-
PyString_AsString(ethinf->device));
175+
PyString_AsString(self->device));
188176
return 0;
189177
}
190178

191-
if( _set_device_index(ethinf) != 1) {
179+
if( _set_device_index(self) != 1) {
192180
return 0;
193181
}
194182

@@ -198,8 +186,8 @@ int get_etherinfo_link(etherinfo_py *self)
198186
}
199187
link = rtnl_link_alloc();
200188
/* FIXME: Error handling? */
201-
rtnl_link_set_ifindex(link, ethinf->index);
202-
nl_cache_foreach_filter(link_cache, OBJ_CAST(link), callback_nl_link, ethinf);
189+
rtnl_link_set_ifindex(link, self->index);
190+
nl_cache_foreach_filter(link_cache, OBJ_CAST(link), callback_nl_link, self);
203191
rtnl_link_put(link);
204192
nl_cache_free(link_cache);
205193

@@ -211,34 +199,32 @@ int get_etherinfo_link(etherinfo_py *self)
211199
/**
212200
* Query NETLINK for device IP address configuration
213201
*
214-
* @param ethinf Pointer to an available struct etherinfo element. The 'device' member
215-
* must contain a valid string to the device to query for information
216-
* @param nlc Pointer to the libnl handle, which is used for the query against NETLINK
217-
* @param query What to query for. Must be NLQRY_ADDR4 or NLQRY_ADDR6.
202+
* @param self A etherinfo_py Python object for the current device to retrieve IP address
203+
* configuration data from
204+
* @param query What to query for. Must be NLQRY_ADDR4 for IPv4 addresses or NLQRY_ADDR6
205+
* for IPv6 addresses.
218206
*
219207
* @return Returns a Python list containing PyNetlinkIPaddress objects on success, otherwise NULL
220208
*/
221209
PyObject * get_etherinfo_address(etherinfo_py *self, nlQuery query)
222210
{
223211
struct nl_cache *addr_cache;
224212
struct rtnl_addr *addr;
225-
struct etherinfo *ethinf = NULL;
226213
PyObject *addrlist = NULL;
227214

228-
if( !self || !self->ethinfo ) {
215+
if( !self ) {
229216
return NULL;
230217
}
231-
ethinf = self->ethinfo;
232218

233219
/* Open a NETLINK connection on-the-fly */
234220
if( !open_netlink(self) ) {
235221
PyErr_Format(PyExc_RuntimeError,
236222
"Could not open a NETLINK connection for %s",
237-
PyString_AsString(ethinf->device));
223+
PyString_AsString(self->device));
238224
return NULL;
239225
}
240226

241-
if( _set_device_index(ethinf) != 1) {
227+
if( _set_device_index(self) != 1) {
242228
return NULL;
243229
}
244230

@@ -251,7 +237,7 @@ PyObject * get_etherinfo_address(etherinfo_py *self, nlQuery query)
251237
}
252238
addr = rtnl_addr_alloc();
253239
/* FIXME: Error handling? */
254-
rtnl_addr_set_ifindex(addr, ethinf->index);
240+
rtnl_addr_set_ifindex(addr, self->index);
255241

256242
switch( query ) {
257243
case NLQRY_ADDR4:

python-ethtool/etherinfo.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ typedef enum {NLQRY_ADDR4, NLQRY_ADDR6} nlQuery; /**< Supported query types in
2121

2222
int get_etherinfo_link(etherinfo_py *data);
2323
PyObject * get_etherinfo_address(etherinfo_py *self, nlQuery query);
24-
void free_etherinfo(struct etherinfo *ptr);
2524

2625
int open_netlink(etherinfo_py *);
2726
struct nl_sock * get_nlc();

python-ethtool/etherinfo_obj.c

Lines changed: 23 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -34,58 +34,17 @@
3434
/**
3535
* ethtool.etherinfo deallocator - cleans up when a object is deleted
3636
*
37-
* @param self etherinfo_py object structure
37+
* @param self etherinfo_py Python object to deallocate
3838
*/
39-
void _ethtool_etherinfo_dealloc(etherinfo_py *self)
39+
static void _ethtool_etherinfo_dealloc(etherinfo_py *self)
4040
{
4141
close_netlink(self);
42-
if( self->ethinfo ) {
43-
free_etherinfo(self->ethinfo);
44-
}
42+
Py_XDECREF(self->device); self->device = NULL;
43+
Py_XDECREF(self->hwaddress); self->hwaddress = NULL;
4544
self->ob_type->tp_free((PyObject*)self);
4645
}
4746

4847

49-
/**
50-
* ethtool.etherinfo function, creating a new etherinfo object
51-
*
52-
* @param type
53-
* @param args
54-
* @param kwds
55-
*
56-
* @return Returns in PyObject with the new object on success, otherwise NULL
57-
*/
58-
PyObject *_ethtool_etherinfo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
59-
{
60-
etherinfo_py *self;
61-
62-
self = (etherinfo_py *)type->tp_alloc(type, 0);
63-
return (PyObject *)self;
64-
}
65-
66-
67-
/**
68-
* ethtool.etherinfo init (constructor) method. Makes sure the object is initialised correctly.
69-
*
70-
* @param self
71-
* @param args
72-
* @param kwds
73-
*
74-
* @return Returns 0 on success.
75-
*/
76-
int _ethtool_etherinfo_init(etherinfo_py *self, PyObject *args, PyObject *kwds)
77-
{
78-
static char *etherinfo_kwlist[] = {"etherinfo_ptr", NULL};
79-
PyObject *ethinf_ptr = NULL;
80-
81-
if( !PyArg_ParseTupleAndKeywords(args, kwds, "O", etherinfo_kwlist, &ethinf_ptr)) {
82-
PyErr_SetString(PyExc_AttributeError, "Invalid data pointer to constructor");
83-
return -1;
84-
}
85-
self->ethinfo = (struct etherinfo *) PyCObject_AsVoidPtr(ethinf_ptr);
86-
return 0;
87-
}
88-
8948
/*
9049
The old approach of having a single IPv4 address per device meant each result
9150
that came in from netlink overwrote the old result.
@@ -120,7 +79,7 @@ static PyNetlinkIPaddress * get_last_ipv4_address(PyObject *addrlist)
12079
/**
12180
* ethtool.etherinfo function for retrieving data from a Python object.
12281
*
123-
* @param self
82+
* @param self Pointer to the current etherinfo_py device object
12483
* @param attr_o contains the object member request (which element to return)
12584
*
12685
* @return Returns a PyObject with the value requested on success, otherwise NULL
@@ -131,22 +90,22 @@ PyObject *_ethtool_etherinfo_getter(etherinfo_py *self, PyObject *attr_o)
13190
PyNetlinkIPaddress *py_addr;
13291
PyObject *addrlist = NULL;
13392

134-
if( !self || !self->ethinfo ) {
93+
if( !self ) {
13594
PyErr_SetString(PyExc_AttributeError, "No data available");
13695
return NULL;
13796
}
13897

13998
if( strcmp(attr, "device") == 0 ) {
140-
if( self->ethinfo->device ) {
141-
Py_INCREF(self->ethinfo->device);
142-
return self->ethinfo->device;
99+
if( self->device ) {
100+
Py_INCREF(self->device);
101+
return self->device;
143102
} else {
144103
return Py_INCREF(Py_None), Py_None;
145104
}
146105
} else if( strcmp(attr, "mac_address") == 0 ) {
147106
get_etherinfo_link(self);
148-
Py_INCREF(self->ethinfo->hwaddress);
149-
return self->ethinfo->hwaddress;
107+
Py_INCREF(self->hwaddress);
108+
return self->hwaddress;
150109
} else if( strcmp(attr, "ipv4_address") == 0 ) {
151110
addrlist = get_etherinfo_address(self, NLQRY_ADDR4);
152111
/* For compatiblity with old approach, return last IPv4 address: */
@@ -200,7 +159,7 @@ int _ethtool_etherinfo_setter(etherinfo_py *self, PyObject *attr_o, PyObject *va
200159
/**
201160
* Creates a human readable format of the information when object is being treated as a string
202161
*
203-
* @param self
162+
* @param self Pointer to the current etherinfo_py device object
204163
*
205164
* @return Returns a PyObject with a string with all of the information
206165
*/
@@ -209,20 +168,20 @@ PyObject *_ethtool_etherinfo_str(etherinfo_py *self)
209168
PyObject *ret = NULL;
210169
PyObject *ipv4addrs = NULL, *ipv6addrs = NULL;
211170

212-
if( !self || !self->ethinfo ) {
171+
if( !self ) {
213172
PyErr_SetString(PyExc_AttributeError, "No data available");
214173
return NULL;
215174
}
216175

217176
get_etherinfo_link(self);
218177

219178
ret = PyString_FromFormat("Device ");
220-
PyString_Concat(&ret, self->ethinfo->device);
179+
PyString_Concat(&ret, self->device);
221180
PyString_ConcatAndDel(&ret, PyString_FromString(":\n"));
222181

223-
if( self->ethinfo->hwaddress ) {
182+
if( self->hwaddress ) {
224183
PyString_ConcatAndDel(&ret, PyString_FromString("\tMAC address: "));
225-
PyString_Concat(&ret, self->ethinfo->hwaddress);
184+
PyString_Concat(&ret, self->hwaddress);
226185
PyString_ConcatAndDel(&ret, PyString_FromString("\n"));
227186
}
228187

@@ -265,13 +224,13 @@ PyObject *_ethtool_etherinfo_str(etherinfo_py *self)
265224
/**
266225
* Returns a tuple list of configured IPv4 addresses
267226
*
268-
* @param self
227+
* @param self Pointer to the current etherinfo_py device object to extract IPv4 info from
269228
* @param notused
270229
*
271230
* @return Returns a Python tuple list of NetlinkIP4Address objects
272231
*/
273232
static PyObject *_ethtool_etherinfo_get_ipv4_addresses(etherinfo_py *self, PyObject *notused) {
274-
if( !self || !self->ethinfo ) {
233+
if( !self ) {
275234
PyErr_SetString(PyExc_AttributeError, "No data available");
276235
return NULL;
277236
}
@@ -281,15 +240,15 @@ static PyObject *_ethtool_etherinfo_get_ipv4_addresses(etherinfo_py *self, PyObj
281240

282241

283242
/**
284-
* Returns a tuple list of configured IPv4 addresses
243+
* Returns a tuple list of configured IPv6 addresses
285244
*
286-
* @param self
245+
* @param self Pointer to the current etherinfo_py device object to extract IPv6 info from
287246
* @param notused
288247
*
289248
* @return Returns a Python tuple list of NetlinkIP6Address objects
290249
*/
291250
static PyObject *_ethtool_etherinfo_get_ipv6_addresses(etherinfo_py *self, PyObject *notused) {
292-
if( !self || !self->ethinfo ) {
251+
if( !self ) {
293252
PyErr_SetString(PyExc_AttributeError, "No data available");
294253
return NULL;
295254
}
@@ -351,8 +310,8 @@ PyTypeObject ethtool_etherinfoType = {
351310
0, /* tp_descr_get */
352311
0, /* tp_descr_set */
353312
0, /* tp_dictoffset */
354-
(initproc)_ethtool_etherinfo_init, /* tp_init */
313+
0, /* tp_init */
355314
0, /* tp_alloc */
356-
_ethtool_etherinfo_new, /* tp_new */
315+
0, /* tp_new */
357316
};
358317

python-ethtool/etherinfo_struct.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,6 @@
2828

2929
#include <netlink/route/addr.h>
3030

31-
/**
32-
* Contains IP address information about a particular ethernet device
33-
*
34-
*/
35-
struct etherinfo {
36-
PyObject *device; /**< Device name */
37-
int index; /**< NETLINK index reference */
38-
PyObject *hwaddress; /**< string: HW address / MAC address of device */
39-
};
40-
4131
/* Python object containing data baked from a (struct rtnl_addr) */
4232
typedef struct PyNetlinkIPaddress {
4333
PyObject_HEAD
@@ -56,8 +46,10 @@ extern PyTypeObject ethtool_netlink_ip_address_Type;
5646
*/
5747
typedef struct {
5848
PyObject_HEAD
59-
struct etherinfo *ethinfo; /**< Information about the interface configuration */
60-
unsigned short nlc_active; /**< Is this instance using NETLINK? */
49+
PyObject *device; /**< Device name */
50+
int index; /**< NETLINK index reference */
51+
PyObject *hwaddress; /**< string: HW address / MAC address of device */
52+
unsigned short nlc_active; /**< Is this instance using NETLINK? */
6153
} etherinfo_py;
6254

6355

0 commit comments

Comments
 (0)