Antoni Segura Puimedon has uploaded a new change for review. Change subject: netlink: User libnl-3 when available ......................................................................
netlink: User libnl-3 when available On new distibutions (Fedora, ubuntu, el7, etc) python-ethtool uses libnl3 while vdsm was using libnl1. The problem was that libnl1 and libnl3 use the same algorithm for allocating netlink ports and collided. This patch fixes it by using libnl3 if it is in the system (which reasonably means that the python-ethtool version will be new enough as to use it as well) Change-Id: I45f043a8416e57d5fb550e2e817e6df38cd793b1 Bug-Url: https://bugzilla.redhat.com/1078312 Signed-off-by: Antoni S. Puimedon <asegu...@redhat.com> --- M lib/vdsm/netlink.py 1 file changed, 89 insertions(+), 37 deletions(-) git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/14/26514/1 diff --git a/lib/vdsm/netlink.py b/lib/vdsm/netlink.py index c90f3da..60a16e8 100644 --- a/lib/vdsm/netlink.py +++ b/lib/vdsm/netlink.py @@ -18,7 +18,7 @@ # from contextlib import contextmanager -from ctypes import (CDLL, CFUNCTYPE, c_char, c_char_p, c_int, c_void_p, +from ctypes import (CDLL, CFUNCTYPE, byref, c_char, c_char_p, c_int, c_void_p, c_size_t, get_errno, sizeof) from functools import partial from Queue import Empty, Queue @@ -28,7 +28,6 @@ NETLINK_ROUTE = 0 _POOL_SIZE = 5 CHARBUFFSIZE = 40 # Increased to fit IPv6 expanded representations -LIBNL = CDLL('libnl.so.1', use_errno=True) # C function prototypes # http://docs.python.org/2/library/ctypes.html#function-prototypes @@ -38,49 +37,96 @@ _int_proto = CFUNCTYPE(c_int, c_void_p) _char_proto = CFUNCTYPE(c_char_p, c_void_p) _void_proto = CFUNCTYPE(c_void_p, c_void_p) +try: + LIBNL = LIBNL3 = CDLL('libnl-3.so.200', use_errno=True) + + _nl_socket_alloc = CFUNCTYPE(c_void_p)(('nl_socket_alloc', LIBNL3)) + _nl_socket_free = CFUNCTYPE(None, c_void_p)(('nl_socket_free', LIBNL3)) + + LIBNL_ROUTE = CDLL('libnl-route-3.so', use_errno=True) + + def _rtnl_link_alloc_cache(sock): + AF_UNSPEC = 0 + __rtnl_link_alloc_cache = CFUNCTYPE(c_int, c_void_p, c_int, c_void_p)( + ('rtnl_link_alloc_cache', LIBNL_ROUTE)) + cache = c_void_p() + err = __rtnl_link_alloc_cache(sock, AF_UNSPEC, byref(cache)) + if err: + return None + else: + return cache + + def _rtnl_addr_alloc_cache(sock): + __rtnl_addr_alloc_cache = CFUNCTYPE(c_int, c_void_p, c_void_p)( + ('rtnl_addr_alloc_cache', LIBNL_ROUTE)) + cache = c_void_p() + err = __rtnl_addr_alloc_cache(sock, byref(cache)) + if err: + return None + else: + return cache + + _rtnl_link_get_type = _char_proto(('rtnl_link_get_type', LIBNL_ROUTE)) + + def _rtnl_link_vlan_get_id(link): + __rtnl_link_is_vlan = _int_proto(('rtnl_link_is_vlan', LIBNL_ROUTE)) + __rtnl_link_vlan_get_id = _int_proto(('rtnl_link_vlan_get_id', + LIBNL_ROUTE)) + if __rtnl_link_is_vlan(link): + return __rtnl_link_vlan_get_id(link) + else: + return -1 + +except OSError: # libnl3 is not present, fallback to libnl1 + LIBNL_ROUTE = LIBNL = CDLL('libnl.so.1', use_errno=True) + LIBNL3 = None + + _nl_handle_alloc = CFUNCTYPE(c_void_p)(('nl_handle_alloc', LIBNL)) + _nl_handle_destroy = CFUNCTYPE(None, c_void_p)(('nl_handle_destroy', + LIBNL)) + + _rtnl_link_alloc_cache = _void_proto(('rtnl_link_alloc_cache', LIBNL)) + _rtnl_addr_alloc_cache = _void_proto(('rtnl_addr_alloc_cache', LIBNL)) + + _rtnl_link_vlan_get_id = _int_proto(('rtnl_link_vlan_get_id', LIBNL)) _nl_connect = CFUNCTYPE(c_int, c_void_p, c_int)(('nl_connect', LIBNL)) -_nl_handle_alloc = CFUNCTYPE(c_void_p)(('nl_handle_alloc', LIBNL)) -_nl_handle_destroy = CFUNCTYPE(None, c_void_p)(('nl_handle_destroy', LIBNL)) - _nl_geterror = CFUNCTYPE(c_char_p)(('nl_geterror', LIBNL)) _nl_cache_free = CFUNCTYPE(None, c_void_p)(('nl_cache_free', LIBNL)) _nl_cache_get_first = _void_proto(('nl_cache_get_first', LIBNL)) _nl_cache_get_next = _void_proto(('nl_cache_get_next', LIBNL)) -_rtnl_link_alloc_cache = _void_proto(('rtnl_link_alloc_cache', LIBNL)) -_rtnl_addr_alloc_cache = _void_proto(('rtnl_addr_alloc_cache', LIBNL)) -_rtnl_link_get_addr = _void_proto(('rtnl_link_get_addr', LIBNL)) -_rtnl_link_get_flags = _int_proto(('rtnl_link_get_flags', LIBNL)) -_rtnl_link_get_ifindex = _int_proto(('rtnl_link_get_ifindex', LIBNL)) -_rtnl_link_get_link = _int_proto(('rtnl_link_get_link', LIBNL)) -_rtnl_link_get_master = _int_proto(('rtnl_link_get_master', LIBNL)) -_rtnl_link_get_mtu = _int_proto(('rtnl_link_get_mtu', LIBNL)) -_rtnl_link_get_name = _char_proto(('rtnl_link_get_name', LIBNL)) -_rtnl_link_get_operstate = _int_proto(('rtnl_link_get_operstate', LIBNL)) -_rtnl_link_get_qdisc = _char_proto(('rtnl_link_get_qdisc', LIBNL)) -_rtnl_link_vlan_get_id = _int_proto(('rtnl_link_vlan_get_id', LIBNL)) +_rtnl_link_get_addr = _void_proto(('rtnl_link_get_addr', LIBNL_ROUTE)) +_rtnl_link_get_flags = _int_proto(('rtnl_link_get_flags', LIBNL_ROUTE)) +_rtnl_link_get_ifindex = _int_proto(('rtnl_link_get_ifindex', LIBNL_ROUTE)) +_rtnl_link_get_link = _int_proto(('rtnl_link_get_link', LIBNL_ROUTE)) +_rtnl_link_get_master = _int_proto(('rtnl_link_get_master', LIBNL_ROUTE)) +_rtnl_link_get_mtu = _int_proto(('rtnl_link_get_mtu', LIBNL_ROUTE)) +_rtnl_link_get_name = _char_proto(('rtnl_link_get_name', LIBNL_ROUTE)) +_rtnl_link_get_operstate = _int_proto(('rtnl_link_get_operstate', LIBNL_ROUTE)) +_rtnl_link_get_qdisc = _char_proto(('rtnl_link_get_qdisc', LIBNL_ROUTE)) -_rtnl_addr_get_label = _char_proto(('rtnl_addr_get_label', LIBNL)) -_rtnl_addr_get_ifindex = _int_proto(('rtnl_addr_get_ifindex', LIBNL)) -_rtnl_addr_get_family = _int_proto(('rtnl_addr_get_family', LIBNL)) -_rtnl_addr_get_prefixlen = _int_proto(('rtnl_addr_get_prefixlen', LIBNL)) -_rtnl_addr_get_scope = _int_proto(('rtnl_addr_get_scope', LIBNL)) -_rtnl_addr_get_flags = _int_proto(('rtnl_addr_get_flags', LIBNL)) -_rtnl_addr_get_local = _void_proto(('rtnl_addr_get_local', LIBNL)) +_rtnl_addr_get_label = _char_proto(('rtnl_addr_get_label', LIBNL_ROUTE)) +_rtnl_addr_get_ifindex = _int_proto(('rtnl_addr_get_ifindex', LIBNL_ROUTE)) +_rtnl_addr_get_family = _int_proto(('rtnl_addr_get_family', LIBNL_ROUTE)) +_rtnl_addr_get_prefixlen = _int_proto(('rtnl_addr_get_prefixlen', LIBNL_ROUTE)) +_rtnl_addr_get_scope = _int_proto(('rtnl_addr_get_scope', LIBNL_ROUTE)) +_rtnl_addr_get_flags = _int_proto(('rtnl_addr_get_flags', LIBNL_ROUTE)) +_rtnl_addr_get_local = _void_proto(('rtnl_addr_get_local', LIBNL_ROUTE)) -_nl_addr2str = CFUNCTYPE(c_char_p, c_void_p, c_char_p, c_int)(( +_nl_addr2str = CFUNCTYPE(c_char_p, c_void_p, c_char_p, c_size_t)(( 'nl_addr2str', LIBNL)) _rtnl_link_get_by_name = CFUNCTYPE(c_void_p, c_void_p, c_char_p)(( - 'rtnl_link_get_by_name', LIBNL)) -_rtnl_link_i2name = CFUNCTYPE(c_char_p, c_void_p, c_int, c_char_p, c_int)(( - 'rtnl_link_i2name', LIBNL)) + 'rtnl_link_get_by_name', LIBNL_ROUTE)) +_rtnl_link_i2name = CFUNCTYPE(c_char_p, c_void_p, c_int, c_char_p, c_size_t)(( + 'rtnl_link_i2name', LIBNL_ROUTE)) _rtnl_link_operstate2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_size_t)(( - 'rtnl_link_operstate2str', LIBNL)) -_nl_af2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_int)(('nl_af2str', LIBNL)) -_rtnl_scope2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_int)(( - 'rtnl_scope2str', LIBNL)) + 'rtnl_link_operstate2str', LIBNL_ROUTE)) +_nl_af2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_size_t)(('nl_af2str', + LIBNL)) +_rtnl_scope2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_size_t)(( + 'rtnl_scope2str', LIBNL_ROUTE)) class NLSocketPool(object): @@ -110,20 +156,23 @@ def _open_socket(): """Returns an open netlink socket.""" - handle = _nl_handle_alloc() + handle = _nl_handle_alloc() if LIBNL3 is None else _nl_socket_alloc() if handle is None: raise IOError(get_errno(), 'Failed to allocate netlink handle') err = _nl_connect(handle, NETLINK_ROUTE) if err: - _nl_handle_destroy(handle) + _close_socket(handle) raise IOError(-err, _nl_geterror()) return handle def _close_socket(sock): """Closes and frees the resources of the passed netlink socket.""" - _nl_handle_destroy(sock) + if LIBNL3 is None: + _nl_handle_destroy(sock) + else: + _nl_socket_free(sock) def iter_links(): @@ -204,8 +253,11 @@ # libnl-1 has a bug when getting type information. # https://github.com/tgraf/libnl-1.1-stable/issues/1 - # TODO: Add the following line (and prototype) when the above bug is fixed. - # info['type'] = _rtnl_link_get_info_type(link) + # TODO: Add for libnl1 if the bug is fixed + if LIBNL3: + link_type = _rtnl_link_get_type(link) + if link_type is not None: + info['type'] = link_type underlying_device_index = _rtnl_link_get_link(link) if underlying_device_index > 0: -- To view, visit http://gerrit.ovirt.org/26514 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I45f043a8416e57d5fb550e2e817e6df38cd793b1 Gerrit-PatchSet: 1 Gerrit-Project: vdsm Gerrit-Branch: master Gerrit-Owner: Antoni Segura Puimedon <asegu...@redhat.com> _______________________________________________ vdsm-patches mailing list vdsm-patches@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches