diff options
author | David Sommerseth <davids@redhat.com> | 2013-12-17 21:07:36 +0100 |
---|---|---|
committer | David Sommerseth <davids@redhat.com> | 2013-12-17 21:15:24 +0100 |
commit | 4c301d903dfc3d011e673a8772d4ac75e99bbd2a (patch) | |
tree | 379b0bd747c1ab4330d7641df5d1a108ca27604f | |
parent | e9784985e3f7b72cc5f3210d60a88014625b2660 (diff) | |
download | python-ethtool-4c301d903dfc3d011e673a8772d4ac75e99bbd2a.tar.gz python-ethtool-4c301d903dfc3d011e673a8772d4ac75e99bbd2a.tar.xz python-ethtool-4c301d903dfc3d011e673a8772d4ac75e99bbd2a.zip |
Reduce the NETLINK pointer complexity
Make the NETLINK connection pointer and user counter
local global variables inside netlink.c only. Where NETLINK
calls via libnl is required, rather use get_nlc() to get a
NETLINK connection.
This also prepares the next step, to get rid of the
struct etherinfo_obj_data wrapper.
Signed-off-by: David Sommerseth <davids@redhat.com>
-rw-r--r-- | python-ethtool/etherinfo.c | 14 | ||||
-rw-r--r-- | python-ethtool/etherinfo.h | 7 | ||||
-rw-r--r-- | python-ethtool/etherinfo_obj.c | 22 | ||||
-rw-r--r-- | python-ethtool/etherinfo_struct.h | 4 | ||||
-rw-r--r-- | python-ethtool/ethtool.c | 4 | ||||
-rw-r--r-- | python-ethtool/netlink.c | 57 |
6 files changed, 58 insertions, 50 deletions
diff --git a/python-ethtool/etherinfo.c b/python-ethtool/etherinfo.c index 74b30d4..509ae08 100644 --- a/python-ethtool/etherinfo.c +++ b/python-ethtool/etherinfo.c @@ -142,7 +142,7 @@ static void callback_nl_address(struct nl_object *obj, void *arg) * * @return Returns 1 on success, otherwise 0. */ -int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query) +int get_etherinfo(etherinfo_py *self, nlQuery query) { struct nl_cache *link_cache; struct nl_cache *addr_cache; @@ -153,13 +153,13 @@ int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query) int ret = 0; - if( !data || !data->ethinfo ) { + if( !self || !self->data || !self->data->ethinfo ) { return 0; } - ethinf = data->ethinfo; + ethinf = self->data->ethinfo; /* Open a NETLINK connection on-the-fly */ - if( !open_netlink(data) ) { + if( !open_netlink(self) ) { PyErr_Format(PyExc_RuntimeError, "Could not open a NETLINK connection for %s", ethinf->device); @@ -171,7 +171,7 @@ int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query) * interface index if we have that */ if( ethinf->index < 0 ) { - if( rtnl_link_alloc_cache(*data->nlc, AF_UNSPEC, &link_cache) < 0) { + if( rtnl_link_alloc_cache(get_nlc(), AF_UNSPEC, &link_cache) < 0) { return 0; } @@ -195,7 +195,7 @@ int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query) switch( query ) { case NLQRY_LINK: /* Extract MAC/hardware address of the interface */ - if( rtnl_link_alloc_cache(*data->nlc, AF_UNSPEC, &link_cache) < 0) { + if( rtnl_link_alloc_cache(get_nlc(), AF_UNSPEC, &link_cache) < 0) { return 0; } link = rtnl_link_alloc(); @@ -209,7 +209,7 @@ int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query) case NLQRY_ADDR4: case NLQRY_ADDR6: /* Extract IP address information */ - if( rtnl_addr_alloc_cache(*data->nlc, &addr_cache) < 0) { + if( rtnl_addr_alloc_cache(get_nlc(), &addr_cache) < 0) { nl_cache_free(addr_cache); return 0; } diff --git a/python-ethtool/etherinfo.h b/python-ethtool/etherinfo.h index 1997807..5b8c874 100644 --- a/python-ethtool/etherinfo.h +++ b/python-ethtool/etherinfo.h @@ -19,10 +19,11 @@ typedef enum {NLQRY_LINK, NLQRY_ADDR4, NLQRY_ADDR6} nlQuery; /**< Supported query types in the etherinfo code */ -int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query); +int get_etherinfo(etherinfo_py *data, nlQuery query); void free_etherinfo(struct etherinfo *ptr); -int open_netlink(struct etherinfo_obj_data *); -void close_netlink(struct etherinfo_obj_data *); +int open_netlink(etherinfo_py *); +struct nl_sock * get_nlc(); +void close_netlink(etherinfo_py *); #endif diff --git a/python-ethtool/etherinfo_obj.c b/python-ethtool/etherinfo_obj.c index 55a42db..97a06be 100644 --- a/python-ethtool/etherinfo_obj.c +++ b/python-ethtool/etherinfo_obj.c @@ -41,7 +41,7 @@ extern PyTypeObject ethtool_etherinfoIPv6Type; void _ethtool_etherinfo_dealloc(etherinfo_py *self) { if( self->data ) { - close_netlink(self->data); + close_netlink(self); if( self->data->ethinfo ) { free_etherinfo(self->data->ethinfo); @@ -151,11 +151,11 @@ PyObject *_ethtool_etherinfo_getter(etherinfo_py *self, PyObject *attr_o) return Py_INCREF(Py_None), Py_None; } } else if( strcmp(attr, "mac_address") == 0 ) { - get_etherinfo(self->data, NLQRY_LINK); + get_etherinfo(self, NLQRY_LINK); Py_INCREF(self->data->ethinfo->hwaddress); return self->data->ethinfo->hwaddress; } else if( strcmp(attr, "ipv4_address") == 0 ) { - get_etherinfo(self->data, NLQRY_ADDR4); + get_etherinfo(self, NLQRY_ADDR4); /* For compatiblity with old approach, return last IPv4 address: */ py_addr = get_last_ipv4_address(self); if (py_addr) { @@ -166,14 +166,14 @@ PyObject *_ethtool_etherinfo_getter(etherinfo_py *self, PyObject *attr_o) } Py_RETURN_NONE; } else if( strcmp(attr, "ipv4_netmask") == 0 ) { - get_etherinfo(self->data, NLQRY_ADDR4); + get_etherinfo(self, NLQRY_ADDR4); py_addr = get_last_ipv4_address(self); if (py_addr) { return PyInt_FromLong(py_addr->prefixlen); } return PyInt_FromLong(0); } else if( strcmp(attr, "ipv4_broadcast") == 0 ) { - get_etherinfo(self->data, NLQRY_ADDR4); + get_etherinfo(self, NLQRY_ADDR4); py_addr = get_last_ipv4_address(self); if (py_addr) { if (py_addr->ipv4_broadcast) { @@ -215,14 +215,14 @@ PyObject *_ethtool_etherinfo_str(etherinfo_py *self) { PyObject *ret = NULL; - if( !self || !self->data || !self->data->nlc || !self->data->ethinfo ) { + if( !self || !self->data || !self->data->ethinfo ) { PyErr_SetString(PyExc_AttributeError, "No data available"); return NULL; } - get_etherinfo(self->data, NLQRY_LINK); - get_etherinfo(self->data, NLQRY_ADDR4); - get_etherinfo(self->data, NLQRY_ADDR6); + get_etherinfo(self, NLQRY_LINK); + get_etherinfo(self, NLQRY_ADDR4); + get_etherinfo(self, NLQRY_ADDR6); ret = PyString_FromFormat("Device %s:\n", self->data->ethinfo->device); if( self->data->ethinfo->hwaddress ) { @@ -281,7 +281,7 @@ static PyObject *_ethtool_etherinfo_get_ipv4_addresses(etherinfo_py *self, PyObj return NULL; } - get_etherinfo(self->data, NLQRY_ADDR4); + get_etherinfo(self, NLQRY_ADDR4); /* Transfer ownership of reference: */ ret = self->data->ethinfo->ipv4_addresses; @@ -307,7 +307,7 @@ static PyObject *_ethtool_etherinfo_get_ipv6_addresses(etherinfo_py *self, PyObj return NULL; } - get_etherinfo(self->data, NLQRY_ADDR6); + get_etherinfo(self, NLQRY_ADDR6); /* Transfer ownership of reference: */ ret = self->data->ethinfo->ipv6_addresses; diff --git a/python-ethtool/etherinfo_struct.h b/python-ethtool/etherinfo_struct.h index 6d2da36..31c71c0 100644 --- a/python-ethtool/etherinfo_struct.h +++ b/python-ethtool/etherinfo_struct.h @@ -56,9 +56,6 @@ extern PyTypeObject ethtool_netlink_ip_address_Type; * */ struct etherinfo_obj_data { - struct nl_sock **nlc; /**< Contains NETLINK connection info (global) */ - unsigned int *nlc_users; /**< Resource counter for the NETLINK connection (global) */ - unsigned short nlc_active; /**< Is this instance using NETLINK? */ struct etherinfo *ethinfo; /**< Contains info about our current interface */ }; @@ -69,6 +66,7 @@ struct etherinfo_obj_data { typedef struct { PyObject_HEAD struct etherinfo_obj_data *data; /* IPv4 and IPv6 address information, only one element used */ + unsigned short nlc_active; /**< Is this instance using NETLINK? */ } etherinfo_py; diff --git a/python-ethtool/ethtool.c b/python-ethtool/ethtool.c index 7e7ff1d..4aa07bc 100644 --- a/python-ethtool/ethtool.c +++ b/python-ethtool/ethtool.c @@ -32,8 +32,6 @@ #include "etherinfo_obj.h" #include "etherinfo.h" -static struct nl_sock *nlconnection = NULL; -unsigned int nlconnection_users = 0; /* How many NETLINK users are active? */ extern PyTypeObject ethtool_etherinfoType; #ifndef IFF_DYNAMIC @@ -292,8 +290,6 @@ static PyObject *get_interfaces_info(PyObject *self __unused, PyObject *args) { */ objdata->ethinfo->device = strdup(fetch_devs[i]); objdata->ethinfo->index = -1; - objdata->nlc = &nlconnection; - objdata->nlc_users = &nlconnection_users; /* Instantiate a new etherinfo object with the device information */ ethinf_py = PyCObject_FromVoidPtr(objdata, NULL); diff --git a/python-ethtool/netlink.c b/python-ethtool/netlink.c index f80ebd4..f24b312 100644 --- a/python-ethtool/netlink.c +++ b/python-ethtool/netlink.c @@ -24,6 +24,8 @@ #include "etherinfo_struct.h" pthread_mutex_t nlc_counter_mtx = PTHREAD_MUTEX_INITIALIZER; +static struct nl_sock *nlconnection = NULL; +static unsigned int nlconnection_users = 0; /* How many NETLINK users are active? */ /** @@ -31,34 +33,34 @@ pthread_mutex_t nlc_counter_mtx = PTHREAD_MUTEX_INITIALIZER; * for each etherinfo object being generated, and it will * keep a separate file descriptor open for each object * - * @param data etherinfo_obj_data structure + * @param ethi etherinfo_py structure (basically the "self" object) * * @return Returns 1 on success, otherwise 0. */ -int open_netlink(struct etherinfo_obj_data *data) +int open_netlink(etherinfo_py *ethi) { - if( !data ) { + if( !ethi ) { return 0; } /* Reuse already established NETLINK connection, if a connection exists */ - if( *data->nlc ) { + if( nlconnection ) { /* If this object has not used NETLINK earlier, tag it as a user */ - if( !data->nlc_active ) { + if( !ethi->nlc_active ) { pthread_mutex_lock(&nlc_counter_mtx); - (*data->nlc_users)++; + nlconnection_users++; pthread_mutex_unlock(&nlc_counter_mtx); } - data->nlc_active = 1; + ethi->nlc_active = 1; return 1; } /* No earlier connections exists, establish a new one */ - *data->nlc = nl_socket_alloc(); - nl_connect(*data->nlc, NETLINK_ROUTE); - if( (*data->nlc != NULL) ) { + nlconnection = nl_socket_alloc(); + nl_connect(nlconnection, NETLINK_ROUTE); + if( (nlconnection != NULL) ) { /* Force O_CLOEXEC flag on the NETLINK socket */ - if( fcntl(nl_socket_get_fd(*data->nlc), F_SETFD, FD_CLOEXEC) == -1 ) { + if( fcntl(nl_socket_get_fd(nlconnection), F_SETFD, FD_CLOEXEC) == -1 ) { fprintf(stderr, "**WARNING** Failed to set O_CLOEXEC on NETLINK socket: %s\n", strerror(errno)); @@ -66,9 +68,9 @@ int open_netlink(struct etherinfo_obj_data *data) /* Tag this object as an active user */ pthread_mutex_lock(&nlc_counter_mtx); - (*data->nlc_users)++; + nlconnection_users++; pthread_mutex_unlock(&nlc_counter_mtx); - data->nlc_active = 1; + ethi->nlc_active = 1; return 1; } else { return 0; @@ -77,32 +79,43 @@ int open_netlink(struct etherinfo_obj_data *data) /** + * Return a reference to the global netlink connection + * + * @returns Returns a pointer to a NETLINK connection libnl functions can use + */ +struct nl_sock * get_nlc() +{ + assert(nlconnection); + return nlconnection; +} + +/** * Closes the NETLINK connection. This should be called automatically whenever * the corresponding etherinfo object is deleted. * - * @param ptr Pointer to the pointer of struct nl_handle, which contains the NETLINK connection + * @param ethi etherinfo_py structure (basically the "self" object) */ -void close_netlink(struct etherinfo_obj_data *data) +void close_netlink(etherinfo_py *ethi) { - if( !data || !(*data->nlc) ) { + if( !ethi || !nlconnection ) { return; } /* Untag this object as a NETLINK user */ - data->nlc_active = 0; + ethi->nlc_active = 0; pthread_mutex_lock(&nlc_counter_mtx); - (*data->nlc_users)--; + nlconnection_users--; pthread_mutex_unlock(&nlc_counter_mtx); /* Don't close the connection if there are more users */ - if( *data->nlc_users > 0) { + if( nlconnection_users > 0) { return; } /* Close NETLINK connection */ - nl_close(*data->nlc); - nl_socket_free(*data->nlc); - *data->nlc = NULL; + nl_close(nlconnection); + nl_socket_free(nlconnection); + nlconnection = NULL; } /* |