From 83f06bfbb85b475f6c6ba9993ed6de9f0f3f9315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28=D0=BD=D0=BE=D1=83=D1=82=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=20=D0=B4=D0=BE=D0=BC=D0=B0=29?= Date: Tue, 5 Jun 2012 01:08:27 +0600 Subject: Fix indentation (spaces vs tabs) Now, python files use pseudo-tab equal 4 spaces --- python/netlink/core.py | 1132 +++++++++++++++++------------------ python/netlink/route/address.py | 756 +++++++++++------------ python/netlink/route/link.py | 942 ++++++++++++++--------------- python/netlink/route/links/dummy.py | 12 +- python/netlink/route/links/inet.py | 180 +++--- python/netlink/route/links/vlan.py | 104 ++-- python/netlink/route/qdisc/htb.py | 262 ++++---- python/netlink/route/tc.py | 780 ++++++++++++------------ python/netlink/util.py | 216 +++---- 9 files changed, 2192 insertions(+), 2192 deletions(-) (limited to 'python') diff --git a/python/netlink/core.py b/python/netlink/core.py index 0ffa22f6..219b5220 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -11,16 +11,16 @@ This module provides an interface to netlink sockets The module contains the following public classes: - Socket -- The netlink socket - Object -- Abstract object (based on struct nl_obect in libnl) used as - base class for all object types which can be put into a Cache + base class for all object types which can be put into a Cache - Cache -- A collection of objects which are derived from the base - class Object. Used for netlink protocols which maintain a list - or tree of objects. + class Object. Used for netlink protocols which maintain a list + or tree of objects. - DumpParams -- The following exceptions are defined: - NetlinkError -- Base exception for all general purpose exceptions raised. - KernelError -- Raised when the kernel returns an error as response to a - request. + request. All other classes or functions in this module are considered implementation details. @@ -34,7 +34,7 @@ import sys import socket __all__ = ['Message', 'Socket', 'DumpParams', 'Object', 'Cache', 'KernelError', - 'NetlinkError'] + 'NetlinkError'] __version__ = "0.1" # netlink protocols @@ -82,168 +82,168 @@ NLM_F_CREATE = 0x400 NLM_F_APPEND = 0x800 class NetlinkError(Exception): - def __init__(self, error): - self._error = error - self._msg = capi.nl_geterror(error) + def __init__(self, error): + self._error = error + self._msg = capi.nl_geterror(error) - def __str__(self): - return self._msg + def __str__(self): + return self._msg class KernelError(NetlinkError): - def __str__(self): - return "Kernel returned: {0}".format(self._msg) + def __str__(self): + return "Kernel returned: {0}".format(self._msg) class ImmutableError(NetlinkError): - def __init__(self, msg): - self._msg = msg + def __init__(self, msg): + self._msg = msg - def __str__(self): - return "Immutable attribute: {0}".format(self._msg) + def __str__(self): + return "Immutable attribute: {0}".format(self._msg) class Message(object): - """Netlink message""" + """Netlink message""" - def __init__(self, size=0): - if size == 0: - self._msg = capi.nlmsg_alloc() - else: - self._msg = capi.nlmsg_alloc_size(size) + def __init__(self, size=0): + if size == 0: + self._msg = capi.nlmsg_alloc() + else: + self._msg = capi.nlmsg_alloc_size(size) - if self._msg is None: - raise Exception("Message allocation returned NULL") + if self._msg is None: + raise Exception("Message allocation returned NULL") - def __del__(self): - capi.nlmsg_free(self._msg) + def __del__(self): + capi.nlmsg_free(self._msg) - def __len__(self): - return capi.nlmsg_len(nlmsg_hdr(self._msg)) + def __len__(self): + return capi.nlmsg_len(nlmsg_hdr(self._msg)) - @property - def protocol(self): - return capi.nlmsg_get_proto(self._msg) + @property + def protocol(self): + return capi.nlmsg_get_proto(self._msg) - @protocol.setter - def protocol(self, value): - capi.nlmsg_set_proto(self._msg, value) + @protocol.setter + def protocol(self, value): + capi.nlmsg_set_proto(self._msg, value) - @property - def maxSize(self): - return capi.nlmsg_get_max_size(self._msg) + @property + def maxSize(self): + return capi.nlmsg_get_max_size(self._msg) - @property - def hdr(self): - return capi.nlmsg_hdr(self._msg) + @property + def hdr(self): + return capi.nlmsg_hdr(self._msg) - @property - def data(self): - return capi.nlmsg_data(self._msg) + @property + def data(self): + return capi.nlmsg_data(self._msg) - @property - def attrs(self): - return capi.nlmsg_attrdata(self._msg) + @property + def attrs(self): + return capi.nlmsg_attrdata(self._msg) - def send(self, socket): - socket.send(self) + def send(self, socket): + socket.send(self) class Socket(object): - """Netlink socket""" + """Netlink socket""" - def __init__(self, cb=None): - if cb is None: - self._sock = capi.nl_socket_alloc() - else: - self._sock = capi.nl_socket_alloc_cb(cb) + def __init__(self, cb=None): + if cb is None: + self._sock = capi.nl_socket_alloc() + else: + self._sock = capi.nl_socket_alloc_cb(cb) - if self._sock is None: - raise Exception("NULL pointer returned while allocating socket") + if self._sock is None: + raise Exception("NULL pointer returned while allocating socket") - def __del__(self): - capi.nl_socket_free(self._sock) + def __del__(self): + capi.nl_socket_free(self._sock) - def __str__(self): - return "nlsock<{0}>".format(self.localPort) + def __str__(self): + return "nlsock<{0}>".format(self.localPort) - @property - def local_port(self): - return capi.nl_socket_get_local_port(self._sock) + @property + def local_port(self): + return capi.nl_socket_get_local_port(self._sock) - @local_port.setter - def local_port(self, value): - capi.nl_socket_set_local_port(self._sock, int(value)) + @local_port.setter + def local_port(self, value): + capi.nl_socket_set_local_port(self._sock, int(value)) - @property - def peer_port(self): - return capi.nl_socket_get_peer_port(self._sock) + @property + def peer_port(self): + return capi.nl_socket_get_peer_port(self._sock) - @peer_port.setter - def peer_port(self, value): - capi.nl_socket_set_peer_port(self._sock, int(value)) + @peer_port.setter + def peer_port(self, value): + capi.nl_socket_set_peer_port(self._sock, int(value)) - @property - def peer_groups(self): - return capi.nl_socket_get_peer_groups(self._sock) + @property + def peer_groups(self): + return capi.nl_socket_get_peer_groups(self._sock) - @peer_groups.setter - def peer_groups(self, value): - capi.nl_socket_set_peer_groups(self._sock, value) + @peer_groups.setter + def peer_groups(self, value): + capi.nl_socket_set_peer_groups(self._sock, value) - def set_bufsize(self, rx, tx): - capi.nl_socket_set_buffer_size(self._sock, rx, tx) + def set_bufsize(self, rx, tx): + capi.nl_socket_set_buffer_size(self._sock, rx, tx) - def connect(self, proto): - capi.nl_connect(self._sock, proto) - return self + def connect(self, proto): + capi.nl_connect(self._sock, proto) + return self - def disconnect(self): - capi.nl_close(self._sock) + def disconnect(self): + capi.nl_close(self._sock) - def sendto(self, buf): - ret = capi.nl_sendto(self._sock, buf, len(buf)) - if ret < 0: - raise Exception("Failed to send") - else: - return ret + def sendto(self, buf): + ret = capi.nl_sendto(self._sock, buf, len(buf)) + if ret < 0: + raise Exception("Failed to send") + else: + return ret _sockets = {} def lookup_socket(protocol): - try: - sock = _sockets[protocol] - except KeyError: - sock = Socket() - sock.connect(protocol) - _sockets[protocol] = sock + try: + sock = _sockets[protocol] + except KeyError: + sock = Socket() + sock.connect(protocol) + _sockets[protocol] = sock - return sock + return sock class DumpParams(object): - """Dumping parameters""" + """Dumping parameters""" - def __init__(self, type=NL_DUMP_LINE): - self._dp = capi.alloc_dump_params() - if not self._dp: - raise Exception("Unable to allocate struct nl_dump_params") + def __init__(self, type=NL_DUMP_LINE): + self._dp = capi.alloc_dump_params() + if not self._dp: + raise Exception("Unable to allocate struct nl_dump_params") - self._dp.dp_type = type + self._dp.dp_type = type - def __del__(self): - capi.free_dump_params(self._dp) + def __del__(self): + capi.free_dump_params(self._dp) - @property - def type(self): - return self._dp.dp_type + @property + def type(self): + return self._dp.dp_type - @type.setter - def type(self, value): - self._dp.dp_type = value + @type.setter + def type(self, value): + self._dp.dp_type = value - @property - def prefix(self): - return self._dp.dp_prefix + @property + def prefix(self): + return self._dp.dp_prefix - @prefix.setter - def prefix(self, value): - self._dp.dp_prefix = value + @prefix.setter + def prefix(self, value): + self._dp.dp_prefix = value # underscore this to make sure it is deleted first upon module deletion _defaultDumpParams = DumpParams(type=NL_DUMP_LINE) @@ -251,493 +251,493 @@ _defaultDumpParams = DumpParams(type=NL_DUMP_LINE) ########################################################################### # Cacheable Object (Base Class) class Object(object): - """Cacheable object (base class)""" + """Cacheable object (base class)""" - def __init__(self, obj_name, name, obj=None): - self._obj_name = obj_name - self._name = name - self._modules = [] + def __init__(self, obj_name, name, obj=None): + self._obj_name = obj_name + self._name = name + self._modules = [] - if not obj: - obj = capi.object_alloc_name(self._obj_name) - - self._nl_object = obj - - # Create a clone which stores the original state to notice - # modifications - clone_obj = capi.nl_object_clone(self._nl_object) - self._orig = self._obj2type(clone_obj) - - def __del__(self): - if not self._nl_object: - raise ValueError() - - capi.nl_object_put(self._nl_object) - - def __str__(self): - if hasattr(self, 'format'): - return self.format() - else: - return capi.nl_object_dump_buf(self._nl_object, 4096).rstrip() - - def _new_instance(self): - raise NotImplementedError() - - def clone(self): - """Clone object""" - return self._new_instance(capi.nl_object_clone(self._nl_object)) - - def _module_lookup(self, path, constructor=None): - """Lookup object specific module and load it - - Object implementations consisting of multiple types may - offload some type specific code to separate modules which - are loadable on demand, e.g. a VLAN link or a specific - queueing discipline implementation. - - Loads the module `path` and calls the constructor if - supplied or `module`.init() - - The constructor/init function typically assigns a new - object covering the type specific implementation aspects - to the new object, e.g. link.vlan = VLANLink() - """ - try: - tmp = __import__(path) - except ImportError: - return - - module = sys.modules[path] - - if constructor: - ret = getattr(module, constructor)(self) - else: - ret = module.init(self) - - if ret: - self._modules.append(ret) - - def _module_brief(self): - ret = '' - - for module in self._modules: - if hasattr(module, 'brief'): - ret += module.brief() - - return ret - - def dump(self, params=None): - """Dump object as human readable text""" - if params is None: - params = _defaultDumpParams - - capi.nl_object_dump(self._nl_object, params._dp) - - - ##################################################################### - # mark - @property - def mark(self): - if capi.nl_object_is_marked(self.obj): - return True - else: - return False - - @mark.setter - def mark(self, value): - if value: - capi.nl_object_mark(self._nl_object) - else: - capi.nl_object_unmark(self._nl_object) - - ##################################################################### - # shared - @property - def shared(self): - return capi.nl_object_shared(self._nl_object) != 0 - - ##################################################################### - # attrs - @property - def attrs(self): - attr_list = capi.nl_object_attr_list(self._nl_object, 1024) - return re.split('\W+', attr_list[0]) - - ##################################################################### - # refcnt - @property - def refcnt(self): - return capi.nl_object_get_refcnt(self._nl_object) - - # this method resolves multiple levels of sub types to allow - # accessing properties of subclass/subtypes (e.g. link.vlan.id) - def _resolve(self, attr): - obj = self - l = attr.split('.') - while len(l) > 1: - obj = getattr(obj, l.pop(0)) - return (obj, l.pop(0)) - - def _setattr(self, attr, val): - obj, attr = self._resolve(attr) - return setattr(obj, attr, val) - - def _hasattr(self, attr): - obj, attr = self._resolve(attr) - return hasattr(obj, attr) - - def apply(self, attr, val): - try: - d = attrs[self._name + "." + attr] - except KeyError: - raise KeyError("Unknown " + self._name + - " attribute: " + attr) - - if 'immutable' in d: - raise ImmutableError(attr) - - if not self._hasattr(attr): - raise KeyError("Invalid " + self._name + - " attribute: " + attr) - self._setattr(attr, val) + if not obj: + obj = capi.object_alloc_name(self._obj_name) -class ObjIterator(object): - def __init__(self, cache, obj): - self._cache = cache - self._nl_object = None - - if not obj: - self._end = 1 - else: - capi.nl_object_get(obj) - self._nl_object = obj - self._first = 1 - self._end = 0 - - def __del__(self): - if self._nl_object: - capi.nl_object_put(self._nl_object) - - def __iter__(self): - return self - - def get_next(self): - return capi.nl_cache_get_next(self._nl_object) - - def next(self): - if self._end: - raise StopIteration() - - if self._first: - ret = self._nl_object - self._first = 0 - else: - ret = self.get_next() - if not ret: - self._end = 1 - raise StopIteration() - - # return ref of previous element and acquire ref of current - # element to have object stay around until we fetched the - # next ptr - capi.nl_object_put(self._nl_object) - capi.nl_object_get(ret) - self._nl_object = ret - - # reference used inside object - capi.nl_object_get(ret) - return self._cache._new_object(ret) + self._nl_object = obj + # Create a clone which stores the original state to notice + # modifications + clone_obj = capi.nl_object_clone(self._nl_object) + self._orig = self._obj2type(clone_obj) -class ReverseObjIterator(ObjIterator): - def get_next(self): - return capi.nl_cache_get_prev(self._nl_object) + def __del__(self): + if not self._nl_object: + raise ValueError() -########################################################################### -# Cache -class Cache(object): - """Collection of netlink objects""" - def __init__(self): - raise NotImplementedError() - - def __del(self): - capi.nl_cache_free(self._nl_cache) + capi.nl_object_put(self._nl_object) - def __len__(self): - return capi.nl_cache_nitems(self._nl_cache) - - def __iter__(self): - obj = capi.nl_cache_get_first(self._nl_cache) - return ObjIterator(self, obj) + def __str__(self): + if hasattr(self, 'format'): + return self.format() + else: + return capi.nl_object_dump_buf(self._nl_object, 4096).rstrip() - def __reversed__(self): - obj = capi.nl_cache_get_last(self._nl_cache) - return ReverseObjIterator(self, obj) + def _new_instance(self): + raise NotImplementedError() - def __contains__(self, item): - obj = capi.nl_cache_search(self._nl_cache, item._nl_object) - if obj is None: - return False - else: - capi.nl_object_put(obj) - return True + def clone(self): + """Clone object""" + return self._new_instance(capi.nl_object_clone(self._nl_object)) - # called by sub classes to allocate type specific caches by name - def _alloc_cache_name(self, name): - return capi.alloc_cache_name(name) + def _module_lookup(self, path, constructor=None): + """Lookup object specific module and load it - # implemented by sub classes, must return new instasnce of cacheable - # object - def _new_object(self, obj): - raise NotImplementedError() + Object implementations consisting of multiple types may + offload some type specific code to separate modules which + are loadable on demand, e.g. a VLAN link or a specific + queueing discipline implementation. - # implemented by sub classes, must return instance of sub class - def _new_cache(self, cache): - raise NotImplementedError() + Loads the module `path` and calls the constructor if + supplied or `module`.init() - def subset(self, filter): - """Return new cache containing subset of cache + The constructor/init function typically assigns a new + object covering the type specific implementation aspects + to the new object, e.g. link.vlan = VLANLink() + """ + try: + tmp = __import__(path) + except ImportError: + return + + module = sys.modules[path] + + if constructor: + ret = getattr(module, constructor)(self) + else: + ret = module.init(self) + + if ret: + self._modules.append(ret) + + def _module_brief(self): + ret = '' + + for module in self._modules: + if hasattr(module, 'brief'): + ret += module.brief() + + return ret + + def dump(self, params=None): + """Dump object as human readable text""" + if params is None: + params = _defaultDumpParams + + capi.nl_object_dump(self._nl_object, params._dp) + + + ##################################################################### + # mark + @property + def mark(self): + if capi.nl_object_is_marked(self.obj): + return True + else: + return False + + @mark.setter + def mark(self, value): + if value: + capi.nl_object_mark(self._nl_object) + else: + capi.nl_object_unmark(self._nl_object) + + ##################################################################### + # shared + @property + def shared(self): + return capi.nl_object_shared(self._nl_object) != 0 + + ##################################################################### + # attrs + @property + def attrs(self): + attr_list = capi.nl_object_attr_list(self._nl_object, 1024) + return re.split('\W+', attr_list[0]) + + ##################################################################### + # refcnt + @property + def refcnt(self): + return capi.nl_object_get_refcnt(self._nl_object) + + # this method resolves multiple levels of sub types to allow + # accessing properties of subclass/subtypes (e.g. link.vlan.id) + def _resolve(self, attr): + obj = self + l = attr.split('.') + while len(l) > 1: + obj = getattr(obj, l.pop(0)) + return (obj, l.pop(0)) + + def _setattr(self, attr, val): + obj, attr = self._resolve(attr) + return setattr(obj, attr, val) + + def _hasattr(self, attr): + obj, attr = self._resolve(attr) + return hasattr(obj, attr) + + def apply(self, attr, val): + try: + d = attrs[self._name + "." + attr] + except KeyError: + raise KeyError("Unknown " + self._name + + " attribute: " + attr) - Cretes a new cache containing all objects which match the - specified filter. - """ - if not filter: - raise ValueError() + if 'immutable' in d: + raise ImmutableError(attr) - c = capi.nl_cache_subset(self._nl_cache, filter._nl_object) - return self._new_cache(cache=c) + if not self._hasattr(attr): + raise KeyError("Invalid " + self._name + + " attribute: " + attr) + self._setattr(attr, val) - def dump(self, params=None, filter=None): - """Dump (print) cache as human readable text""" - if not params: - params = _defaultDumpParams +class ObjIterator(object): + def __init__(self, cache, obj): + self._cache = cache + self._nl_object = None + + if not obj: + self._end = 1 + else: + capi.nl_object_get(obj) + self._nl_object = obj + self._first = 1 + self._end = 0 + + def __del__(self): + if self._nl_object: + capi.nl_object_put(self._nl_object) + + def __iter__(self): + return self + + def get_next(self): + return capi.nl_cache_get_next(self._nl_object) + + def next(self): + if self._end: + raise StopIteration() + + if self._first: + ret = self._nl_object + self._first = 0 + else: + ret = self.get_next() + if not ret: + self._end = 1 + raise StopIteration() + + # return ref of previous element and acquire ref of current + # element to have object stay around until we fetched the + # next ptr + capi.nl_object_put(self._nl_object) + capi.nl_object_get(ret) + self._nl_object = ret + + # reference used inside object + capi.nl_object_get(ret) + return self._cache._new_object(ret) - if filter: - filter = filter._nl_object - capi.nl_cache_dump_filter(self._nl_cache, params._dp, filter) +class ReverseObjIterator(ObjIterator): + def get_next(self): + return capi.nl_cache_get_prev(self._nl_object) - def clear(self): - """Remove all cache entries""" - capi.nl_cache_clear(self._nl_cache) +########################################################################### +# Cache +class Cache(object): + """Collection of netlink objects""" + def __init__(self): + raise NotImplementedError() + + def __del(self): + capi.nl_cache_free(self._nl_cache) + + def __len__(self): + return capi.nl_cache_nitems(self._nl_cache) + + def __iter__(self): + obj = capi.nl_cache_get_first(self._nl_cache) + return ObjIterator(self, obj) + + def __reversed__(self): + obj = capi.nl_cache_get_last(self._nl_cache) + return ReverseObjIterator(self, obj) + + def __contains__(self, item): + obj = capi.nl_cache_search(self._nl_cache, item._nl_object) + if obj is None: + return False + else: + capi.nl_object_put(obj) + return True + + # called by sub classes to allocate type specific caches by name + def _alloc_cache_name(self, name): + return capi.alloc_cache_name(name) + + # implemented by sub classes, must return new instasnce of cacheable + # object + def _new_object(self, obj): + raise NotImplementedError() + + # implemented by sub classes, must return instance of sub class + def _new_cache(self, cache): + raise NotImplementedError() + + def subset(self, filter): + """Return new cache containing subset of cache + + Cretes a new cache containing all objects which match the + specified filter. + """ + if not filter: + raise ValueError() - # Called by sub classes to set first cache argument - def _set_arg1(self, arg): - self.arg1 = arg - capi.nl_cache_set_arg1(self._nl_cache, arg) + c = capi.nl_cache_subset(self._nl_cache, filter._nl_object) + return self._new_cache(cache=c) - # Called by sub classes to set second cache argument - def _set_arg2(self, arg): - self.arg2 = arg - capi.nl_cache_set_arg2(self._nl_cache, arg) + def dump(self, params=None, filter=None): + """Dump (print) cache as human readable text""" + if not params: + params = _defaultDumpParams - def refill(self, socket=None): - """Clear cache and refill it""" - if socket is None: - socket = lookup_socket(self._protocol) + if filter: + filter = filter._nl_object - capi.nl_cache_refill(socket._sock, self._nl_cache) - return self + capi.nl_cache_dump_filter(self._nl_cache, params._dp, filter) - def resync(self, socket=None, cb=None): - """Synchronize cache with content in kernel""" - if socket is None: - socket = lookup_socket(self._protocol) + def clear(self): + """Remove all cache entries""" + capi.nl_cache_clear(self._nl_cache) - capi.nl_cache_resync(socket._sock, self._nl_cache, cb) + # Called by sub classes to set first cache argument + def _set_arg1(self, arg): + self.arg1 = arg + capi.nl_cache_set_arg1(self._nl_cache, arg) - def provide(self): - """Provide this cache to others + # Called by sub classes to set second cache argument + def _set_arg2(self, arg): + self.arg2 = arg + capi.nl_cache_set_arg2(self._nl_cache, arg) - Caches which have been "provided" are made available - to other users (of the same application context) which - "require" it. F.e. a link cache is generally provided - to allow others to translate interface indexes to - link names - """ + def refill(self, socket=None): + """Clear cache and refill it""" + if socket is None: + socket = lookup_socket(self._protocol) - capi.nl_cache_mngt_provide(self._nl_cache) + capi.nl_cache_refill(socket._sock, self._nl_cache) + return self - def unprovide(self): - """Unprovide this cache + def resync(self, socket=None, cb=None): + """Synchronize cache with content in kernel""" + if socket is None: + socket = lookup_socket(self._protocol) - No longer make the cache available to others. If the cache - has been handed out already, that reference will still - be valid. - """ - capi.nl_cache_mngt_unprovide(self._nl_cache) + capi.nl_cache_resync(socket._sock, self._nl_cache, cb) + + def provide(self): + """Provide this cache to others + + Caches which have been "provided" are made available + to other users (of the same application context) which + "require" it. F.e. a link cache is generally provided + to allow others to translate interface indexes to + link names + """ + + capi.nl_cache_mngt_provide(self._nl_cache) + + def unprovide(self): + """Unprovide this cache + + No longer make the cache available to others. If the cache + has been handed out already, that reference will still + be valid. + """ + capi.nl_cache_mngt_unprovide(self._nl_cache) ########################################################################### # Cache Manager (Work in Progress) NL_AUTO_PROVIDE = 1 class CacheManager(object): - def __init__(self, protocol, flags=None): + def __init__(self, protocol, flags=None): - self._sock = Socket() - self._sock.connect(protocol) + self._sock = Socket() + self._sock.connect(protocol) - if not flags: - flags = NL_AUTO_PROVIDE + if not flags: + flags = NL_AUTO_PROVIDE - self._mngr = cache_mngr_alloc(self._sock._sock, protocol, flags) + self._mngr = cache_mngr_alloc(self._sock._sock, protocol, flags) - def __del__(self): - if self._sock: - self._sock.disconnect() + def __del__(self): + if self._sock: + self._sock.disconnect() - if self._mngr: - capi.nl_cache_mngr_free(self._mngr) + if self._mngr: + capi.nl_cache_mngr_free(self._mngr) - def add(self, name): - capi.cache_mngr_add(self._mngr, name, None, None) + def add(self, name): + capi.cache_mngr_add(self._mngr, name, None, None) ########################################################################### # Address Family class AddressFamily(object): - """Address family representation + """Address family representation - af = AddressFamily('inet6') - # raises: - # - ValueError if family name is not known - # - TypeError if invalid type is specified for family + af = AddressFamily('inet6') + # raises: + # - ValueError if family name is not known + # - TypeError if invalid type is specified for family - print af # => 'inet6' (string representation) - print int(af) # => 10 (numeric representation) - print repr(af) # => AddressFamily('inet6') - """ - def __init__(self, family=socket.AF_UNSPEC): - if isinstance(family, str): - family = capi.nl_str2af(family) - if family < 0: - raise ValueError('Unknown family name') - elif not isinstance(family, int): - raise TypeError() + print af # => 'inet6' (string representation) + print int(af) # => 10 (numeric representation) + print repr(af) # => AddressFamily('inet6') + """ + def __init__(self, family=socket.AF_UNSPEC): + if isinstance(family, str): + family = capi.nl_str2af(family) + if family < 0: + raise ValueError('Unknown family name') + elif not isinstance(family, int): + raise TypeError() - self._family = family + self._family = family - def __str__(self): - return capi.nl_af2str(self._family, 32)[0] + def __str__(self): + return capi.nl_af2str(self._family, 32)[0] - def __int__(self): - return self._family + def __int__(self): + return self._family - def __repr__(self): - return 'AddressFamily({0!r})'.format(str(self)) + def __repr__(self): + return 'AddressFamily({0!r})'.format(str(self)) ########################################################################### # Abstract Address class AbstractAddress(object): - """Abstract address object - - addr = AbstractAddress('127.0.0.1/8') - print addr # => '127.0.0.1/8' - print addr.prefixlen # => '8' - print addr.family # => 'inet' - print len(addr) # => '4' (32bit ipv4 address) - - a = AbstractAddress('10.0.0.1/24') - b = AbstractAddress('10.0.0.2/24') - print a == b # => False + """Abstract address object + + addr = AbstractAddress('127.0.0.1/8') + print addr # => '127.0.0.1/8' + print addr.prefixlen # => '8' + print addr.family # => 'inet' + print len(addr) # => '4' (32bit ipv4 address) + + a = AbstractAddress('10.0.0.1/24') + b = AbstractAddress('10.0.0.2/24') + print a == b # => False + + + """ + def __init__(self, addr): + self._nl_addr = None + + if isinstance(addr, str): + addr = capi.addr_parse(addr, socket.AF_UNSPEC) + if addr is None: + raise ValueError('Invalid address format') + elif addr: + capi.nl_addr_get(addr) + + self._nl_addr = addr + + def __del__(self): + if self._nl_addr: + capi.nl_addr_put(self._nl_addr) + + def __cmp__(self, other): + if isinstance(other, str): + other = AbstractAddress(other) + + diff = self.prefixlen - other.prefixlen + if diff == 0: + diff = capi.nl_addr_cmp(self._nl_addr, other._nl_addr) + + return diff + + def contains(self, item): + diff = int(self.family) - int(item.family) + if diff: + return False + + if item.prefixlen < self.prefixlen: + return False + + diff = capi.nl_addr_cmp_prefix(self._nl_addr, item._nl_addr) + return diff == 0 + + def __nonzero__(self): + if self._nl_addr: + return not capi.nl_addr_iszero(self._nl_addr) + else: + return False + + def __len__(self): + if self._nl_addr: + return capi.nl_addr_get_len(self._nl_addr) + else: + return 0 + + def __str__(self): + if self._nl_addr: + return capi.nl_addr2str(self._nl_addr, 64)[0] + else: + return "none" + + @property + def shared(self): + """True if address is shared (multiple users)""" + if self._nl_addr: + return capi.nl_addr_shared(self._nl_addr) != 0 + else: + return False + + @property + def prefixlen(self): + """Length of prefix (number of bits)""" + if self._nl_addr: + return capi.nl_addr_get_prefixlen(self._nl_addr) + else: + return 0 + + @prefixlen.setter + def prefixlen(self, value): + if not self._nl_addr: + raise TypeError() + + capi.nl_addr_set_prefixlen(self._nl_addr, int(value)) + + @property + def family(self): + """Address family""" + f = 0 + if self._nl_addr: + f = capi.nl_addr_get_family(self._nl_addr) + + return AddressFamily(f) + + @family.setter + def family(self, value): + if not self._nl_addr: + raise TypeError() - - """ - def __init__(self, addr): - self._nl_addr = None - - if isinstance(addr, str): - addr = capi.addr_parse(addr, socket.AF_UNSPEC) - if addr is None: - raise ValueError('Invalid address format') - elif addr: - capi.nl_addr_get(addr) - - self._nl_addr = addr - - def __del__(self): - if self._nl_addr: - capi.nl_addr_put(self._nl_addr) - - def __cmp__(self, other): - if isinstance(other, str): - other = AbstractAddress(other) - - diff = self.prefixlen - other.prefixlen - if diff == 0: - diff = capi.nl_addr_cmp(self._nl_addr, other._nl_addr) - - return diff - - def contains(self, item): - diff = int(self.family) - int(item.family) - if diff: - return False - - if item.prefixlen < self.prefixlen: - return False - - diff = capi.nl_addr_cmp_prefix(self._nl_addr, item._nl_addr) - return diff == 0 - - def __nonzero__(self): - if self._nl_addr: - return not capi.nl_addr_iszero(self._nl_addr) - else: - return False - - def __len__(self): - if self._nl_addr: - return capi.nl_addr_get_len(self._nl_addr) - else: - return 0 - - def __str__(self): - if self._nl_addr: - return capi.nl_addr2str(self._nl_addr, 64)[0] - else: - return "none" - - @property - def shared(self): - """True if address is shared (multiple users)""" - if self._nl_addr: - return capi.nl_addr_shared(self._nl_addr) != 0 - else: - return False - - @property - def prefixlen(self): - """Length of prefix (number of bits)""" - if self._nl_addr: - return capi.nl_addr_get_prefixlen(self._nl_addr) - else: - return 0 - - @prefixlen.setter - def prefixlen(self, value): - if not self._nl_addr: - raise TypeError() - - capi.nl_addr_set_prefixlen(self._nl_addr, int(value)) - - @property - def family(self): - """Address family""" - f = 0 - if self._nl_addr: - f = capi.nl_addr_get_family(self._nl_addr) - - return AddressFamily(f) - - @family.setter - def family(self, value): - if not self._nl_addr: - raise TypeError() - - if not isinstance(value, AddressFamily): - value = AddressFamily(value) - - capi.nl_addr_set_family(self._nl_addr, int(value)) + if not isinstance(value, AddressFamily): + value = AddressFamily(value) + + capi.nl_addr_set_family(self._nl_addr, int(value)) # global dictionay for all object attributes @@ -752,30 +752,30 @@ class AbstractAddress(object): attrs = {} def add_attr(name, **kwds): - attrs[name] = {} - for k in kwds: - attrs[name][k] = kwds[k] + attrs[name] = {} + for k in kwds: + attrs[name][k] = kwds[k] def nlattr(name, **kwds): - """netlink object attribute decorator + """netlink object attribute decorator - decorator used to mark mutable and immutable properties - of netlink objects. All properties marked as such are - regarded to be accessable. + decorator used to mark mutable and immutable properties + of netlink objects. All properties marked as such are + regarded to be accessable. - @netlink.nlattr('my_type.my_attr', type=int) - @property - def my_attr(self): - return self._my_attr + @netlink.nlattr('my_type.my_attr', type=int) + @property + def my_attr(self): + return self._my_attr - """ + """ - attrs[name] = {} - for k in kwds: - attrs[name][k] = kwds[k] + attrs[name] = {} + for k in kwds: + attrs[name][k] = kwds[k] - def wrap_fn(func): - return func + def wrap_fn(func): + return func - return wrap_fn + return wrap_fn diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py index a8da1ed1..b5f24489 100644 --- a/python/netlink/route/address.py +++ b/python/netlink/route/address.py @@ -10,8 +10,8 @@ from __future__ import absolute_import __version__ = "1.0" __all__ = [ - 'AddressCache', - 'Address'] + 'AddressCache', + 'Address'] import datetime from .. import core as netlink @@ -23,391 +23,391 @@ from .. import util as util ########################################################################### # Address Cache class AddressCache(netlink.Cache): - """Cache containing network addresses""" + """Cache containing network addresses""" - def __init__(self, cache=None): - if not cache: - cache = self._alloc_cache_name("route/addr") + def __init__(self, cache=None): + if not cache: + cache = self._alloc_cache_name("route/addr") - self._protocol = netlink.NETLINK_ROUTE - self._nl_cache = cache + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache - def __getitem__(self, key): - # Using ifindex=0 here implies that the local address itself - # is unique, otherwise the first occurence is returned. - return self.lookup(0, key) + def __getitem__(self, key): + # Using ifindex=0 here implies that the local address itself + # is unique, otherwise the first occurence is returned. + return self.lookup(0, key) - def lookup(self, ifindex, local): - if type(local) is str: - local = netlink.AbstractAddress(local) + def lookup(self, ifindex, local): + if type(local) is str: + local = netlink.AbstractAddress(local) - addr = capi.rtnl_addr_get(self._nl_cache, ifindex, - local._nl_addr) - if addr is None: - raise KeyError() + addr = capi.rtnl_addr_get(self._nl_cache, ifindex, + local._nl_addr) + if addr is None: + raise KeyError() - return Address._from_capi(addr) + return Address._from_capi(addr) - def _new_object(self, obj): - return Address(obj) + def _new_object(self, obj): + return Address(obj) - def _new_cache(self, cache): - return AddressCache(cache=cache) + def _new_cache(self, cache): + return AddressCache(cache=cache) ########################################################################### # Address Object class Address(netlink.Object): - """Network address""" - - def __init__(self, obj=None): - netlink.Object.__init__(self, "route/addr", "address", obj) - self._rtnl_addr = self._obj2type(self._nl_object) - - @classmethod - def _from_capi(cls, obj): - return cls(capi.addr2obj(obj)) - - def _obj2type(self, obj): - return capi.obj2addr(obj) - - def __cmp__(self, other): - # sort by: - # 1. network link - # 2. address family - # 3. local address (including prefixlen) - diff = self.ifindex - other.ifindex - - if diff == 0: - diff = self.family - other.family - if diff == 0: - diff = capi.nl_addr_cmp(self.local, other.local) - - return diff - - def _new_instance(self, obj): - return Address(obj) - - ##################################################################### - # ifindex - @netlink.nlattr('address.ifindex', type=int, immutable=True, - fmt=util.num) - @property - def ifindex(self): - """interface index""" - return capi.rtnl_addr_get_ifindex(self._rtnl_addr) - - @ifindex.setter - def ifindex(self, value): - link = Link.resolve(value) - if not link: - raise ValueError() - - self.link = link - - ##################################################################### - # link - @netlink.nlattr('address.link', type=str, fmt=util.string) - @property - def link(self): - link = capi.rtnl_addr_get_link(self._rtnl_addr) - if not link: - return None - - return Link.Link.from_capi(link) - - @link.setter - def link(self, value): - if type(value) is str: - try: - value = Link.resolve(value) - except KeyError: - raise ValueError() - - capi.rtnl_addr_set_link(self._rtnl_addr, value._rtnl_link) - - # ifindex is immutable but we assume that if _orig does not - # have an ifindex specified, it was meant to be given here - if capi.rtnl_addr_get_ifindex(self._orig) == 0: - capi.rtnl_addr_set_ifindex(self._orig, value.ifindex) - - ##################################################################### - # label - @netlink.nlattr('address.label', type=str, fmt=util.string) - @property - def label(self): - """address label""" - return capi.rtnl_addr_get_label(self._rtnl_addr) - - @label.setter - def label(self, value): - capi.rtnl_addr_set_label(self._rtnl_addr, value) - - ##################################################################### - # flags - @netlink.nlattr('address.flags', type=str, fmt=util.string) - @property - def flags(self): - """Flags - - Setting this property will *Not* reset flags to value you supply in - - Examples: - addr.flags = '+xxx' # add xxx flag - addr.flags = 'xxx' # exactly the same - addr.flags = '-xxx' # remove xxx flag - addr.flags = [ '+xxx', '-yyy' ] # list operation - """ - flags = capi.rtnl_addr_get_flags(self._rtnl_addr) - return capi.rtnl_addr_flags2str(flags, 256)[0].split(',') - - def _set_flag(self, flag): - if flag.startswith('-'): - i = capi.rtnl_addr_str2flags(flag[1:]) - capi.rtnl_addr_unset_flags(self._rtnl_addr, i) - elif flag.startswith('+'): - i = capi.rtnl_addr_str2flags(flag[1:]) - capi.rtnl_addr_set_flags(self._rtnl_addr, i) - else: - i = capi.rtnl_addr_str2flags(flag) - capi.rtnl_addr_set_flags(self._rtnl_addr, i) - - @flags.setter - def flags(self, value): - if type(value) is list: - for flag in value: - self._set_flag(flag) - else: - self._set_flag(value) - - ##################################################################### - # family - @netlink.nlattr('address.family', type=int, immutable=True, - fmt=util.num) - @property - def family(self): - """Address family""" - fam = capi.rtnl_addr_get_family(self._rtnl_addr) - return netlink.AddressFamily(fam) - - @family.setter - def family(self, value): - if not isinstance(value, AddressFamily): - value = AddressFamily(value) - - capi.rtnl_addr_set_family(self._rtnl_addr, int(value)) - - ##################################################################### - # scope - @netlink.nlattr('address.scope', type=int, fmt=util.num) - @property - def scope(self): - """Address scope""" - scope = capi.rtnl_addr_get_scope(self._rtnl_addr) - return capi.rtnl_scope2str(scope, 32)[0] - - @scope.setter - def scope(self, value): - if type(value) is str: - value = capi.rtnl_str2scope(value) - capi.rtnl_addr_set_scope(self._rtnl_addr, value) - - ##################################################################### - # local address - @netlink.nlattr('address.local', type=str, immutable=True, - fmt=util.addr) - @property - def local(self): - """Local address""" - a = capi.rtnl_addr_get_local(self._rtnl_addr) - return netlink.AbstractAddress(a) - - @local.setter - def local(self, value): - a = netlink.AbstractAddress(value) - capi.rtnl_addr_set_local(self._rtnl_addr, a._nl_addr) - - # local is immutable but we assume that if _orig does not - # have a local address specified, it was meant to be given here - if capi.rtnl_addr_get_local(self._orig) is None: - capi.rtnl_addr_set_local(self._orig, a._nl_addr) - - ##################################################################### - # Peer address - @netlink.nlattr('address.peer', type=str, fmt=util.addr) - @property - def peer(self): - """Peer address""" - a = capi.rtnl_addr_get_peer(self._rtnl_addr) - return netlink.AbstractAddress(a) - - @peer.setter - def peer(self, value): - a = netlink.AbstractAddress(value) - capi.rtnl_addr_set_peer(self._rtnl_addr, a._nl_addr) - - ##################################################################### - # Broadcast address - @netlink.nlattr('address.broadcast', type=str, fmt=util.addr) - @property - def broadcast(self): - """Broadcast address""" - a = capi.rtnl_addr_get_broadcast(self._rtnl_addr) - return netlink.AbstractAddress(a) - - @broadcast.setter - def broadcast(self, value): - a = netlink.AbstractAddress(value) - capi.rtnl_addr_set_broadcast(self._rtnl_addr, a._nl_addr) - - ##################################################################### - # Multicast address - @netlink.nlattr('address.multicast', type=str, fmt=util.addr) - @property - def multicast(self): - """multicast address""" - a = capi.rtnl_addr_get_multicast(self._rtnl_addr) - return netlink.AbstractAddress(a) - - @multicast.setter - def multicast(self, value): - try: - a = netlink.AbstractAddress(value) - except ValueError as err: - raise AttributeError('multicast', err) - - capi.rtnl_addr_set_multicast(self._rtnl_addr, a._nl_addr) - - ##################################################################### - # Anycast address - @netlink.nlattr('address.anycast', type=str, fmt=util.addr) - @property - def anycast(self): - """anycast address""" - a = capi.rtnl_addr_get_anycast(self._rtnl_addr) - return netlink.AbstractAddress(a) - - @anycast.setter - def anycast(self, value): - a = netlink.AbstractAddress(value) - capi.rtnl_addr_set_anycast(self._rtnl_addr, a._nl_addr) - - ##################################################################### - # Valid lifetime - @netlink.nlattr('address.valid_lifetime', type=int, immutable=True, - fmt=util.num) - @property - def valid_lifetime(self): - """Valid lifetime""" - msecs = capi.rtnl_addr_get_valid_lifetime(self._rtnl_addr) - if msecs == 0xFFFFFFFF: - return None - else: - return datetime.timedelta(seconds=msecs) - - @valid_lifetime.setter - def valid_lifetime(self, value): - capi.rtnl_addr_set_valid_lifetime(self._rtnl_addr, int(value)) - - ##################################################################### - # Preferred lifetime - @netlink.nlattr('address.preferred_lifetime', type=int, - immutable=True, fmt=util.num) - @property - def preferred_lifetime(self): - """Preferred lifetime""" - msecs = capi.rtnl_addr_get_preferred_lifetime(self._rtnl_addr) - if msecs == 0xFFFFFFFF: - return None - else: - return datetime.timedelta(seconds=msecs) - - @preferred_lifetime.setter - def preferred_lifetime(self, value): - capi.rtnl_addr_set_preferred_lifetime(self._rtnl_addr, int(value)) - - ##################################################################### - # Creation Time - @netlink.nlattr('address.create_time', type=int, immutable=True, - fmt=util.num) - @property - def create_time(self): - """Creation time""" - hsec = capi.rtnl_addr_get_create_time(self._rtnl_addr) - return datetime.timedelta(milliseconds=10*hsec) - - ##################################################################### - # Last Update - @netlink.nlattr('address.last_update', type=int, immutable=True, - fmt=util.num) - @property - def last_update(self): - """Last update""" - hsec = capi.rtnl_addr_get_last_update_time(self._rtnl_addr) - return datetime.timedelta(milliseconds=10*hsec) - - ##################################################################### - # add() - def add(self, socket=None, flags=None): - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) - - if not flags: - flags = netlink.NLM_F_CREATE - - ret = capi.rtnl_addr_add(socket._sock, self._rtnl_addr, flags) - if ret < 0: - raise netlink.KernelError(ret) - - ##################################################################### - # delete() - def delete(self, socket, flags=0): - """Attempt to delete this address in the kernel""" - ret = capi.rtnl_addr_delete(socket._sock, self._rtnl_addr, flags) - if ret < 0: - raise netlink.KernelError(ret) - - ################################################################### - # private properties - # - # Used for formatting output. USE AT OWN RISK - @property - def _flags(self): - return ','.join(self.flags) - - ################################################################### - # - # format(details=False, stats=False) - # - def format(self, details=False, stats=False, nodev=False, indent=''): - """Return address as formatted text""" - fmt = util.MyFormatter(self, indent) - - buf = fmt.format('{a|local!b}') - - if not nodev: - buf += fmt.format(' {a|ifindex}') - - buf += fmt.format(' {a|scope}') - - if self.label: - buf += fmt.format(' "{a|label}"') - - buf += fmt.format(' <{a|_flags}>') - - if details: - buf += fmt.nl('\t{t|broadcast} {t|multicast}') \ - + fmt.nl('\t{t|peer} {t|anycast}') - - if self.valid_lifetime: - buf += fmt.nl('\t{s|valid-lifetime!k} '\ - '{a|valid_lifetime}') - - if self.preferred_lifetime: - buf += fmt.nl('\t{s|preferred-lifetime!k} '\ - '{a|preferred_lifetime}') - - if stats and (self.create_time or self.last_update): - buf += self.nl('\t{s|created!k} {a|create_time}'\ - ' {s|last-updated!k} {a|last_update}') - - return buf + """Network address""" + + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/addr", "address", obj) + self._rtnl_addr = self._obj2type(self._nl_object) + + @classmethod + def _from_capi(cls, obj): + return cls(capi.addr2obj(obj)) + + def _obj2type(self, obj): + return capi.obj2addr(obj) + + def __cmp__(self, other): + # sort by: + # 1. network link + # 2. address family + # 3. local address (including prefixlen) + diff = self.ifindex - other.ifindex + + if diff == 0: + diff = self.family - other.family + if diff == 0: + diff = capi.nl_addr_cmp(self.local, other.local) + + return diff + + def _new_instance(self, obj): + return Address(obj) + + ##################################################################### + # ifindex + @netlink.nlattr('address.ifindex', type=int, immutable=True, + fmt=util.num) + @property + def ifindex(self): + """interface index""" + return capi.rtnl_addr_get_ifindex(self._rtnl_addr) + + @ifindex.setter + def ifindex(self, value): + link = Link.resolve(value) + if not link: + raise ValueError() + + self.link = link + + ##################################################################### + # link + @netlink.nlattr('address.link', type=str, fmt=util.string) + @property + def link(self): + link = capi.rtnl_addr_get_link(self._rtnl_addr) + if not link: + return None + + return Link.Link.from_capi(link) + + @link.setter + def link(self, value): + if type(value) is str: + try: + value = Link.resolve(value) + except KeyError: + raise ValueError() + + capi.rtnl_addr_set_link(self._rtnl_addr, value._rtnl_link) + + # ifindex is immutable but we assume that if _orig does not + # have an ifindex specified, it was meant to be given here + if capi.rtnl_addr_get_ifindex(self._orig) == 0: + capi.rtnl_addr_set_ifindex(self._orig, value.ifindex) + + ##################################################################### + # label + @netlink.nlattr('address.label', type=str, fmt=util.string) + @property + def label(self): + """address label""" + return capi.rtnl_addr_get_label(self._rtnl_addr) + + @label.setter + def label(self, value): + capi.rtnl_addr_set_label(self._rtnl_addr, value) + + ##################################################################### + # flags + @netlink.nlattr('address.flags', type=str, fmt=util.string) + @property + def flags(self): + """Flags + + Setting this property will *Not* reset flags to value you supply in + + Examples: + addr.flags = '+xxx' # add xxx flag + addr.flags = 'xxx' # exactly the same + addr.flags = '-xxx' # remove xxx flag + addr.flags = [ '+xxx', '-yyy' ] # list operation + """ + flags = capi.rtnl_addr_get_flags(self._rtnl_addr) + return capi.rtnl_addr_flags2str(flags, 256)[0].split(',') + + def _set_flag(self, flag): + if flag.startswith('-'): + i = capi.rtnl_addr_str2flags(flag[1:]) + capi.rtnl_addr_unset_flags(self._rtnl_addr, i) + elif flag.startswith('+'): + i = capi.rtnl_addr_str2flags(flag[1:]) + capi.rtnl_addr_set_flags(self._rtnl_addr, i) + else: + i = capi.rtnl_addr_str2flags(flag) + capi.rtnl_addr_set_flags(self._rtnl_addr, i) + + @flags.setter + def flags(self, value): + if type(value) is list: + for flag in value: + self._set_flag(flag) + else: + self._set_flag(value) + + ##################################################################### + # family + @netlink.nlattr('address.family', type=int, immutable=True, + fmt=util.num) + @property + def family(self): + """Address family""" + fam = capi.rtnl_addr_get_family(self._rtnl_addr) + return netlink.AddressFamily(fam) + + @family.setter + def family(self, value): + if not isinstance(value, AddressFamily): + value = AddressFamily(value) + + capi.rtnl_addr_set_family(self._rtnl_addr, int(value)) + + ##################################################################### + # scope + @netlink.nlattr('address.scope', type=int, fmt=util.num) + @property + def scope(self): + """Address scope""" + scope = capi.rtnl_addr_get_scope(self._rtnl_addr) + return capi.rtnl_scope2str(scope, 32)[0] + + @scope.setter + def scope(self, value): + if type(value) is str: + value = capi.rtnl_str2scope(value) + capi.rtnl_addr_set_scope(self._rtnl_addr, value) + + ##################################################################### + # local address + @netlink.nlattr('address.local', type=str, immutable=True, + fmt=util.addr) + @property + def local(self): + """Local address""" + a = capi.rtnl_addr_get_local(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @local.setter + def local(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_local(self._rtnl_addr, a._nl_addr) + + # local is immutable but we assume that if _orig does not + # have a local address specified, it was meant to be given here + if capi.rtnl_addr_get_local(self._orig) is None: + capi.rtnl_addr_set_local(self._orig, a._nl_addr) + + ##################################################################### + # Peer address + @netlink.nlattr('address.peer', type=str, fmt=util.addr) + @property + def peer(self): + """Peer address""" + a = capi.rtnl_addr_get_peer(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @peer.setter + def peer(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_peer(self._rtnl_addr, a._nl_addr) + + ##################################################################### + # Broadcast address + @netlink.nlattr('address.broadcast', type=str, fmt=util.addr) + @property + def broadcast(self): + """Broadcast address""" + a = capi.rtnl_addr_get_broadcast(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @broadcast.setter + def broadcast(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_broadcast(self._rtnl_addr, a._nl_addr) + + ##################################################################### + # Multicast address + @netlink.nlattr('address.multicast', type=str, fmt=util.addr) + @property + def multicast(self): + """multicast address""" + a = capi.rtnl_addr_get_multicast(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @multicast.setter + def multicast(self, value): + try: + a = netlink.AbstractAddress(value) + except ValueError as err: + raise AttributeError('multicast', err) + + capi.rtnl_addr_set_multicast(self._rtnl_addr, a._nl_addr) + + ##################################################################### + # Anycast address + @netlink.nlattr('address.anycast', type=str, fmt=util.addr) + @property + def anycast(self): + """anycast address""" + a = capi.rtnl_addr_get_anycast(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @anycast.setter + def anycast(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_anycast(self._rtnl_addr, a._nl_addr) + + ##################################################################### + # Valid lifetime + @netlink.nlattr('address.valid_lifetime', type=int, immutable=True, + fmt=util.num) + @property + def valid_lifetime(self): + """Valid lifetime""" + msecs = capi.rtnl_addr_get_valid_lifetime(self._rtnl_addr) + if msecs == 0xFFFFFFFF: + return None + else: + return datetime.timedelta(seconds=msecs) + + @valid_lifetime.setter + def valid_lifetime(self, value): + capi.rtnl_addr_set_valid_lifetime(self._rtnl_addr, int(value)) + + ##################################################################### + # Preferred lifetime + @netlink.nlattr('address.preferred_lifetime', type=int, + immutable=True, fmt=util.num) + @property + def preferred_lifetime(self): + """Preferred lifetime""" + msecs = capi.rtnl_addr_get_preferred_lifetime(self._rtnl_addr) + if msecs == 0xFFFFFFFF: + return None + else: + return datetime.timedelta(seconds=msecs) + + @preferred_lifetime.setter + def preferred_lifetime(self, value): + capi.rtnl_addr_set_preferred_lifetime(self._rtnl_addr, int(value)) + + ##################################################################### + # Creation Time + @netlink.nlattr('address.create_time', type=int, immutable=True, + fmt=util.num) + @property + def create_time(self): + """Creation time""" + hsec = capi.rtnl_addr_get_create_time(self._rtnl_addr) + return datetime.timedelta(milliseconds=10*hsec) + + ##################################################################### + # Last Update + @netlink.nlattr('address.last_update', type=int, immutable=True, + fmt=util.num) + @property + def last_update(self): + """Last update""" + hsec = capi.rtnl_addr_get_last_update_time(self._rtnl_addr) + return datetime.timedelta(milliseconds=10*hsec) + + ##################################################################### + # add() + def add(self, socket=None, flags=None): + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + if not flags: + flags = netlink.NLM_F_CREATE + + ret = capi.rtnl_addr_add(socket._sock, self._rtnl_addr, flags) + if ret < 0: + raise netlink.KernelError(ret) + + ##################################################################### + # delete() + def delete(self, socket, flags=0): + """Attempt to delete this address in the kernel""" + ret = capi.rtnl_addr_delete(socket._sock, self._rtnl_addr, flags) + if ret < 0: + raise netlink.KernelError(ret) + + ################################################################### + # private properties + # + # Used for formatting output. USE AT OWN RISK + @property + def _flags(self): + return ','.join(self.flags) + + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, nodev=False, indent=''): + """Return address as formatted text""" + fmt = util.MyFormatter(self, indent) + + buf = fmt.format('{a|local!b}') + + if not nodev: + buf += fmt.format(' {a|ifindex}') + + buf += fmt.format(' {a|scope}') + + if self.label: + buf += fmt.format(' "{a|label}"') + + buf += fmt.format(' <{a|_flags}>') + + if details: + buf += fmt.nl('\t{t|broadcast} {t|multicast}') \ + + fmt.nl('\t{t|peer} {t|anycast}') + + if self.valid_lifetime: + buf += fmt.nl('\t{s|valid-lifetime!k} '\ + '{a|valid_lifetime}') + + if self.preferred_lifetime: + buf += fmt.nl('\t{s|preferred-lifetime!k} '\ + '{a|preferred_lifetime}') + + if stats and (self.create_time or self.last_update): + buf += self.nl('\t{s|created!k} {a|create_time}'\ + ' {s|last-updated!k} {a|last_update}') + + return buf diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index b7a377ab..465b3b35 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -8,26 +8,26 @@ This module provides an interface to view configured network links, modify them and to add and delete virtual network links. The following is a basic example: - import netlink.core as netlink - import netlink.route.link as link + import netlink.core as netlink + import netlink.route.link as link - sock = netlink.Socket() - sock.connect(netlink.NETLINK_ROUTE) + sock = netlink.Socket() + sock.connect(netlink.NETLINK_ROUTE) - cache = link.LinkCache() # create new empty link cache - cache.refill(sock) # fill cache with all configured links - eth0 = cache['eth0'] # lookup link "eth0" - print eth0 # print basic configuration + cache = link.LinkCache() # create new empty link cache + cache.refill(sock) # fill cache with all configured links + eth0 = cache['eth0'] # lookup link "eth0" + print eth0 # print basic configuration The module contains the following public classes: - Link -- Represents a network link. Instances can be created directly - via the constructor (empty link objects) or via the refill() - method of a LinkCache. + via the constructor (empty link objects) or via the refill() + method of a LinkCache. - LinkCache -- Derived from netlink.Cache, holds any number of - network links (Link instances). Main purpose is to keep - a local list of all network links configured in the - kernel. + network links (Link instances). Main purpose is to keep + a local list of all network links configured in the + kernel. The following public functions exist: - get_from_kernel(socket, name) @@ -38,9 +38,9 @@ from __future__ import absolute_import __version__ = "0.1" __all__ = [ - 'LinkCache', - 'Link', - 'get_from_kernel'] + 'LinkCache', + 'Link', + 'get_from_kernel'] import socket import sys @@ -113,477 +113,477 @@ ICMP6_OUTERRORS = 56 ########################################################################### # Link Cache class LinkCache(netlink.Cache): - """Cache of network links""" + """Cache of network links""" - def __init__(self, family=socket.AF_UNSPEC, cache=None): - if not cache: - cache = self._alloc_cache_name("route/link") + def __init__(self, family=socket.AF_UNSPEC, cache=None): + if not cache: + cache = self._alloc_cache_name("route/link") - self._info_module = None - self._protocol = netlink.NETLINK_ROUTE - self._nl_cache = cache - self._set_arg1(family) + self._info_module = None + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + self._set_arg1(family) - def __getitem__(self, key): - if type(key) is int: - link = capi.rtnl_link_get(self._nl_cache, key) - else: - link = capi.rtnl_link_get_by_name(self._nl_cache, key) + def __getitem__(self, key): + if type(key) is int: + link = capi.rtnl_link_get(self._nl_cache, key) + else: + link = capi.rtnl_link_get_by_name(self._nl_cache, key) - if link is None: - raise KeyError() - else: - return Link.from_capi(link) + if link is None: + raise KeyError() + else: + return Link.from_capi(link) - def _new_object(self, obj): - return Link(obj) + def _new_object(self, obj): + return Link(obj) - def _new_cache(self, cache): - return LinkCache(family=self.arg1, cache=cache) + def _new_cache(self, cache): + return LinkCache(family=self.arg1, cache=cache) ########################################################################### # Link Object class Link(netlink.Object): - """Network link""" - - def __init__(self, obj=None): - netlink.Object.__init__(self, "route/link", "link", obj) - self._rtnl_link = self._obj2type(self._nl_object) - - if self.type: - self._module_lookup('netlink.route.links.' + self.type) - - self.inet = inet.InetLink(self) - self.af = {'inet' : self.inet } - - @classmethod - def from_capi(cls, obj): - return cls(capi.link2obj(obj)) - - def _obj2type(self, obj): - return capi.obj2link(obj) - - def __cmp__(self, other): - return self.ifindex - other.ifindex - - def _new_instance(self, obj): - if not obj: - raise ValueError() - - return Link(obj) - - ##################################################################### - # ifindex - @netlink.nlattr('link.ifindex', type=int, immutable=True, fmt=util.num) - @property - def ifindex(self): - """interface index""" - return capi.rtnl_link_get_ifindex(self._rtnl_link) - - @ifindex.setter - def ifindex(self, value): - capi.rtnl_link_set_ifindex(self._rtnl_link, int(value)) - - # ifindex is immutable but we assume that if _orig does not - # have an ifindex specified, it was meant to be given here - if capi.rtnl_link_get_ifindex(self._orig) == 0: - capi.rtnl_link_set_ifindex(self._orig, int(value)) - - ##################################################################### - # name - @netlink.nlattr('link.name', type=str, fmt=util.bold) - @property - def name(self): - """Name of link""" - return capi.rtnl_link_get_name(self._rtnl_link) - - @name.setter - def name(self, value): - capi.rtnl_link_set_name(self._rtnl_link, value) - - # name is the secondary identifier, if _orig does not have - # the name specified yet, assume it was meant to be specified - # here. ifindex will always take priority, therefore if ifindex - # is specified as well, this will be ignored automatically. - if capi.rtnl_link_get_name(self._orig) is None: - capi.rtnl_link_set_name(self._orig, value) - - ##################################################################### - # flags - @netlink.nlattr('link.flags', type=str, fmt=util.string) - @property - def flags(self): - """Flags - Setting this property will *Not* reset flags to value you supply in - Examples: - link.flags = '+xxx' # add xxx flag - link.flags = 'xxx' # exactly the same - link.flags = '-xxx' # remove xxx flag - link.flags = [ '+xxx', '-yyy' ] # list operation - """ - flags = capi.rtnl_link_get_flags(self._rtnl_link) - return capi.rtnl_link_flags2str(flags, 256)[0].split(',') - - def _set_flag(self, flag): - if flag.startswith('-'): - i = capi.rtnl_link_str2flags(flag[1:]) - capi.rtnl_link_unset_flags(self._rtnl_link, i) - elif flag.startswith('+'): - i = capi.rtnl_link_str2flags(flag[1:]) - capi.rtnl_link_set_flags(self._rtnl_link, i) - else: - i = capi.rtnl_link_str2flags(flag) - capi.rtnl_link_set_flags(self._rtnl_link, i) - - @flags.setter - def flags(self, value): - if not (type(value) is str): - for flag in value: - self._set_flag(flag) - else: - self._set_flag(value) - - ##################################################################### - # mtu - @netlink.nlattr('link.mtu', type=int, fmt=util.num) - @property - def mtu(self): - """Maximum Transmission Unit""" - return capi.rtnl_link_get_mtu(self._rtnl_link) - - @mtu.setter - def mtu(self, value): - capi.rtnl_link_set_mtu(self._rtnl_link, int(value)) - - ##################################################################### - # family - @netlink.nlattr('link.family', type=int, immutable=True, fmt=util.num) - @property - def family(self): - """Address family""" - return capi.rtnl_link_get_family(self._rtnl_link) - - @family.setter - def family(self, value): - capi.rtnl_link_set_family(self._rtnl_link, value) - - ##################################################################### - # address - @netlink.nlattr('link.address', type=str, fmt=util.addr) - @property - def address(self): - """Hardware address (MAC address)""" - a = capi.rtnl_link_get_addr(self._rtnl_link) - return netlink.AbstractAddress(a) - - @address.setter - def address(self, value): - capi.rtnl_link_set_addr(self._rtnl_link, value._addr) - - ##################################################################### - # broadcast - @netlink.nlattr('link.broadcast', type=str, fmt=util.addr) - @property - def broadcast(self): - """Hardware broadcast address""" - a = capi.rtnl_link_get_broadcast(self._rtnl_link) - return netlink.AbstractAddress(a) - - @broadcast.setter - def broadcast(self, value): - capi.rtnl_link_set_broadcast(self._rtnl_link, value._addr) - - ##################################################################### - # qdisc - @netlink.nlattr('link.qdisc', type=str, immutable=True, fmt=util.string) - @property - def qdisc(self): - """Name of qdisc (cannot be changed)""" - return capi.rtnl_link_get_qdisc(self._rtnl_link) - - @qdisc.setter - def qdisc(self, value): - capi.rtnl_link_set_qdisc(self._rtnl_link, value) - - ##################################################################### - # txqlen - @netlink.nlattr('link.txqlen', type=int, fmt=util.num) - @property - def txqlen(self): - """Length of transmit queue""" - return capi.rtnl_link_get_txqlen(self._rtnl_link) - - @txqlen.setter - def txqlen(self, value): - capi.rtnl_link_set_txqlen(self._rtnl_link, int(value)) - - ##################################################################### - # weight - @netlink.nlattr('link.weight', type=str, fmt=util.string) - @property - def weight(self): - """Weight""" - v = capi.rtnl_link_get_weight(self._rtnl_link) - if v == 4294967295: - return 'max' - else: - return str(v) - - @weight.setter - def weight(self, value): - if value == 'max': - v = 4294967295 - else: - v = int(value) - capi.rtnl_link_set_weight(self._rtnl_link, v) - - ##################################################################### - # arptype - @netlink.nlattr('link.arptype', type=str, immutable=True, fmt=util.string) - @property - def arptype(self): - """Type of link (cannot be changed)""" - type = capi.rtnl_link_get_arptype(self._rtnl_link) - return core_capi.nl_llproto2str(type, 64)[0] - - @arptype.setter - def arptype(self, value): - i = core_capi.nl_str2llproto(value) - capi.rtnl_link_set_arptype(self._rtnl_link, i) - - ##################################################################### - # operstate - @netlink.nlattr('link.operstate', type=str, immutable=True, - fmt=util.string, title='state') - @property - def operstate(self): - """Operational status""" - operstate = capi.rtnl_link_get_operstate(self._rtnl_link) - return capi.rtnl_link_operstate2str(operstate, 32)[0] - - @operstate.setter - def operstate(self, value): - i = capi.rtnl_link_str2operstate(flag) - capi.rtnl_link_set_operstate(self._rtnl_link, i) - - ##################################################################### - # mode - @netlink.nlattr('link.mode', type=str, immutable=True, fmt=util.string) - @property - def mode(self): - """Link mode""" - mode = capi.rtnl_link_get_linkmode(self._rtnl_link) - return capi.rtnl_link_mode2str(mode, 32)[0] - - @mode.setter - def mode(self, value): - i = capi.rtnl_link_str2mode(flag) - capi.rtnl_link_set_linkmode(self._rtnl_link, i) - - ##################################################################### - # alias - @netlink.nlattr('link.alias', type=str, fmt=util.string) - @property - def alias(self): - """Interface alias (SNMP)""" - return capi.rtnl_link_get_ifalias(self._rtnl_link) - - @alias.setter - def alias(self, value): - capi.rtnl_link_set_ifalias(self._rtnl_link, value) - - ##################################################################### - # type - @netlink.nlattr('link.type', type=str, fmt=util.string) - @property - def type(self): - """Link type""" - return capi.rtnl_link_get_type(self._rtnl_link) - - @type.setter - def type(self, value): - if capi.rtnl_link_set_type(self._rtnl_link, value) < 0: - raise NameError("unknown info type") - - self._module_lookup('netlink.route.links.' + value) - - ##################################################################### - # get_stat() - def get_stat(self, stat): - """Retrieve statistical information""" - if type(stat) is str: - stat = capi.rtnl_link_str2stat(stat) - if stat < 0: - raise NameError("unknown name of statistic") - - return capi.rtnl_link_get_stat(self._rtnl_link, stat) - - ##################################################################### - # add() - def add(self, socket=None, flags=None): - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) - - if not flags: - flags = netlink.NLM_F_CREATE - - ret = capi.rtnl_link_add(socket._sock, self._rtnl_link, flags) - if ret < 0: - raise netlink.KernelError(ret) - - ##################################################################### - # change() - def change(self, socket=None, flags=0): - """Commit changes made to the link object""" - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) - - if not self._orig: - raise NetlinkError("Original link not available") - ret = capi.rtnl_link_change(socket._sock, self._orig, self._rtnl_link, flags) - if ret < 0: - raise netlink.KernelError(ret) - - ##################################################################### - # delete() - def delete(self, socket=None): - """Attempt to delete this link in the kernel""" - if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) - - ret = capi.rtnl_link_delete(socket._sock, self._rtnl_link) - if ret < 0: - raise netlink.KernelError(ret) - - ################################################################### - # private properties - # - # Used for formatting output. USE AT OWN RISK - @property - def _state(self): - if 'up' in self.flags: - buf = util.good('up') - if 'lowerup' not in self.flags: - buf += ' ' + util.bad('no-carrier') - else: - buf = util.bad('down') - return buf - - @property - def _brief(self): - return self._module_brief() + self._foreach_af('brief') - - @property - def _flags(self): - ignore = ['up', 'running', 'lowerup'] - return ','.join([flag for flag in self.flags if flag not in ignore]) - - def _foreach_af(self, name, args=None): - buf = '' - for af in self.af: - try: - func = getattr(self.af[af], name) - s = str(func(args)) - if len(s) > 0: - buf += ' ' + s - except AttributeError: - pass - return buf - - ################################################################### - # - # format(details=False, stats=False) - # - def format(self, details=False, stats=False, indent=''): - """Return link as formatted text""" - fmt = util.MyFormatter(self, indent) - - buf = fmt.format('{a|ifindex} {a|name} {a|arptype} {a|address} '\ - '{a|_state} <{a|_flags}> {a|_brief}') - - if details: - buf += fmt.nl('\t{t|mtu} {t|txqlen} {t|weight} '\ - '{t|qdisc} {t|operstate}') - buf += fmt.nl('\t{t|broadcast} {t|alias}') - - buf += self._foreach_af('details', fmt) - - if stats: - l = [['Packets', RX_PACKETS, TX_PACKETS], - ['Bytes', RX_BYTES, TX_BYTES], - ['Errors', RX_ERRORS, TX_ERRORS], - ['Dropped', RX_DROPPED, TX_DROPPED], - ['Compressed', RX_COMPRESSED, TX_COMPRESSED], - ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], - ['Length Errors', RX_LEN_ERR, None], - ['Over Errors', RX_OVER_ERR, None], - ['CRC Errors', RX_CRC_ERR, None], - ['Frame Errors', RX_FRAME_ERR, None], - ['Missed Errors', RX_MISSED_ERR, None], - ['Abort Errors', None, TX_ABORT_ERR], - ['Carrier Errors', None, TX_CARRIER_ERR], - ['Heartbeat Errors', None, TX_HBEAT_ERR], - ['Window Errors', None, TX_WIN_ERR], - ['Collisions', None, COLLISIONS], - ['Multicast', None, MULTICAST], - ['', None, None], - ['Ipv6:', None, None], - ['Packets', IP6_INPKTS, IP6_OUTPKTS], - ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], - ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], - ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], - ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], - ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], - ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], - ['Delivers', IP6_INDELIVERS, None], - ['Forwarded', None, IP6_OUTFORWDATAGRAMS], - ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], - ['Header Errors', IP6_INHDRERRORS, None], - ['Too Big Errors', IP6_INTOOBIGERRORS, None], - ['Address Errors', IP6_INADDRERRORS, None], - ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], - ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], - ['Reasm Timeouts', IP6_REASMTIMEOUT, None], - ['Reasm Requests', IP6_REASMREQDS, None], - ['Reasm Failures', IP6_REASMFAILS, None], - ['Reasm OK', IP6_REASMOKS, None], - ['Frag Created', None, IP6_FRAGCREATES], - ['Frag Failures', None, IP6_FRAGFAILS], - ['Frag OK', None, IP6_FRAGOKS], - ['', None, None], - ['ICMPv6:', None, None], - ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], - ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] - - buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), - 15 * ' ', util.title('TX')) - - for row in l: - row[0] = util.kw(row[0]) - row[1] = self.get_stat(row[1]) if row[1] else '' - row[2] = self.get_stat(row[2]) if row[2] else '' - buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) - - buf += self._foreach_af('stats') - - return buf + """Network link""" + + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/link", "link", obj) + self._rtnl_link = self._obj2type(self._nl_object) + + if self.type: + self._module_lookup('netlink.route.links.' + self.type) + + self.inet = inet.InetLink(self) + self.af = {'inet' : self.inet } + + @classmethod + def from_capi(cls, obj): + return cls(capi.link2obj(obj)) + + def _obj2type(self, obj): + return capi.obj2link(obj) + + def __cmp__(self, other): + return self.ifindex - other.ifindex + + def _new_instance(self, obj): + if not obj: + raise ValueError() + + return Link(obj) + + ##################################################################### + # ifindex + @netlink.nlattr('link.ifindex', type=int, immutable=True, fmt=util.num) + @property + def ifindex(self): + """interface index""" + return capi.rtnl_link_get_ifindex(self._rtnl_link) + + @ifindex.setter + def ifindex(self, value): + capi.rtnl_link_set_ifindex(self._rtnl_link, int(value)) + + # ifindex is immutable but we assume that if _orig does not + # have an ifindex specified, it was meant to be given here + if capi.rtnl_link_get_ifindex(self._orig) == 0: + capi.rtnl_link_set_ifindex(self._orig, int(value)) + + ##################################################################### + # name + @netlink.nlattr('link.name', type=str, fmt=util.bold) + @property + def name(self): + """Name of link""" + return capi.rtnl_link_get_name(self._rtnl_link) + + @name.setter + def name(self, value): + capi.rtnl_link_set_name(self._rtnl_link, value) + + # name is the secondary identifier, if _orig does not have + # the name specified yet, assume it was meant to be specified + # here. ifindex will always take priority, therefore if ifindex + # is specified as well, this will be ignored automatically. + if capi.rtnl_link_get_name(self._orig) is None: + capi.rtnl_link_set_name(self._orig, value) + + ##################################################################### + # flags + @netlink.nlattr('link.flags', type=str, fmt=util.string) + @property + def flags(self): + """Flags + Setting this property will *Not* reset flags to value you supply in + Examples: + link.flags = '+xxx' # add xxx flag + link.flags = 'xxx' # exactly the same + link.flags = '-xxx' # remove xxx flag + link.flags = [ '+xxx', '-yyy' ] # list operation + """ + flags = capi.rtnl_link_get_flags(self._rtnl_link) + return capi.rtnl_link_flags2str(flags, 256)[0].split(',') + + def _set_flag(self, flag): + if flag.startswith('-'): + i = capi.rtnl_link_str2flags(flag[1:]) + capi.rtnl_link_unset_flags(self._rtnl_link, i) + elif flag.startswith('+'): + i = capi.rtnl_link_str2flags(flag[1:]) + capi.rtnl_link_set_flags(self._rtnl_link, i) + else: + i = capi.rtnl_link_str2flags(flag) + capi.rtnl_link_set_flags(self._rtnl_link, i) + + @flags.setter + def flags(self, value): + if not (type(value) is str): + for flag in value: + self._set_flag(flag) + else: + self._set_flag(value) + + ##################################################################### + # mtu + @netlink.nlattr('link.mtu', type=int, fmt=util.num) + @property + def mtu(self): + """Maximum Transmission Unit""" + return capi.rtnl_link_get_mtu(self._rtnl_link) + + @mtu.setter + def mtu(self, value): + capi.rtnl_link_set_mtu(self._rtnl_link, int(value)) + + ##################################################################### + # family + @netlink.nlattr('link.family', type=int, immutable=True, fmt=util.num) + @property + def family(self): + """Address family""" + return capi.rtnl_link_get_family(self._rtnl_link) + + @family.setter + def family(self, value): + capi.rtnl_link_set_family(self._rtnl_link, value) + + ##################################################################### + # address + @netlink.nlattr('link.address', type=str, fmt=util.addr) + @property + def address(self): + """Hardware address (MAC address)""" + a = capi.rtnl_link_get_addr(self._rtnl_link) + return netlink.AbstractAddress(a) + + @address.setter + def address(self, value): + capi.rtnl_link_set_addr(self._rtnl_link, value._addr) + + ##################################################################### + # broadcast + @netlink.nlattr('link.broadcast', type=str, fmt=util.addr) + @property + def broadcast(self): + """Hardware broadcast address""" + a = capi.rtnl_link_get_broadcast(self._rtnl_link) + return netlink.AbstractAddress(a) + + @broadcast.setter + def broadcast(self, value): + capi.rtnl_link_set_broadcast(self._rtnl_link, value._addr) + + ##################################################################### + # qdisc + @netlink.nlattr('link.qdisc', type=str, immutable=True, fmt=util.string) + @property + def qdisc(self): + """Name of qdisc (cannot be changed)""" + return capi.rtnl_link_get_qdisc(self._rtnl_link) + + @qdisc.setter + def qdisc(self, value): + capi.rtnl_link_set_qdisc(self._rtnl_link, value) + + ##################################################################### + # txqlen + @netlink.nlattr('link.txqlen', type=int, fmt=util.num) + @property + def txqlen(self): + """Length of transmit queue""" + return capi.rtnl_link_get_txqlen(self._rtnl_link) + + @txqlen.setter + def txqlen(self, value): + capi.rtnl_link_set_txqlen(self._rtnl_link, int(value)) + + ##################################################################### + # weight + @netlink.nlattr('link.weight', type=str, fmt=util.string) + @property + def weight(self): + """Weight""" + v = capi.rtnl_link_get_weight(self._rtnl_link) + if v == 4294967295: + return 'max' + else: + return str(v) + + @weight.setter + def weight(self, value): + if value == 'max': + v = 4294967295 + else: + v = int(value) + capi.rtnl_link_set_weight(self._rtnl_link, v) + + ##################################################################### + # arptype + @netlink.nlattr('link.arptype', type=str, immutable=True, fmt=util.string) + @property + def arptype(self): + """Type of link (cannot be changed)""" + type = capi.rtnl_link_get_arptype(self._rtnl_link) + return core_capi.nl_llproto2str(type, 64)[0] + + @arptype.setter + def arptype(self, value): + i = core_capi.nl_str2llproto(value) + capi.rtnl_link_set_arptype(self._rtnl_link, i) + + ##################################################################### + # operstate + @netlink.nlattr('link.operstate', type=str, immutable=True, + fmt=util.string, title='state') + @property + def operstate(self): + """Operational status""" + operstate = capi.rtnl_link_get_operstate(self._rtnl_link) + return capi.rtnl_link_operstate2str(operstate, 32)[0] + + @operstate.setter + def operstate(self, value): + i = capi.rtnl_link_str2operstate(flag) + capi.rtnl_link_set_operstate(self._rtnl_link, i) + + ##################################################################### + # mode + @netlink.nlattr('link.mode', type=str, immutable=True, fmt=util.string) + @property + def mode(self): + """Link mode""" + mode = capi.rtnl_link_get_linkmode(self._rtnl_link) + return capi.rtnl_link_mode2str(mode, 32)[0] + + @mode.setter + def mode(self, value): + i = capi.rtnl_link_str2mode(flag) + capi.rtnl_link_set_linkmode(self._rtnl_link, i) + + ##################################################################### + # alias + @netlink.nlattr('link.alias', type=str, fmt=util.string) + @property + def alias(self): + """Interface alias (SNMP)""" + return capi.rtnl_link_get_ifalias(self._rtnl_link) + + @alias.setter + def alias(self, value): + capi.rtnl_link_set_ifalias(self._rtnl_link, value) + + ##################################################################### + # type + @netlink.nlattr('link.type', type=str, fmt=util.string) + @property + def type(self): + """Link type""" + return capi.rtnl_link_get_type(self._rtnl_link) + + @type.setter + def type(self, value): + if capi.rtnl_link_set_type(self._rtnl_link, value) < 0: + raise NameError("unknown info type") + + self._module_lookup('netlink.route.links.' + value) + + ##################################################################### + # get_stat() + def get_stat(self, stat): + """Retrieve statistical information""" + if type(stat) is str: + stat = capi.rtnl_link_str2stat(stat) + if stat < 0: + raise NameError("unknown name of statistic") + + return capi.rtnl_link_get_stat(self._rtnl_link, stat) + + ##################################################################### + # add() + def add(self, socket=None, flags=None): + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) -def get(name, socket=None): - """Lookup Link object directly from kernel""" - if not name: - raise ValueError() + if not flags: + flags = netlink.NLM_F_CREATE + ret = capi.rtnl_link_add(socket._sock, self._rtnl_link, flags) + if ret < 0: + raise netlink.KernelError(ret) + + ##################################################################### + # change() + def change(self, socket=None, flags=0): + """Commit changes made to the link object""" + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + if not self._orig: + raise NetlinkError("Original link not available") + ret = capi.rtnl_link_change(socket._sock, self._orig, self._rtnl_link, flags) + if ret < 0: + raise netlink.KernelError(ret) + + ##################################################################### + # delete() + def delete(self, socket=None): + """Attempt to delete this link in the kernel""" if not socket: - socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + ret = capi.rtnl_link_delete(socket._sock, self._rtnl_link) + if ret < 0: + raise netlink.KernelError(ret) + + ################################################################### + # private properties + # + # Used for formatting output. USE AT OWN RISK + @property + def _state(self): + if 'up' in self.flags: + buf = util.good('up') + if 'lowerup' not in self.flags: + buf += ' ' + util.bad('no-carrier') + else: + buf = util.bad('down') + return buf + + @property + def _brief(self): + return self._module_brief() + self._foreach_af('brief') + + @property + def _flags(self): + ignore = ['up', 'running', 'lowerup'] + return ','.join([flag for flag in self.flags if flag not in ignore]) + + def _foreach_af(self, name, args=None): + buf = '' + for af in self.af: + try: + func = getattr(self.af[af], name) + s = str(func(args)) + if len(s) > 0: + buf += ' ' + s + except AttributeError: + pass + return buf + + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, indent=''): + """Return link as formatted text""" + fmt = util.MyFormatter(self, indent) + + buf = fmt.format('{a|ifindex} {a|name} {a|arptype} {a|address} '\ + '{a|_state} <{a|_flags}> {a|_brief}') + + if details: + buf += fmt.nl('\t{t|mtu} {t|txqlen} {t|weight} '\ + '{t|qdisc} {t|operstate}') + buf += fmt.nl('\t{t|broadcast} {t|alias}') + + buf += self._foreach_af('details', fmt) + + if stats: + l = [['Packets', RX_PACKETS, TX_PACKETS], + ['Bytes', RX_BYTES, TX_BYTES], + ['Errors', RX_ERRORS, TX_ERRORS], + ['Dropped', RX_DROPPED, TX_DROPPED], + ['Compressed', RX_COMPRESSED, TX_COMPRESSED], + ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], + ['Length Errors', RX_LEN_ERR, None], + ['Over Errors', RX_OVER_ERR, None], + ['CRC Errors', RX_CRC_ERR, None], + ['Frame Errors', RX_FRAME_ERR, None], + ['Missed Errors', RX_MISSED_ERR, None], + ['Abort Errors', None, TX_ABORT_ERR], + ['Carrier Errors', None, TX_CARRIER_ERR], + ['Heartbeat Errors', None, TX_HBEAT_ERR], + ['Window Errors', None, TX_WIN_ERR], + ['Collisions', None, COLLISIONS], + ['Multicast', None, MULTICAST], + ['', None, None], + ['Ipv6:', None, None], + ['Packets', IP6_INPKTS, IP6_OUTPKTS], + ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], + ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], + ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], + ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], + ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], + ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], + ['Delivers', IP6_INDELIVERS, None], + ['Forwarded', None, IP6_OUTFORWDATAGRAMS], + ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], + ['Header Errors', IP6_INHDRERRORS, None], + ['Too Big Errors', IP6_INTOOBIGERRORS, None], + ['Address Errors', IP6_INADDRERRORS, None], + ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], + ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], + ['Reasm Timeouts', IP6_REASMTIMEOUT, None], + ['Reasm Requests', IP6_REASMREQDS, None], + ['Reasm Failures', IP6_REASMFAILS, None], + ['Reasm OK', IP6_REASMOKS, None], + ['Frag Created', None, IP6_FRAGCREATES], + ['Frag Failures', None, IP6_FRAGFAILS], + ['Frag OK', None, IP6_FRAGOKS], + ['', None, None], + ['ICMPv6:', None, None], + ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], + ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] + + buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), + 15 * ' ', util.title('TX')) + + for row in l: + row[0] = util.kw(row[0]) + row[1] = self.get_stat(row[1]) if row[1] else '' + row[2] = self.get_stat(row[2]) if row[2] else '' + buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) + + buf += self._foreach_af('stats') + + return buf + +def get(name, socket=None): + """Lookup Link object directly from kernel""" + if not name: + raise ValueError() + + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) - link = capi.get_from_kernel(socket._sock, 0, name) - if not link: - return None + link = capi.get_from_kernel(socket._sock, 0, name) + if not link: + return None - return Link.from_capi(link) + return Link.from_capi(link) _link_cache = LinkCache() def resolve(name): - _link_cache.refill() - return _link_cache[name] + _link_cache.refill() + return _link_cache[name] diff --git a/python/netlink/route/links/dummy.py b/python/netlink/route/links/dummy.py index caf3ba7e..13b30775 100644 --- a/python/netlink/route/links/dummy.py +++ b/python/netlink/route/links/dummy.py @@ -14,12 +14,12 @@ __all__ = ['init'] from ... import core as netlink from .. import capi as capi class DummyLink(object): - def __init__(self, link): - self._rtnl_link = link + def __init__(self, link): + self._rtnl_link = link - def brief(self): - return 'dummy' + def brief(self): + return 'dummy' def init(link): - link.dummy = DummyLink(link._rtnl_link) - return link.dummy + link.dummy = DummyLink(link._rtnl_link) + return link.dummy diff --git a/python/netlink/route/links/inet.py b/python/netlink/route/links/inet.py index b5b11522..1a133490 100644 --- a/python/netlink/route/links/inet.py +++ b/python/netlink/route/links/inet.py @@ -41,98 +41,98 @@ DEVCONF_PROXY_ARP_PVLAN = 25 DEVCONF_MAX = DEVCONF_PROXY_ARP_PVLAN def _resolve(id): - if type(id) is str: - id = capi.rtnl_link_inet_str2devconf(id)[0] - if id < 0: - raise NameError("unknown configuration id") - return id + if type(id) is str: + id = capi.rtnl_link_inet_str2devconf(id)[0] + if id < 0: + raise NameError("unknown configuration id") + return id class InetLink(object): - def __init__(self, link): - self._link = link - - def details(self, fmt): - buf = fmt.nl('\n\t{0}\n\t'.format(util.title('Configuration:'))) - - for i in range(DEVCONF_FORWARDING,DEVCONF_MAX+1): - if i & 1 and i > 1: - buf += fmt.nl('\t') - txt = util.kw(capi.rtnl_link_inet_devconf2str(i, 32)[0]) - buf += fmt.format('{0:28s} {1:12} ', txt, - self.get_conf(i)) - - - return buf - - def get_conf(self, id): - return capi.inet_get_conf(self._link._rtnl_link, _resolve(id)) - - def set_conf(self, id, value): - return capi.rtnl_link_inet_set_conf(self._link._rtnl_link, - _resolve(id), int(value)) - - @netlink.nlattr('link.inet.forwarding', type=bool, fmt=util.bool) - @property - def forwarding(self): - return bool(self.get_conf(DEVCONF_FORWARDING)) - - @forwarding.setter - def forwarding(self, value): - self.set_conf(DEVCONF_FORWARDING, int(value)) - - @netlink.nlattr('link.inet.mc_forwarding', type=bool, fmt=util.bool) - @property - def mc_forwarding(self): - return bool(self.get_conf(DEVCONF_MC_FORWARDING)) - - @mc_forwarding.setter - def mc_forwarding(self, value): - self.set_conf(DEVCONF_MC_FORWARDING, int(value)) - - @netlink.nlattr('link.inet.proxy_arp', type=bool, fmt=util.bool) - @property - def proxy_arp(self): - return bool(self.get_conf(DEVCONF_PROXY_ARP)) - - @proxy_arp.setter - def proxy_arp(self, value): - self.set_conf(DEVCONF_PROXY_ARP, int(value)) - - @netlink.nlattr('link.inet.accept_redirects', type=bool, fmt=util.bool) - @property - def accept_redirects(self): - return bool(self.get_conf(DEVCONF_ACCEPT_REDIRECTS)) - - @accept_redirects.setter - def accept_redirects(self, value): - self.set_conf(DEVCONF_ACCEPT_REDIRECTS, int(value)) - - @netlink.nlattr('link.inet.secure_redirects', type=bool, fmt=util.bool) - @property - def secure_redirects(self): - return bool(self.get_conf(DEVCONF_SECURE_REDIRECTS)) - - @secure_redirects.setter - def secure_redirects(self, value): - self.set_conf(DEVCONF_SECURE_REDIRECTS, int(value)) - - @netlink.nlattr('link.inet.send_redirects', type=bool, fmt=util.bool) - @property - def send_redirects(self): - return bool(self.get_conf(DEVCONF_SEND_REDIRECTS)) - - @send_redirects.setter - def send_redirects(self, value): - self.set_conf(DEVCONF_SEND_REDIRECTS, int(value)) - - @netlink.nlattr('link.inet.shared_media', type=bool, fmt=util.bool) - @property - def shared_media(self): - return bool(self.get_conf(DEVCONF_SHARED_MEDIA)) - - @shared_media.setter - def shared_media(self, value): - self.set_conf(DEVCONF_SHARED_MEDIA, int(value)) + def __init__(self, link): + self._link = link + + def details(self, fmt): + buf = fmt.nl('\n\t{0}\n\t'.format(util.title('Configuration:'))) + + for i in range(DEVCONF_FORWARDING,DEVCONF_MAX+1): + if i & 1 and i > 1: + buf += fmt.nl('\t') + txt = util.kw(capi.rtnl_link_inet_devconf2str(i, 32)[0]) + buf += fmt.format('{0:28s} {1:12} ', txt, + self.get_conf(i)) + + + return buf + + def get_conf(self, id): + return capi.inet_get_conf(self._link._rtnl_link, _resolve(id)) + + def set_conf(self, id, value): + return capi.rtnl_link_inet_set_conf(self._link._rtnl_link, + _resolve(id), int(value)) + + @netlink.nlattr('link.inet.forwarding', type=bool, fmt=util.bool) + @property + def forwarding(self): + return bool(self.get_conf(DEVCONF_FORWARDING)) + + @forwarding.setter + def forwarding(self, value): + self.set_conf(DEVCONF_FORWARDING, int(value)) + + @netlink.nlattr('link.inet.mc_forwarding', type=bool, fmt=util.bool) + @property + def mc_forwarding(self): + return bool(self.get_conf(DEVCONF_MC_FORWARDING)) + + @mc_forwarding.setter + def mc_forwarding(self, value): + self.set_conf(DEVCONF_MC_FORWARDING, int(value)) + + @netlink.nlattr('link.inet.proxy_arp', type=bool, fmt=util.bool) + @property + def proxy_arp(self): + return bool(self.get_conf(DEVCONF_PROXY_ARP)) + + @proxy_arp.setter + def proxy_arp(self, value): + self.set_conf(DEVCONF_PROXY_ARP, int(value)) + + @netlink.nlattr('link.inet.accept_redirects', type=bool, fmt=util.bool) + @property + def accept_redirects(self): + return bool(self.get_conf(DEVCONF_ACCEPT_REDIRECTS)) + + @accept_redirects.setter + def accept_redirects(self, value): + self.set_conf(DEVCONF_ACCEPT_REDIRECTS, int(value)) + + @netlink.nlattr('link.inet.secure_redirects', type=bool, fmt=util.bool) + @property + def secure_redirects(self): + return bool(self.get_conf(DEVCONF_SECURE_REDIRECTS)) + + @secure_redirects.setter + def secure_redirects(self, value): + self.set_conf(DEVCONF_SECURE_REDIRECTS, int(value)) + + @netlink.nlattr('link.inet.send_redirects', type=bool, fmt=util.bool) + @property + def send_redirects(self): + return bool(self.get_conf(DEVCONF_SEND_REDIRECTS)) + + @send_redirects.setter + def send_redirects(self, value): + self.set_conf(DEVCONF_SEND_REDIRECTS, int(value)) + + @netlink.nlattr('link.inet.shared_media', type=bool, fmt=util.bool) + @property + def shared_media(self): + return bool(self.get_conf(DEVCONF_SHARED_MEDIA)) + + @shared_media.setter + def shared_media(self, value): + self.set_conf(DEVCONF_SHARED_MEDIA, int(value)) # IPV4_DEVCONF_RP_FILTER, # IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, diff --git a/python/netlink/route/links/vlan.py b/python/netlink/route/links/vlan.py index bb339d08..d13a8c68 100644 --- a/python/netlink/route/links/vlan.py +++ b/python/netlink/route/links/vlan.py @@ -12,64 +12,64 @@ from __future__ import absolute_import from ... import core as netlink from .. import capi as capi class VLANLink(object): - def __init__(self, link): - self._link = link + def __init__(self, link): + self._link = link - ################################################################### - # id - @netlink.nlattr('link.vlan.id', type=int) - @property - def id(self): - """vlan identifier""" - return capi.rtnl_link_vlan_get_id(self._link) + ################################################################### + # id + @netlink.nlattr('link.vlan.id', type=int) + @property + def id(self): + """vlan identifier""" + return capi.rtnl_link_vlan_get_id(self._link) - @id.setter - def id(self, value): - capi.rtnl_link_vlan_set_id(self._link, int(value)) + @id.setter + def id(self, value): + capi.rtnl_link_vlan_set_id(self._link, int(value)) - ################################################################### - # flags - @netlink.nlattr('link.vlan.flags', type=str) - @property - def flags(self): - """ VLAN flags - Setting this property will *Not* reset flags to value you supply in - Examples: - link.flags = '+xxx' # add xxx flag - link.flags = 'xxx' # exactly the same - link.flags = '-xxx' # remove xxx flag - link.flags = [ '+xxx', '-yyy' ] # list operation - """ - flags = capi.rtnl_link_vlan_get_flags(self._link) - return capi.rtnl_link_vlan_flags2str(flags, 256)[0].split(',') + ################################################################### + # flags + @netlink.nlattr('link.vlan.flags', type=str) + @property + def flags(self): + """ VLAN flags + Setting this property will *Not* reset flags to value you supply in + Examples: + link.flags = '+xxx' # add xxx flag + link.flags = 'xxx' # exactly the same + link.flags = '-xxx' # remove xxx flag + link.flags = [ '+xxx', '-yyy' ] # list operation + """ + flags = capi.rtnl_link_vlan_get_flags(self._link) + return capi.rtnl_link_vlan_flags2str(flags, 256)[0].split(',') - def _set_flag(self, flag): - if flag.startswith('-'): - i = capi.rtnl_link_vlan_str2flags(flag[1:]) - capi.rtnl_link_vlan_unset_flags(self._link, i) - elif flag.startswith('+'): - i = capi.rtnl_link_vlan_str2flags(flag[1:]) - capi.rtnl_link_vlan_set_flags(self._link, i) - else: - i = capi.rtnl_link_vlan_str2flags(flag) - capi.rtnl_link_vlan_set_flags(self._link, i) + def _set_flag(self, flag): + if flag.startswith('-'): + i = capi.rtnl_link_vlan_str2flags(flag[1:]) + capi.rtnl_link_vlan_unset_flags(self._link, i) + elif flag.startswith('+'): + i = capi.rtnl_link_vlan_str2flags(flag[1:]) + capi.rtnl_link_vlan_set_flags(self._link, i) + else: + i = capi.rtnl_link_vlan_str2flags(flag) + capi.rtnl_link_vlan_set_flags(self._link, i) - @flags.setter - def flags(self, value): - if type(value) is list: - for flag in value: - self._set_flag(flag) - else: - self._set_flag(value) + @flags.setter + def flags(self, value): + if type(value) is list: + for flag in value: + self._set_flag(flag) + else: + self._set_flag(value) - ################################################################### - # TODO: - # - ingress map - # - egress map + ################################################################### + # TODO: + # - ingress map + # - egress map - def brief(self): - return 'vlan-id {0}'.format(self.id) + def brief(self): + return 'vlan-id {0}'.format(self.id) def init(link): - link.vlan = VLANLink(link._link) - return link.vlan + link.vlan = VLANLink(link._link) + return link.vlan diff --git a/python/netlink/route/qdisc/htb.py b/python/netlink/route/qdisc/htb.py index 23c7f751..799ce480 100644 --- a/python/netlink/route/qdisc/htb.py +++ b/python/netlink/route/qdisc/htb.py @@ -14,150 +14,150 @@ from .. import capi as capi from .. import tc as tc class HTBQdisc(object): - def __init__(self, qdisc): - self._qdisc = qdisc + def __init__(self, qdisc): + self._qdisc = qdisc - ################################################################### - # default class - @netlink.nlattr('qdisc.htb.default_class', type=int) - @property - def default_class(self): - return tc.Handle(capi.rtnl_htb_get_defcls(self._qdisc._rtnl_qdisc)) + ################################################################### + # default class + @netlink.nlattr('qdisc.htb.default_class', type=int) + @property + def default_class(self): + return tc.Handle(capi.rtnl_htb_get_defcls(self._qdisc._rtnl_qdisc)) - @default_class.setter - def default_class(self, value): - capi.rtnl_htb_set_defcls(self._qdisc._rtnl_qdisc, int(value)) + @default_class.setter + def default_class(self, value): + capi.rtnl_htb_set_defcls(self._qdisc._rtnl_qdisc, int(value)) - ##################################################################### - # r2q - @netlink.nlattr('qdisc.htb.r2q', type=int) - @property - def r2q(self): - return capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc) + ##################################################################### + # r2q + @netlink.nlattr('qdisc.htb.r2q', type=int) + @property + def r2q(self): + return capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc) - @r2q.setter - def r2q(self, value): - capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc, - int(value)) + @r2q.setter + def r2q(self, value): + capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc, + int(value)) - def brief(self): - fmt = util.MyFormatter(self) + def brief(self): + fmt = util.MyFormatter(self) - ret = ' {s|default-class!k} {a|default_class}' + ret = ' {s|default-class!k} {a|default_class}' - if self.r2q: - ret += ' {s|r2q!k} {a|r2q}' + if self.r2q: + ret += ' {s|r2q!k} {a|r2q}' - return fmt.format(ret) + return fmt.format(ret) class HTBClass(object): - def __init__(self, cl): - self._class = cl - - ##################################################################### - # rate - @netlink.nlattr('class.htb.rate', type=str) - @property - def rate(self): - rate = capi.rtnl_htb_get_rate(self._class._rtnl_class) - return util.Rate(rate) - - @rate.setter - def rate(self, value): - capi.rtnl_htb_set_rate(self._class._rtnl_class, int(value)) - - ##################################################################### - # ceil - @netlink.nlattr('class.htb.ceil', type=str) - @property - def ceil(self): - ceil = capi.rtnl_htb_get_ceil(self._class._rtnl_class) - return util.Rate(ceil) - - @ceil.setter - def ceil(self, value): - capi.rtnl_htb_set_ceil(self._class._rtnl_class, int(value)) - - ##################################################################### - # burst - @netlink.nlattr('class.htb.burst', type=str) - @property - def burst(self): - burst = capi.rtnl_htb_get_rbuffer(self._class._rtnl_class) - return util.Size(burst) - - @burst.setter - def burst(self, value): - capi.rtnl_htb_set_rbuffer(self._class._rtnl_class, int(value)) - - ##################################################################### - # ceil burst - @netlink.nlattr('class.htb.ceil_burst', type=str) - @property - def ceil_burst(self): - burst = capi.rtnl_htb_get_cbuffer(self._class._rtnl_class) - return util.Size(burst) - - @ceil_burst.setter - def ceil_burst(self, value): - capi.rtnl_htb_set_cbuffer(self._class._rtnl_class, int(value)) - - ##################################################################### - # priority - @netlink.nlattr('class.htb.prio', type=int) - @property - def prio(self): - return capi.rtnl_htb_get_prio(self._class._rtnl_class) - - @prio.setter - def prio(self, value): - capi.rtnl_htb_set_prio(self._class._rtnl_class, int(value)) - - ##################################################################### - # quantum - @netlink.nlattr('class.htb.quantum', type=int) - @property - def quantum(self): - return capi.rtnl_htb_get_quantum(self._class._rtnl_class) - - @quantum.setter - def quantum(self, value): - capi.rtnl_htb_set_quantum(self._class._rtnl_class, int(value)) - - ##################################################################### - # level - @netlink.nlattr('class.htb.level', type=int) - @property - def level(self): - level = capi.rtnl_htb_get_level(self._class._rtnl_class) - - @level.setter - def level(self, value): - capi.rtnl_htb_set_level(self._class._rtnl_class, int(value)) - - def brief(self): - fmt = util.MyFormatter(self) - - ret = ' {t|prio} {t|rate}' - - if self.rate != self.ceil: - ret += ' {s|borrow-up-to!k} {a|ceil}' - - ret += ' {t|burst}' - - return fmt.format(ret) - - def details(self): - fmt = util.MyFormatter(self) - - return fmt.nl('\t{t|level} {t|quantum}') + def __init__(self, cl): + self._class = cl + + ##################################################################### + # rate + @netlink.nlattr('class.htb.rate', type=str) + @property + def rate(self): + rate = capi.rtnl_htb_get_rate(self._class._rtnl_class) + return util.Rate(rate) + + @rate.setter + def rate(self, value): + capi.rtnl_htb_set_rate(self._class._rtnl_class, int(value)) + + ##################################################################### + # ceil + @netlink.nlattr('class.htb.ceil', type=str) + @property + def ceil(self): + ceil = capi.rtnl_htb_get_ceil(self._class._rtnl_class) + return util.Rate(ceil) + + @ceil.setter + def ceil(self, value): + capi.rtnl_htb_set_ceil(self._class._rtnl_class, int(value)) + + ##################################################################### + # burst + @netlink.nlattr('class.htb.burst', type=str) + @property + def burst(self): + burst = capi.rtnl_htb_get_rbuffer(self._class._rtnl_class) + return util.Size(burst) + + @burst.setter + def burst(self, value): + capi.rtnl_htb_set_rbuffer(self._class._rtnl_class, int(value)) + + ##################################################################### + # ceil burst + @netlink.nlattr('class.htb.ceil_burst', type=str) + @property + def ceil_burst(self): + burst = capi.rtnl_htb_get_cbuffer(self._class._rtnl_class) + return util.Size(burst) + + @ceil_burst.setter + def ceil_burst(self, value): + capi.rtnl_htb_set_cbuffer(self._class._rtnl_class, int(value)) + + ##################################################################### + # priority + @netlink.nlattr('class.htb.prio', type=int) + @property + def prio(self): + return capi.rtnl_htb_get_prio(self._class._rtnl_class) + + @prio.setter + def prio(self, value): + capi.rtnl_htb_set_prio(self._class._rtnl_class, int(value)) + + ##################################################################### + # quantum + @netlink.nlattr('class.htb.quantum', type=int) + @property + def quantum(self): + return capi.rtnl_htb_get_quantum(self._class._rtnl_class) + + @quantum.setter + def quantum(self, value): + capi.rtnl_htb_set_quantum(self._class._rtnl_class, int(value)) + + ##################################################################### + # level + @netlink.nlattr('class.htb.level', type=int) + @property + def level(self): + level = capi.rtnl_htb_get_level(self._class._rtnl_class) + + @level.setter + def level(self, value): + capi.rtnl_htb_set_level(self._class._rtnl_class, int(value)) + + def brief(self): + fmt = util.MyFormatter(self) + + ret = ' {t|prio} {t|rate}' + + if self.rate != self.ceil: + ret += ' {s|borrow-up-to!k} {a|ceil}' + + ret += ' {t|burst}' + + return fmt.format(ret) + + def details(self): + fmt = util.MyFormatter(self) + + return fmt.nl('\t{t|level} {t|quantum}') def init_qdisc(qdisc): - qdisc.htb = HTBQdisc(qdisc) - return qdisc.htb + qdisc.htb = HTBQdisc(qdisc) + return qdisc.htb def init_class(cl): - cl.htb = HTBClass(cl) - return cl.htb + cl.htb = HTBClass(cl) + return cl.htb #extern void rtnl_htb_set_quantum(struct rtnl_class *, uint32_t quantum); diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py index 1c654e16..92f29506 100644 --- a/python/netlink/route/tc.py +++ b/python/netlink/route/tc.py @@ -4,12 +4,12 @@ from __future__ import absolute_import __all__ = [ - 'TcCache', - 'Tc', - 'QdiscCache', - 'Qdisc', - 'TcClassCache', - 'TcClass'] + 'TcCache', + 'Tc', + 'QdiscCache', + 'Qdisc', + 'TcClassCache', + 'TcClass'] import socket import sys @@ -47,218 +47,218 @@ STAT_MAX = STAT_OVERLIMITS ########################################################################### # Handle class Handle(object): - """ Traffic control handle + """ Traffic control handle - Representation of a traffic control handle which uniquely identifies - each traffic control object in its link namespace. + Representation of a traffic control handle which uniquely identifies + each traffic control object in its link namespace. - handle = tc.Handle('10:20') - handle = tc.handle('root') - print int(handle) - print str(handle) - """ - def __init__(self, val=None): - if type(val) is str: - val = capi.tc_str2handle(val) - elif not val: - val = 0 + handle = tc.Handle('10:20') + handle = tc.handle('root') + print int(handle) + print str(handle) + """ + def __init__(self, val=None): + if type(val) is str: + val = capi.tc_str2handle(val) + elif not val: + val = 0 - self._val = int(val) + self._val = int(val) - def __cmp__(self, other): - if other is None: - other = 0 + def __cmp__(self, other): + if other is None: + other = 0 - if isinstance(other, Handle): - return int(self) - int(other) - elif isinstance(other, int): - return int(self) - other - else: - raise TypeError() + if isinstance(other, Handle): + return int(self) - int(other) + elif isinstance(other, int): + return int(self) - other + else: + raise TypeError() - def __int__(self): - return self._val + def __int__(self): + return self._val - def __str__(self): - return capi.rtnl_tc_handle2str(self._val, 64)[0] + def __str__(self): + return capi.rtnl_tc_handle2str(self._val, 64)[0] - def isroot(self): - return self._val == TC_H_ROOT or self._val == TC_H_INGRESS + def isroot(self): + return self._val == TC_H_ROOT or self._val == TC_H_INGRESS ########################################################################### # TC Cache class TcCache(netlink.Cache): - """Cache of traffic control object""" + """Cache of traffic control object""" - def __getitem__(self, key): - raise NotImplementedError() + def __getitem__(self, key): + raise NotImplementedError() ########################################################################### # Tc Object class Tc(netlink.Object): - def __cmp__(self, other): - diff = self.ifindex - other.ifindex - if diff == 0: - diff = int(self.handle) - int(other.handle) - return diff - - def _tc_module_lookup(self): - self._module_lookup(self._module_path + self.kind, - 'init_' + self._name) - - @property - def root(self): - """True if tc object is a root object""" - return self.parent.isroot() - - ##################################################################### - # ifindex - @property - def ifindex(self): - """interface index""" - return capi.rtnl_tc_get_ifindex(self._rtnl_tc) - - @ifindex.setter - def ifindex(self, value): - capi.rtnl_tc_set_ifindex(self._rtnl_tc, int(value)) - - ##################################################################### - # link - @property - def link(self): - link = capi.rtnl_tc_get_link(self._rtnl_tc) - if not link: - return None - - return Link.Link.from_capi(link) - - @link.setter - def link(self, value): - capi.rtnl_tc_set_link(self._rtnl_tc, value._link) - - ##################################################################### - # mtu - @property - def mtu(self): - return capi.rtnl_tc_get_mtu(self._rtnl_tc) - - @mtu.setter - def mtu(self, value): - capi.rtnl_tc_set_mtu(self._rtnl_tc, int(value)) - - ##################################################################### - # mpu - @property - def mpu(self): - return capi.rtnl_tc_get_mpu(self._rtnl_tc) - - @mpu.setter - def mpu(self, value): - capi.rtnl_tc_set_mpu(self._rtnl_tc, int(value)) - - ##################################################################### - # overhead - @property - def overhead(self): - return capi.rtnl_tc_get_overhead(self._rtnl_tc) - - @overhead.setter - def overhead(self, value): - capi.rtnl_tc_set_overhead(self._rtnl_tc, int(value)) - - ##################################################################### - # linktype - @property - def linktype(self): - return capi.rtnl_tc_get_linktype(self._rtnl_tc) - - @linktype.setter - def linktype(self, value): - capi.rtnl_tc_set_linktype(self._rtnl_tc, int(value)) - - ##################################################################### - # handle - @property - def handle(self): - return Handle(capi.rtnl_tc_get_handle(self._rtnl_tc)) - - @handle.setter - def handle(self, value): - capi.rtnl_tc_set_handle(self._rtnl_tc, int(value)) - - ##################################################################### - # parent - @property - def parent(self): - return Handle(capi.rtnl_tc_get_parent(self._rtnl_tc)) - - @parent.setter - def parent(self, value): - capi.rtnl_tc_set_parent(self._rtnl_tc, int(value)) - - ##################################################################### - # kind - @property - def kind(self): - return capi.rtnl_tc_get_kind(self._rtnl_tc) - - @kind.setter - def kind(self, value): - capi.rtnl_tc_set_kind(self._rtnl_tc, value) - self._tc_module_lookup() - - def get_stat(self, id): - return capi.rtnl_tc_get_stat(self._rtnl_tc, id) - - @property - def _dev(self): - buf = util.kw('dev') + ' ' - - if self.link: - return buf + util.string(self.link.name) - else: - return buf + util.num(self.ifindex) - - def brief(self, title, nodev=False, noparent=False): - ret = title + ' {a|kind} {a|handle}' - - if not nodev: - ret += ' {a|_dev}' - - if not noparent: - ret += ' {t|parent}' - - return ret + self._module_brief() + def __cmp__(self, other): + diff = self.ifindex - other.ifindex + if diff == 0: + diff = int(self.handle) - int(other.handle) + return diff + + def _tc_module_lookup(self): + self._module_lookup(self._module_path + self.kind, + 'init_' + self._name) + + @property + def root(self): + """True if tc object is a root object""" + return self.parent.isroot() + + ##################################################################### + # ifindex + @property + def ifindex(self): + """interface index""" + return capi.rtnl_tc_get_ifindex(self._rtnl_tc) + + @ifindex.setter + def ifindex(self, value): + capi.rtnl_tc_set_ifindex(self._rtnl_tc, int(value)) + + ##################################################################### + # link + @property + def link(self): + link = capi.rtnl_tc_get_link(self._rtnl_tc) + if not link: + return None + + return Link.Link.from_capi(link) + + @link.setter + def link(self, value): + capi.rtnl_tc_set_link(self._rtnl_tc, value._link) + + ##################################################################### + # mtu + @property + def mtu(self): + return capi.rtnl_tc_get_mtu(self._rtnl_tc) + + @mtu.setter + def mtu(self, value): + capi.rtnl_tc_set_mtu(self._rtnl_tc, int(value)) + + ##################################################################### + # mpu + @property + def mpu(self): + return capi.rtnl_tc_get_mpu(self._rtnl_tc) + + @mpu.setter + def mpu(self, value): + capi.rtnl_tc_set_mpu(self._rtnl_tc, int(value)) + + ##################################################################### + # overhead + @property + def overhead(self): + return capi.rtnl_tc_get_overhead(self._rtnl_tc) + + @overhead.setter + def overhead(self, value): + capi.rtnl_tc_set_overhead(self._rtnl_tc, int(value)) + + ##################################################################### + # linktype + @property + def linktype(self): + return capi.rtnl_tc_get_linktype(self._rtnl_tc) + + @linktype.setter + def linktype(self, value): + capi.rtnl_tc_set_linktype(self._rtnl_tc, int(value)) + + ##################################################################### + # handle + @property + def handle(self): + return Handle(capi.rtnl_tc_get_handle(self._rtnl_tc)) + + @handle.setter + def handle(self, value): + capi.rtnl_tc_set_handle(self._rtnl_tc, int(value)) + + ##################################################################### + # parent + @property + def parent(self): + return Handle(capi.rtnl_tc_get_parent(self._rtnl_tc)) + + @parent.setter + def parent(self, value): + capi.rtnl_tc_set_parent(self._rtnl_tc, int(value)) + + ##################################################################### + # kind + @property + def kind(self): + return capi.rtnl_tc_get_kind(self._rtnl_tc) + + @kind.setter + def kind(self, value): + capi.rtnl_tc_set_kind(self._rtnl_tc, value) + self._tc_module_lookup() + + def get_stat(self, id): + return capi.rtnl_tc_get_stat(self._rtnl_tc, id) + + @property + def _dev(self): + buf = util.kw('dev') + ' ' + + if self.link: + return buf + util.string(self.link.name) + else: + return buf + util.num(self.ifindex) + + def brief(self, title, nodev=False, noparent=False): + ret = title + ' {a|kind} {a|handle}' + + if not nodev: + ret += ' {a|_dev}' + + if not noparent: + ret += ' {t|parent}' + + return ret + self._module_brief() - def details(self): - return '{t|mtu} {t|mpu} {t|overhead} {t|linktype}' - - @property - def packets(self): - return self.get_stat(STAT_PACKETS) - - @property - def bytes(self): - return self.get_stat(STAT_BYTES) - - @property - def qlen(self): - return self.get_stat(STAT_QLEN) - - def stats(self, fmt): - return fmt.nl('{t|packets} {t|bytes} {t|qlen}') + def details(self): + return '{t|mtu} {t|mpu} {t|overhead} {t|linktype}' + + @property + def packets(self): + return self.get_stat(STAT_PACKETS) + + @property + def bytes(self): + return self.get_stat(STAT_BYTES) + + @property + def qlen(self): + return self.get_stat(STAT_QLEN) + + def stats(self, fmt): + return fmt.nl('{t|packets} {t|bytes} {t|qlen}') ########################################################################### # Queueing discipline cache class QdiscCache(netlink.Cache): - """Cache of qdiscs""" + """Cache of qdiscs""" - def __init__(self, cache=None): - if not cache: - cache = self._alloc_cache_name("route/qdisc") + def __init__(self, cache=None): + if not cache: + cache = self._alloc_cache_name("route/qdisc") - self._protocol = netlink.NETLINK_ROUTE - self._nl_cache = cache + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache # def __getitem__(self, key): # if type(key) is int: @@ -271,56 +271,56 @@ class QdiscCache(netlink.Cache): # else: # return Qdisc._from_capi(capi.qdisc2obj(qdisc)) - def _new_object(self, obj): - return Qdisc(obj) + def _new_object(self, obj): + return Qdisc(obj) - def _new_cache(self, cache): - return QdiscCache(cache=cache) + def _new_cache(self, cache): + return QdiscCache(cache=cache) ########################################################################### # Qdisc Object class Qdisc(Tc): - """Queueing discipline""" + """Queueing discipline""" - def __init__(self, obj=None): - netlink.Object.__init__(self, "route/qdisc", "qdisc", obj) - self._module_path = 'netlink.route.qdisc.' - self._rtnl_qdisc = self._obj2type(self._nl_object) - self._rtnl_tc = capi.obj2tc(self._nl_object) + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/qdisc", "qdisc", obj) + self._module_path = 'netlink.route.qdisc.' + self._rtnl_qdisc = self._obj2type(self._nl_object) + self._rtnl_tc = capi.obj2tc(self._nl_object) - netlink.add_attr('qdisc.handle', fmt=util.handle) - netlink.add_attr('qdisc.parent', fmt=util.handle) - netlink.add_attr('qdisc.kind', fmt=util.bold) + netlink.add_attr('qdisc.handle', fmt=util.handle) + netlink.add_attr('qdisc.parent', fmt=util.handle) + netlink.add_attr('qdisc.kind', fmt=util.bold) - if self.kind: - self._tc_module_lookup() + if self.kind: + self._tc_module_lookup() - @classmethod - def from_capi(cls, obj): - return cls(capi.qdisc2obj(obj)) + @classmethod + def from_capi(cls, obj): + return cls(capi.qdisc2obj(obj)) - def _obj2type(self, obj): - return capi.obj2qdisc(obj) + def _obj2type(self, obj): + return capi.obj2qdisc(obj) - def _new_instance(self, obj): - if not obj: - raise ValueError() + def _new_instance(self, obj): + if not obj: + raise ValueError() - return Qdisc(obj) + return Qdisc(obj) - @property - def childs(self): - ret = [] + @property + def childs(self): + ret = [] - if int(self.handle): - ret += get_cls(self.ifindex, parent=self.handle) + if int(self.handle): + ret += get_cls(self.ifindex, parent=self.handle) - if self.root: - ret += get_class(self.ifindex, parent=TC_H_ROOT) + if self.root: + ret += get_class(self.ifindex, parent=TC_H_ROOT) - ret += get_class(self.ifindex, parent=self.handle) + ret += get_class(self.ifindex, parent=self.handle) - return ret + return ret # ##################################################################### # # add() @@ -350,22 +350,22 @@ class Qdisc(Tc): # if ret < 0: # raise netlink.KernelError(ret) - ################################################################### - # - # format(details=False, stats=False) - # - def format(self, details=False, stats=False, nodev=False, - noparent=False, indent=''): - """Return qdisc as formatted text""" - fmt = util.MyFormatter(self, indent) + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, nodev=False, + noparent=False, indent=''): + """Return qdisc as formatted text""" + fmt = util.MyFormatter(self, indent) - buf = fmt.format(self.brief('qdisc', nodev, noparent)) + buf = fmt.format(self.brief('qdisc', nodev, noparent)) - if details: - buf += fmt.nl('\t' + self.details()) + if details: + buf += fmt.nl('\t' + self.details()) - if stats: - buf += self.stats(fmt) + if stats: + buf += self.stats(fmt) # if stats: # l = [['Packets', RX_PACKETS, TX_PACKETS], @@ -423,230 +423,230 @@ class Qdisc(Tc): # row[2] = self.get_stat(row[2]) if row[2] else '' # buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) - return buf + return buf ########################################################################### # Traffic class cache class TcClassCache(netlink.Cache): - """Cache of traffic classes""" + """Cache of traffic classes""" - def __init__(self, ifindex, cache=None): - if not cache: - cache = self._alloc_cache_name("route/class") + def __init__(self, ifindex, cache=None): + if not cache: + cache = self._alloc_cache_name("route/class") - self._protocol = netlink.NETLINK_ROUTE - self._nl_cache = cache - self._set_arg1(ifindex) + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + self._set_arg1(ifindex) - def _new_object(self, obj): - return TcClass(obj) + def _new_object(self, obj): + return TcClass(obj) - def _new_cache(self, cache): - return TcClassCache(self.arg1, cache=cache) + def _new_cache(self, cache): + return TcClassCache(self.arg1, cache=cache) ########################################################################### # Traffic Class Object class TcClass(Tc): - """Traffic Class""" + """Traffic Class""" - def __init__(self, obj=None): - netlink.Object.__init__(self, "route/class", "class", obj) - self._module_path = 'netlink.route.qdisc.' - self._rtnl_class = self._obj2type(self._nl_object) - self._rtnl_tc = capi.obj2tc(self._nl_object) + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/class", "class", obj) + self._module_path = 'netlink.route.qdisc.' + self._rtnl_class = self._obj2type(self._nl_object) + self._rtnl_tc = capi.obj2tc(self._nl_object) - netlink.add_attr('class.handle', fmt=util.handle) - netlink.add_attr('class.parent', fmt=util.handle) - netlink.add_attr('class.kind', fmt=util.bold) + netlink.add_attr('class.handle', fmt=util.handle) + netlink.add_attr('class.parent', fmt=util.handle) + netlink.add_attr('class.kind', fmt=util.bold) - if self.kind: - self._tc_module_lookup() + if self.kind: + self._tc_module_lookup() - @classmethod - def from_capi(cls, obj): - return cls(capi.class2obj(obj)) + @classmethod + def from_capi(cls, obj): + return cls(capi.class2obj(obj)) - def _obj2type(self, obj): - return capi.obj2class(obj) + def _obj2type(self, obj): + return capi.obj2class(obj) - def _new_instance(self, obj): - if not obj: - raise ValueError() + def _new_instance(self, obj): + if not obj: + raise ValueError() - return TcClass(obj) + return TcClass(obj) - @property - def childs(self): - ret = [] + @property + def childs(self): + ret = [] - # classes can have classifiers, child classes and leaf - # qdiscs - ret += get_cls(self.ifindex, parent=self.handle) - ret += get_class(self.ifindex, parent=self.handle) - ret += get_qdisc(self.ifindex, parent=self.handle) + # classes can have classifiers, child classes and leaf + # qdiscs + ret += get_cls(self.ifindex, parent=self.handle) + ret += get_class(self.ifindex, parent=self.handle) + ret += get_qdisc(self.ifindex, parent=self.handle) - return ret + return ret - ################################################################### - # - # format(details=False, stats=False) - # - def format(self, details=False, stats=False, nodev=False, - noparent=False, indent=''): - """Return class as formatted text""" - fmt = util.MyFormatter(self, indent) + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, nodev=False, + noparent=False, indent=''): + """Return class as formatted text""" + fmt = util.MyFormatter(self, indent) - buf = fmt.format(self.brief('class', nodev, noparent)) + buf = fmt.format(self.brief('class', nodev, noparent)) - if details: - buf += fmt.nl('\t' + self.details()) + if details: + buf += fmt.nl('\t' + self.details()) - return buf + return buf ########################################################################### # Classifier Cache class ClassifierCache(netlink.Cache): - """Cache of traffic classifiers objects""" + """Cache of traffic classifiers objects""" - def __init__(self, ifindex, parent, cache=None): - if not cache: - cache = self._alloc_cache_name("route/cls") + def __init__(self, ifindex, parent, cache=None): + if not cache: + cache = self._alloc_cache_name("route/cls") - self._protocol = netlink.NETLINK_ROUTE - self._nl_cache = cache - self._set_arg1(ifindex) - self._set_arg2(int(parent)) + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + self._set_arg1(ifindex) + self._set_arg2(int(parent)) - def _new_object(self, obj): - return Classifier(obj) + def _new_object(self, obj): + return Classifier(obj) - def _new_cache(self, cache): - return ClassifierCache(self.arg1, self.arg2, cache=cache) + def _new_cache(self, cache): + return ClassifierCache(self.arg1, self.arg2, cache=cache) ########################################################################### # Classifier Object class Classifier(Tc): - """Classifier""" + """Classifier""" - def __init__(self, obj=None): - netlink.Object.__init__(self, "route/cls", "cls", obj) - self._module_path = 'netlink.route.cls.' - self._rtnl_cls = self._obj2type(self._nl_object) - self._rtnl_tc = capi.obj2tc(self._nl_object) + def __init__(self, obj=None): + netlink.Object.__init__(self, "route/cls", "cls", obj) + self._module_path = 'netlink.route.cls.' + self._rtnl_cls = self._obj2type(self._nl_object) + self._rtnl_tc = capi.obj2tc(self._nl_object) - netlink.add_attr('cls.handle', fmt=util.handle) - netlink.add_attr('cls.parent', fmt=util.handle) - netlink.add_attr('cls.kind', fmt=util.bold) + netlink.add_attr('cls.handle', fmt=util.handle) + netlink.add_attr('cls.parent', fmt=util.handle) + netlink.add_attr('cls.kind', fmt=util.bold) - @classmethod - def from_capi(cls, obj): - return cls(capi.cls2obj(obj)) + @classmethod + def from_capi(cls, obj): + return cls(capi.cls2obj(obj)) - def _obj2type(self, obj): - return capi.obj2cls(obj) + def _obj2type(self, obj): + return capi.obj2cls(obj) - def _new_instance(self, obj): - if not obj: - raise ValueError() + def _new_instance(self, obj): + if not obj: + raise ValueError() - return Classifier(obj) + return Classifier(obj) - ##################################################################### - # priority - @property - def priority(self): - return capi.rtnl_cls_get_prio(self._rtnl_cls) + ##################################################################### + # priority + @property + def priority(self): + return capi.rtnl_cls_get_prio(self._rtnl_cls) - @priority.setter - def priority(self, value): - capi.rtnl_cls_set_prio(self._rtnl_cls, int(value)) + @priority.setter + def priority(self, value): + capi.rtnl_cls_set_prio(self._rtnl_cls, int(value)) - ##################################################################### - # protocol - @property - def protocol(self): - return capi.rtnl_cls_get_protocol(self._rtnl_cls) + ##################################################################### + # protocol + @property + def protocol(self): + return capi.rtnl_cls_get_protocol(self._rtnl_cls) - @protocol.setter - def protocol(self, value): - capi.rtnl_cls_set_protocol(self._rtnl_cls, int(value)) + @protocol.setter + def protocol(self, value): + capi.rtnl_cls_set_protocol(self._rtnl_cls, int(value)) - @property - def childs(self): - return [] + @property + def childs(self): + return [] - ################################################################### - # - # format(details=False, stats=False) - # - def format(self, details=False, stats=False, nodev=False, - noparent=False, indent=''): - """Return class as formatted text""" - fmt = util.MyFormatter(self, indent) + ################################################################### + # + # format(details=False, stats=False) + # + def format(self, details=False, stats=False, nodev=False, + noparent=False, indent=''): + """Return class as formatted text""" + fmt = util.MyFormatter(self, indent) - buf = fmt.format(self.brief('classifier', nodev, noparent)) - buf += fmt.format(' {t|priority} {t|protocol}') + buf = fmt.format(self.brief('classifier', nodev, noparent)) + buf += fmt.format(' {t|priority} {t|protocol}') - if details: - buf += fmt.nl('\t' + self.details()) + if details: + buf += fmt.nl('\t' + self.details()) - return buf + return buf _qdisc_cache = QdiscCache() def get_qdisc(ifindex, handle=None, parent=None): - l = [] + l = [] - _qdisc_cache.refill() + _qdisc_cache.refill() - for qdisc in _qdisc_cache: - if qdisc.ifindex == ifindex and \ - (handle == None or qdisc.handle == handle) and \ - (parent == None or qdisc.parent == parent): - l.append(qdisc) + for qdisc in _qdisc_cache: + if qdisc.ifindex == ifindex and \ + (handle == None or qdisc.handle == handle) and \ + (parent == None or qdisc.parent == parent): + l.append(qdisc) - return l + return l _class_cache = {} def get_class(ifindex, parent, handle=None): - l = [] + l = [] - try: - cache = _class_cache[ifindex] - except KeyError: - cache = TcClassCache(ifindex) - _class_cache[ifindex] = cache + try: + cache = _class_cache[ifindex] + except KeyError: + cache = TcClassCache(ifindex) + _class_cache[ifindex] = cache - cache.refill() + cache.refill() - for cl in cache: - if (parent == None or cl.parent == parent) and \ - (handle == None or cl.handle == handle): - l.append(cl) + for cl in cache: + if (parent == None or cl.parent == parent) and \ + (handle == None or cl.handle == handle): + l.append(cl) - return l + return l _cls_cache = {} def get_cls(ifindex, parent, handle=None): - l = [] + l = [] - try: - chain = _cls_cache[ifindex] - except KeyError: - _cls_cache[ifindex] = {} + try: + chain = _cls_cache[ifindex] + except KeyError: + _cls_cache[ifindex] = {} - try: - cache = _cls_cache[ifindex][parent] - except KeyError: - cache = ClassifierCache(ifindex, parent) - _cls_cache[ifindex][parent] = cache + try: + cache = _cls_cache[ifindex][parent] + except KeyError: + cache = ClassifierCache(ifindex, parent) + _cls_cache[ifindex][parent] = cache - cache.refill() + cache.refill() - for cls in cache: - if handle == None or cls.handle == handle: - l.append(cls) + for cls in cache: + if handle == None or cls.handle == handle: + l.append(cls) - return l + return l diff --git a/python/netlink/util.py b/python/netlink/util.py index 73a211df..5249be9d 100644 --- a/python/netlink/util.py +++ b/python/netlink/util.py @@ -18,162 +18,162 @@ import types __version__ = "1.0" def _color(t, c): - return b'{esc}[{color}m{text}{esc}[0m'.format(esc=b'\x1b', color=c, text=t) + return b'{esc}[{color}m{text}{esc}[0m'.format(esc=b'\x1b', color=c, text=t) def black(t): - return _color(t, 30) + return _color(t, 30) def red(t): - return _color(t, 31) + return _color(t, 31) def green(t): - return _color(t, 32) + return _color(t, 32) def yellow(t): - return _color(t, 33) + return _color(t, 33) def blue(t): - return _color(t, 34) + return _color(t, 34) def magenta(t): - return _color(t, 35) + return _color(t, 35) def cyan(t): - return _color(t, 36) + return _color(t, 36) def white(t): - return _color(t, 37) + return _color(t, 37) def bold(t): - return _color(t, 1) + return _color(t, 1) def kw(t): - return yellow(t) + return yellow(t) def num(t): - return str(t) + return str(t) def string(t): - return t + return t def addr(t): - return str(t) + return str(t) def bad(t): - return red(t) + return red(t) def good(t): - return green(t) + return green(t) def title(t): - return t + return t def bool(t): - return str(t) + return str(t) def handle(t): - return str(t) + return str(t) class MyFormatter(Formatter): - def __init__(self, obj, indent=''): - self._obj = obj - self._indent = indent - - def _nlattr(self, key): - value = getattr(self._obj, key) - title = None - - if isinstance(value, types.MethodType): - value = value() - - try: - d = netlink.attrs[self._obj._name + '.' + key] - - if 'fmt' in d: - value = d['fmt'](value) - - if 'title' in d: - title = d['title'] - except KeyError: - pass - except AttributeError: - pass - - return title, str(value) - - def get_value(self, key, args, kwds): - # Let default get_value() handle ints - if not isinstance(key, str): - return Formatter.get_value(self, key, args, kwds) - - # HACK, we allow defining strings via fields to allow - # conversions - if key[:2] == 's|': - return key[2:] - - if key[:2] == 't|': - # title mode ("TITLE ATTR") - include_title = True - elif key[:2] == 'a|': - # plain attribute mode ("ATTR") - include_title = False - else: - # No special field, have default get_value() get it - return Formatter.get_value(self, key, args, kwds) - - key = key[2:] - (title, value) = self._nlattr(key) - - if include_title: - if not title: - title = key # fall back to key as title - value = '{0} {1}'.format(kw(title), value) - - return value - - def convert_field(self, value, conversion): - if conversion == 'r': - return repr(value) - elif conversion == 's': - return str(value) - elif conversion == 'k': - return kw(value) - elif conversion == 'b': - return bold(value) - elif conversion is None: - return value - - raise ValueError("Unknown converion specifier {0!s}".format(conversion)) - - def nl(self, format_string=''): - return '\n' + self._indent + self.format(format_string) + def __init__(self, obj, indent=''): + self._obj = obj + self._indent = indent + + def _nlattr(self, key): + value = getattr(self._obj, key) + title = None + + if isinstance(value, types.MethodType): + value = value() + + try: + d = netlink.attrs[self._obj._name + '.' + key] + + if 'fmt' in d: + value = d['fmt'](value) + + if 'title' in d: + title = d['title'] + except KeyError: + pass + except AttributeError: + pass + + return title, str(value) + + def get_value(self, key, args, kwds): + # Let default get_value() handle ints + if not isinstance(key, str): + return Formatter.get_value(self, key, args, kwds) + + # HACK, we allow defining strings via fields to allow + # conversions + if key[:2] == 's|': + return key[2:] + + if key[:2] == 't|': + # title mode ("TITLE ATTR") + include_title = True + elif key[:2] == 'a|': + # plain attribute mode ("ATTR") + include_title = False + else: + # No special field, have default get_value() get it + return Formatter.get_value(self, key, args, kwds) + + key = key[2:] + (title, value) = self._nlattr(key) + + if include_title: + if not title: + title = key # fall back to key as title + value = '{0} {1}'.format(kw(title), value) + + return value + + def convert_field(self, value, conversion): + if conversion == 'r': + return repr(value) + elif conversion == 's': + return str(value) + elif conversion == 'k': + return kw(value) + elif conversion == 'b': + return bold(value) + elif conversion is None: + return value + + raise ValueError("Unknown converion specifier {0!s}".format(conversion)) + + def nl(self, format_string=''): + return '\n' + self._indent + self.format(format_string) NL_BYTE_RATE = 0 NL_BIT_RATE = 1 class Rate(object): - def __init__(self, rate, mode=NL_BYTE_RATE): - self._rate = rate - self._mode = mode + def __init__(self, rate, mode=NL_BYTE_RATE): + self._rate = rate + self._mode = mode - def __str__(self): - return capi.nl_rate2str(self._rate, self._mode, 32)[1] + def __str__(self): + return capi.nl_rate2str(self._rate, self._mode, 32)[1] - def __int__(self): - return self._rate + def __int__(self): + return self._rate - def __cmp__(self, other): - return int(self) - int(other) + def __cmp__(self, other): + return int(self) - int(other) class Size(object): - def __init__(self, size): - self._size = size + def __init__(self, size): + self._size = size - def __str__(self): - return capi.nl_size2str(self._size, 32)[0] + def __str__(self): + return capi.nl_size2str(self._size, 32)[0] - def __int__(self): - return self._size + def __int__(self): + return self._size - def __cmp__(self, other): - return int(self) - int(other) + def __cmp__(self, other): + return int(self) - int(other) -- cgit v1.2.3