Mini Shell
import importlib
import logging
import os
import pkgutil
import struct
import sys
from socket import AF_INET, AF_INET6
from pyroute2 import config
from pyroute2.common import basestring, map_namespace
from pyroute2.config import AF_BRIDGE
from pyroute2.netlink import NLA_F_NESTED, nla, nlmsg, nlmsg_atoms
from pyroute2.netlink.rtnl.ifinfmsg.plugins import (
bond,
can,
geneve,
gtp,
ipoib,
ipvlan,
team,
tun,
tuntap,
vlan,
vrf,
vti,
vti6,
vxlan,
xfrm,
)
from pyroute2.netlink.rtnl.iw_event import iw_event
log = logging.getLogger(__name__)
# it's simpler to double constants here, than to change all the
# module layout; but it is a subject of the future refactoring
RTM_NEWLINK = 16
RTM_DELLINK = 17
#
##
#
# tuntap flags
#
IFT_TUN = 0x0001
IFT_TAP = 0x0002
IFT_NO_PI = 0x1000
IFT_ONE_QUEUE = 0x2000
IFT_VNET_HDR = 0x4000
IFT_TUN_EXCL = 0x8000
IFT_MULTI_QUEUE = 0x0100
IFT_ATTACH_QUEUE = 0x0200
IFT_DETACH_QUEUE = 0x0400
# read-only
IFT_PERSIST = 0x0800
IFT_NOFILTER = 0x1000
##
#
# normal flags
#
IFF_UP = 0x1 # interface is up
IFF_BROADCAST = 0x2 # broadcast address valid
IFF_DEBUG = 0x4 # turn on debugging
IFF_LOOPBACK = 0x8 # is a loopback net
IFF_POINTOPOINT = 0x10 # interface is has p-p link
IFF_NOTRAILERS = 0x20 # avoid use of trailers
IFF_RUNNING = 0x40 # interface RFC2863 OPER_UP
IFF_NOARP = 0x80 # no ARP protocol
IFF_PROMISC = 0x100 # receive all packets
IFF_ALLMULTI = 0x200 # receive all multicast packets
IFF_MASTER = 0x400 # master of a load balancer
IFF_SLAVE = 0x800 # slave of a load balancer
IFF_MULTICAST = 0x1000 # Supports multicast
IFF_PORTSEL = 0x2000 # can set media type
IFF_AUTOMEDIA = 0x4000 # auto media select active
IFF_DYNAMIC = 0x8000 # dialup device with changing addresses
IFF_LOWER_UP = 0x10000 # driver signals L1 up
IFF_DORMANT = 0x20000 # driver signals dormant
IFF_ECHO = 0x40000 # echo sent packets
(IFF_NAMES, IFF_VALUES) = map_namespace('IFF', globals())
IFF_MASK = (
IFF_UP
| IFF_DEBUG
| IFF_NOTRAILERS
| IFF_NOARP
| IFF_PROMISC
| IFF_ALLMULTI
)
IFF_VOLATILE = (
IFF_LOOPBACK
| IFF_POINTOPOINT
| IFF_BROADCAST
| IFF_ECHO
| IFF_MASTER
| IFF_SLAVE
| IFF_RUNNING
| IFF_LOWER_UP
| IFF_DORMANT
)
##
#
# gre flags
#
GRE_ACK = 0x0080
GRE_REC = 0x0700
GRE_STRICT = 0x0800
GRE_SEQ = 0x1000
GRE_KEY = 0x2000
GRE_ROUTING = 0x4000
GRE_CSUM = 0x8000
(GRE_NAMES, GRE_VALUES) = map_namespace('GRE_', globals())
##
#
# vlan filter flags
#
BRIDGE_VLAN_INFO_MASTER = 0x1 # operate on bridge device
BRIDGE_VLAN_INFO_PVID = 0x2 # ingress untagged
BRIDGE_VLAN_INFO_UNTAGGED = 0x4 # egress untagged
BRIDGE_VLAN_INFO_RANGE_BEGIN = 0x8 # range start
BRIDGE_VLAN_INFO_RANGE_END = 0x10 # range end
BRIDGE_VLAN_INFO_BRENTRY = 0x20 # global bridge vlan entry
(BRIDGE_VLAN_NAMES, BRIDGE_VLAN_VALUES) = map_namespace(
'BRIDGE_VLAN_INFO', globals()
)
BRIDGE_VLAN_TUNNEL_UNSPEC = 0
BRIDGE_VLAN_TUNNEL_ID = 1
BRIDGE_VLAN_TUNNEL_VID = 2
BRIDGE_VLAN_TUNNEL_FLAGS = 3
BRIDGE_VLAN_TUNNEL_MAX = 4
BRIDGE_FLAGS_MASTER = 1
BRIDGE_FLAGS_SELF = 2
(BRIDGE_FLAGS_NAMES, BRIDGE_FLAGS_VALUES) = map_namespace(
'BRIDGE_FLAGS', globals()
)
##
#
# XDP flags
#
XDP_FLAGS_UPDATE_IF_NOEXIST = 1 << 0
XDP_FLAGS_SKB_MODE = 1 << 1
XDP_FLAGS_DRV_MODE = 1 << 2
XDP_FLAGS_HW_MODE = 1 << 3
XDP_FLAGS_REPLACE = 1 << 4
XDP_FLAGS_MODES = XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE
XDP_FLAGS_MASK = (
XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_MODES | XDP_FLAGS_REPLACE
)
(XDP_FLAGS_NAMES, XDP_FLAGS_VALUES) = map_namespace('XDP_FLAGS', globals())
states = (
'UNKNOWN',
'NOTPRESENT',
'DOWN',
'LOWERLAYERDOWN',
'TESTING',
'DORMANT',
'UP',
)
state_by_name = {i[1]: i[0] for i in enumerate(states)}
state_by_code = dict(enumerate(states))
stats_names = (
'rx_packets',
'tx_packets',
'rx_bytes',
'tx_bytes',
'rx_errors',
'tx_errors',
'rx_dropped',
'tx_dropped',
'multicast',
'collisions',
'rx_length_errors',
'rx_over_errors',
'rx_crc_errors',
'rx_frame_errors',
'rx_fifo_errors',
'rx_missed_errors',
'tx_aborted_errors',
'tx_carrier_errors',
'tx_fifo_errors',
'tx_heartbeat_errors',
'tx_window_errors',
'rx_compressed',
'tx_compressed',
)
def load_plugins_by_path(path):
plugins = {}
files = set(
[
x.split('.')[0]
for x in filter(
lambda x: x.endswith(('.py', '.pyc', '.pyo')), os.listdir(path)
)
if not x.startswith('_')
]
)
sys.path.append(path)
for name in files:
try:
module = __import__(name, globals(), locals(), [], 0)
register_kind = getattr(module, 'register_kind', name)
plugins[register_kind] = getattr(module, register_kind)
except:
pass
sys.path.pop()
return plugins
def load_plugins_by_pkg(pkg):
plugins = {}
plugin_modules = {
name: name.split('.')[-1]
for loader, name, ispkg in pkgutil.iter_modules(
path=pkg.__path__, prefix=pkg.__name__ + '.'
)
}
# Hack to make it compatible with pyinstaller
# plugin loading will work with and without pyinstaller
# Inspired on:
# https://github.com/webcomics/dosage/blob/master/dosagelib/loader.py
# see: https://github.com/pyinstaller/pyinstaller/issues/1905
importers = map(pkgutil.get_importer, pkg.__path__)
toc = set()
for importer in importers:
if hasattr(importer, 'toc'):
toc |= importer.toc
for element in toc:
if element.startswith(pkg.__name__) and element != pkg.__name__:
plugin_modules[element] = element.split('.')[-1]
for mod_path, mod_name in plugin_modules.items():
if mod_name.startswith('_'):
continue
module = importlib.import_module(mod_path)
register_kind = getattr(module, 'register_kind', mod_name)
plugins[register_kind] = getattr(module, register_kind)
return plugins
data_plugins = {}
for module in (
bond,
can,
geneve,
gtp,
ipvlan,
team,
tuntap,
tun,
vlan,
vrf,
vti,
vti6,
vxlan,
xfrm,
ipoib,
):
name = module.__name__.split('.')[-1]
data_plugins[name] = getattr(module, name)
for pkg in config.data_plugins_pkgs:
data_plugins.update(load_plugins_by_pkg(pkg))
for path in config.data_plugins_path:
data_plugins.update(load_plugins_by_path(path))
class ifla_bridge_id(nla):
fields = [('value', '=8s')]
def encode(self):
r_prio = struct.pack('H', self['prio'])
r_addr = struct.pack(
'BBBBBB', *[int(i, 16) for i in self['addr'].split(':')]
)
self['value'] = r_prio + r_addr
nla.encode(self)
def decode(self):
nla.decode(self)
r_prio = self['value'][:2]
r_addr = self['value'][2:]
self.value = {
'prio': struct.unpack('H', r_prio)[0],
'addr': ':'.join(
'%02x' % (i) for i in struct.unpack('BBBBBB', r_addr)
),
}
class protinfo_bridge(nla):
prefix = 'IFLA_BRPORT_'
nla_map = (
('IFLA_BRPORT_UNSPEC', 'none'),
('IFLA_BRPORT_STATE', 'uint8'),
('IFLA_BRPORT_PRIORITY', 'uint16'),
('IFLA_BRPORT_COST', 'uint32'),
('IFLA_BRPORT_MODE', 'uint8'),
('IFLA_BRPORT_GUARD', 'uint8'),
('IFLA_BRPORT_PROTECT', 'uint8'),
('IFLA_BRPORT_FAST_LEAVE', 'uint8'),
('IFLA_BRPORT_LEARNING', 'uint8'),
('IFLA_BRPORT_UNICAST_FLOOD', 'uint8'),
('IFLA_BRPORT_PROXYARP', 'uint8'),
('IFLA_BRPORT_LEARNING_SYNC', 'uint8'),
('IFLA_BRPORT_PROXYARP_WIFI', 'uint8'),
('IFLA_BRPORT_ROOT_ID', 'br_id'),
('IFLA_BRPORT_BRIDGE_ID', 'br_id'),
('IFLA_BRPORT_DESIGNATED_PORT', 'uint16'),
('IFLA_BRPORT_DESIGNATED_COST', 'uint16'),
('IFLA_BRPORT_ID', 'uint16'),
('IFLA_BRPORT_NO', 'uint16'),
('IFLA_BRPORT_TOPOLOGY_CHANGE_ACK', 'uint8'),
('IFLA_BRPORT_CONFIG_PENDING', 'uint8'),
('IFLA_BRPORT_MESSAGE_AGE_TIMER', 'uint64'),
('IFLA_BRPORT_FORWARD_DELAY_TIMER', 'uint64'),
('IFLA_BRPORT_HOLD_TIMER', 'uint64'),
('IFLA_BRPORT_FLUSH', 'flag'),
('IFLA_BRPORT_MULTICAST_ROUTER', 'uint8'),
('IFLA_BRPORT_PAD', 'uint64'),
('IFLA_BRPORT_MCAST_FLOOD', 'uint8'),
('IFLA_BRPORT_MCAST_TO_UCAST', 'uint8'),
('IFLA_BRPORT_VLAN_TUNNEL', 'uint8'),
('IFLA_BRPORT_BCAST_FLOOD', 'uint8'),
('IFLA_BRPORT_GROUP_FWD_MASK', 'uint16'),
('IFLA_BRPORT_NEIGH_SUPPRESS', 'uint8'),
('IFLA_BRPORT_ISOLATED', 'uint8'),
('IFLA_BRPORT_BACKUP_PORT', 'uint32'),
('IFLA_BRPORT_MRP_RING_OPEN', 'uint8'),
('IFLA_BRPORT_MRP_IN_OPEN', 'uint8'),
)
class br_id(ifla_bridge_id):
pass
class macvx_data(nla):
prefix = 'IFLA_'
nla_map = (
('IFLA_MACVLAN_UNSPEC', 'none'),
('IFLA_MACVLAN_MODE', 'mode'),
('IFLA_MACVLAN_FLAGS', 'flags'),
('IFLA_MACVLAN_MACADDR_MODE', 'macaddr_mode'),
('IFLA_MACVLAN_MACADDR', 'l2addr'),
('IFLA_MACVLAN_MACADDR_DATA', 'macaddr_data'),
('IFLA_MACVLAN_MACADDR_COUNT', 'uint32'),
)
class mode(nlmsg_atoms.uint32):
value_map = {
0: 'none',
1: 'private',
2: 'vepa',
4: 'bridge',
8: 'passthru',
16: 'source',
}
class flags(nlmsg_atoms.uint16):
value_map = {0: 'none', 1: 'nopromisc'}
class macaddr_mode(nlmsg_atoms.uint32):
value_map = {0: 'add', 1: 'del', 2: 'flush', 3: 'set'}
class macaddr_data(nla):
nla_map = ((4, 'IFLA_MACVLAN_MACADDR', 'l2addr'),)
class iptnl_data(nla):
prefix = 'IFLA_'
nla_map = (
('IFLA_IPIP_UNSPEC', 'none'),
('IFLA_IPIP_LINK', 'uint32'),
('IFLA_IPIP_LOCAL', 'ip4addr'),
('IFLA_IPIP_REMOTE', 'ip4addr'),
('IFLA_IPIP_TTL', 'uint8'),
('IFLA_IPIP_TOS', 'uint8'),
('IFLA_IPIP_ENCAP_LIMIT', 'uint8'),
('IFLA_IPIP_FLOWINFO', 'be32'),
('IFLA_IPIP_FLAGS', 'uint32'),
('IFLA_IPIP_PROTO', 'uint8'),
('IFLA_IPIP_PMTUDISC', 'uint8'),
('IFLA_IPIP_6RD_PREFIX', 'ip6addr'),
('IFLA_IPIP_6RD_RELAY_PREFIX', 'ip4addr'),
('IFLA_IPIP_6RD_PREFIXLEN', 'uint16'),
('IFLA_IPIP_6RD_RELAY_PREFIXLEN', 'uint16'),
('IFLA_IPIP_ENCAP_TYPE', 'uint16'),
('IFLA_IPIP_ENCAP_FLAGS', 'uint16'),
('IFLA_IPIP_ENCAP_SPORT', 'be16'),
('IFLA_IPIP_ENCAP_DPORT', 'be16'),
('IFLA_IPIP_COLLECT_METADATA', 'flag'),
('IFLA_IPIP_FWMARK', 'uint32'),
)
class ifinfbase(object):
'''
Network interface message.
C structure::
struct ifinfomsg {
unsigned char ifi_family; /* AF_UNSPEC */
unsigned short ifi_type; /* Device type */
int ifi_index; /* Interface index */
unsigned int ifi_flags; /* Device flags */
unsigned int ifi_change; /* change mask */
};
'''
prefix = 'IFLA_'
#
# Changed from PRIMARY KEY to NOT NULL to support multiple
# targets in one table, so we can collect info from multiple
# systems.
#
# To provide data integrity one should use foreign keys,
# but when you create a foreign key using interfaces as
# the parent table, create also a unique index on
# the fields specified in the foreign key definition.
#
# E.g.
#
# CREATE TABLE interfaces (f_target TEXT NOT NULL,
# f_index INTEGER NOT NULL, ...)
# CREATE TABLE routes (f_target TEXT NOT NULL,
# f_RTA_OIF INTEGER, ...
# FOREIGN KEY (f_target, f_RTA_OIF)
# REFERENCES interfaces(f_target, f_index))
# CREATE UNIQUE INDEX if_idx ON interfaces(f_target, f_index)
#
sql_constraints = {'index': 'NOT NULL'}
sql_extra_fields = (('state', 'TEXT'),)
lookup_fallbacks = {'index': 'ifname'}
fields = (
('family', 'B'),
('__align', 'x'),
('ifi_type', 'H'),
('index', 'i'),
('flags', 'I'),
('change', 'I'),
)
nla_map = (
('IFLA_UNSPEC', 'none'),
('IFLA_ADDRESS', 'l2addr'),
('IFLA_BROADCAST', 'l2addr'),
('IFLA_IFNAME', 'asciiz'),
('IFLA_MTU', 'uint32'),
('IFLA_LINK', 'uint32'),
('IFLA_QDISC', 'asciiz'),
('IFLA_STATS', 'ifstats'),
('IFLA_COST', 'hex'),
('IFLA_PRIORITY', 'hex'),
('IFLA_MASTER', 'uint32'),
('IFLA_WIRELESS', 'wireless'),
('IFLA_PROTINFO', 'protinfo'),
('IFLA_TXQLEN', 'uint32'),
('IFLA_MAP', 'ifmap'),
('IFLA_WEIGHT', 'hex'),
('IFLA_OPERSTATE', 'state'),
('IFLA_LINKMODE', 'uint8'),
('IFLA_LINKINFO', 'ifinfo'),
('IFLA_NET_NS_PID', 'uint32'),
('IFLA_IFALIAS', 'asciiz'),
('IFLA_NUM_VF', 'uint32'),
('IFLA_VFINFO_LIST', 'vflist'),
('IFLA_STATS64', 'ifstats64'),
('IFLA_VF_PORTS', 'hex'),
('IFLA_PORT_SELF', 'hex'),
('IFLA_AF_SPEC', 'af_spec'),
('IFLA_GROUP', 'uint32'),
('IFLA_NET_NS_FD', 'netns_fd'),
('IFLA_EXT_MASK', 'uint32'),
('IFLA_PROMISCUITY', 'uint32'),
('IFLA_NUM_TX_QUEUES', 'uint32'),
('IFLA_NUM_RX_QUEUES', 'uint32'),
('IFLA_CARRIER', 'uint8'),
('IFLA_PHYS_PORT_ID', 'hex'),
('IFLA_CARRIER_CHANGES', 'uint32'),
('IFLA_PHYS_SWITCH_ID', 'hex'),
('IFLA_LINK_NETNSID', 'int32'),
('IFLA_PHYS_PORT_NAME', 'asciiz'),
('IFLA_PROTO_DOWN', 'uint8'),
('IFLA_GSO_MAX_SEGS', 'uint32'),
('IFLA_GSO_MAX_SIZE', 'uint32'),
('IFLA_PAD', 'hex'),
('IFLA_XDP', 'xdp'),
('IFLA_EVENT', 'uint32'),
('IFLA_NEW_NETNSID', 'be32'),
('IFLA_IF_NETNSID', 'uint32'),
('IFLA_CARRIER_UP_COUNT', 'uint32'),
('IFLA_CARRIER_DOWN_COUNT', 'uint32'),
('IFLA_NEW_IFINDEX', 'uint32'),
('IFLA_MIN_MTU', 'uint32'),
('IFLA_MAX_MTU', 'uint32'),
('IFLA_PROP_LIST', 'proplist'),
('IFLA_ALT_IFNAME', 'asciiz'),
('IFLA_PERM_ADDRESS', 'hex'),
('IFLA_PROTO_DOWN_REASON', 'down_reason'),
('IFLA_PARENT_DEV_NAME', 'asciiz'),
('IFLA_PARENT_DEV_BUS_NAME', 'asciiz'),
('IFLA_GRO_MAX_SIZE', 'uint32'),
('IFLA_TSO_MAX_SIZE', 'uint32'),
('IFLA_TSO_MAX_SEGS', 'uint32'),
)
@staticmethod
def flags2names(flags, mask=0xFFFFFFFF):
ret = []
for flag in IFF_VALUES:
if (flag & mask & flags) == flag:
ret.append(IFF_VALUES[flag])
return ret
@staticmethod
def names2flags(flags):
ret = 0
mask = 0
for flag in flags:
if flag[0] == '!':
flag = flag[1:]
else:
ret |= IFF_NAMES[flag]
mask |= IFF_NAMES[flag]
return (ret, mask)
def encode(self):
# convert flags
if isinstance(self['flags'], (set, tuple, list)):
self['flags'], self['change'] = self.names2flags(self['flags'])
return super(ifinfbase, self).encode()
class down_reason(nla):
nla_flags = NLA_F_NESTED
prefix = 'IFLA_'
nla_map = (
('IFLA_PROTO_DOWN_REASON_UNSPEC', 'none'),
('IFLA_PROTO_DOWN_REASON_MASK', 'uint32'),
('IFLA_PROTO_DOWN_REASON_VALUE', 'uint32'),
)
class netns_fd(nla):
fields = [('value', 'I')]
netns_run_dir = '/var/run/netns'
netns_fd = None
def encode(self):
#
# There are two ways to specify netns
#
# 1. provide fd to an open file
# 2. provide a file name
#
# In the first case, the value is passed to the kernel
# as is. In the second case, the object opens appropriate
# file from `self.netns_run_dir` and closes it upon
# `__del__(self)`
if isinstance(self.value, int):
self['value'] = self.value
else:
if isinstance(self.value, bytes):
self.value = self.value.decode('utf-8')
if '/' in self.value:
netns_path = self.value
else:
netns_path = '%s/%s' % (self.netns_run_dir, self.value)
self.netns_fd = os.open(netns_path, os.O_RDONLY)
self['value'] = self.netns_fd
self.register_clean_cb(self.close)
nla.encode(self)
def close(self):
if self.netns_fd is not None:
os.close(self.netns_fd)
class xdp(nla):
nla_flags = NLA_F_NESTED
prefix = 'IFLA_'
nla_map = (
('IFLA_XDP_UNSPEC', 'none'),
('IFLA_XDP_FD', 'xdp_fd'),
('IFLA_XDP_ATTACHED', 'xdp_mode'),
('IFLA_XDP_FLAGS', 'xdp_flags'),
('IFLA_XDP_PROG_ID', 'uint32'),
('IFLA_XDP_DRV_PROG_ID', 'uint32'),
('IFLA_XDP_SKB_PROG_ID', 'uint32'),
('IFLA_XDP_HW_PROG_ID', 'uint32'),
('IFLA_XDP_EXPECTED_FD', 'xdp_fd'),
)
class xdp_fd(nlmsg_atoms.int32):
sql_type = None
class xdp_flags(nla):
fields = [('value', '>H')]
sql_type = 'INTEGER'
def encode(self):
v = self.value
for flag in XDP_FLAGS_VALUES:
v &= ~flag
if v != 0:
log.warning('possibly incorrect XDP flags')
nla.encode(self)
class xdp_mode(nlmsg_atoms.uint8):
value_map = {
0: None,
1: 'xdp',
2: 'xdpgeneric',
3: 'xdpoffload',
4: 'xdpmulti',
}
class proplist(nla):
nla_flags = NLA_F_NESTED
# Proplist has currently only IFLA_ALT_IFNAME, but start at same
# index than IFLA_ALT_IFNAME in ifinfbase()
nla_map = ((53, 'IFLA_ALT_IFNAME', 'asciiz'),)
def altnames(self):
return (
attr[1]
for attr in self["attrs"]
if attr[0] == "IFLA_ALT_IFNAME"
)
class vflist(nla):
nla_map = (('IFLA_VF_INFO_UNSPEC', 'none'), ('IFLA_VF_INFO', 'vfinfo'))
class vfinfo(nla):
prefix = 'IFLA_VF_'
nla_map = (
('IFLA_VF_UNSPEC', 'none'),
('IFLA_VF_MAC', 'vf_mac'),
('IFLA_VF_VLAN', 'vf_vlan'),
('IFLA_VF_TX_RATE', 'vf_tx_rate'),
('IFLA_VF_SPOOFCHK', 'vf_spoofchk'),
('IFLA_VF_LINK_STATE', 'vf_link_state'),
('IFLA_VF_RATE', 'vf_rate'),
('IFLA_VF_RSS_QUERY_EN', 'vf_rss_query_en'),
('IFLA_VF_STATS', 'vf_stats'),
('IFLA_VF_TRUST', 'vf_trust'),
('IFLA_VF_IB_NODE_GUID', 'vf_ib_node_guid'),
('IFLA_VF_IB_PORT_GUID', 'vf_ib_port_guid'),
('IFLA_VF_VLAN_LIST', 'vf_vlist'),
)
class vf_ib_node_guid(nla):
fields = (('vf', 'I'), ('ib_node_guid', '32B'))
def decode(self):
nla.decode(self)
self['ib_node_guid'] = ':'.join(
['%02x' % x for x in self['ib_node_guid'][4:12][::-1]]
)
def encode(self):
encoded_guid = self['ib_node_guid'].split(':')[::-1]
self['ib_node_guid'] = (
[0] * 4 + [int(x, 16) for x in encoded_guid] + [0] * 20
)
nla.encode(self)
class vf_ib_port_guid(nla):
fields = (('vf', 'I'), ('ib_port_guid', '32B'))
def decode(self):
nla.decode(self)
self['ib_port_guid'] = ':'.join(
['%02x' % x for x in self['ib_port_guid'][4:12][::-1]]
)
def encode(self):
encoded_guid = self['ib_port_guid'].split(':')[::-1]
self['ib_port_guid'] = (
[0] * 4 + [int(x, 16) for x in encoded_guid] + [0] * 20
)
nla.encode(self)
class vf_mac(nla):
fields = (('vf', 'I'), ('mac', '32B'))
def decode(self):
nla.decode(self)
self['mac'] = ':'.join(
['%02x' % x for x in self['mac'][:6]]
)
def encode(self):
self['mac'] = [
int(x, 16) for x in self['mac'].split(':')
] + [0] * 26
nla.encode(self)
class vf_vlan(nla):
fields = (('vf', 'I'), ('vlan', 'I'), ('qos', 'I'))
class vf_tx_rate(nla):
fields = (('vf', 'I'), ('tx_rate', 'I'))
class vf_spoofchk(nla):
fields = (('vf', 'I'), ('spoofchk', 'I'))
class vf_link_state(nla):
fields = (('vf', 'I'), ('link_state', 'I'))
class vf_rate(nla):
fields = (
('vf', 'I'),
('min_tx_rate', 'I'),
('max_tx_rate', 'I'),
)
class vf_rss_query_en(nla):
fields = (('vf', 'I'), ('rss_query_en', 'I'))
class vf_stats(nla):
nla_map = (
('IFLA_VF_STATS_RX_PACKETS', 'uint64'),
('IFLA_VF_STATS_TX_PACKETS', 'uint64'),
('IFLA_VF_STATS_RX_BYTES', 'uint64'),
('IFLA_VF_STATS_TX_BYTES', 'uint64'),
('IFLA_VF_STATS_BROADCAST', 'uint64'),
('IFLA_VF_STATS_MULTICAST', 'uint64'),
('IFLA_VF_STATS_PAD', 'uint64'),
('IFLA_VF_STATS_RX_DROPPED', 'uint64'),
('IFLA_VF_STATS_TX_DROPPED', 'uint64'),
)
class vf_trust(nla):
fields = (('vf', 'I'), ('trust', 'I'))
class vf_vlist(nla):
nla_map = (
('IFLA_VF_VLAN_INFO_UNSPEC', 'none'),
('IFLA_VF_VLAN_INFO', 'ivvi'),
)
class ivvi(nla):
fields = (
('vf', 'I'),
('vlan', 'I'),
('qos', 'I'),
('proto', '>H'),
)
class wireless(iw_event):
pass
class state(nla):
fields = (('value', 'B'),)
sql_type = 'TEXT'
def encode(self):
self['value'] = state_by_name[self.value]
nla.encode(self)
def decode(self):
nla.decode(self)
self.value = state_by_code[self['value']]
class ifstats(nla):
fields = [(i, 'I') for i in stats_names]
class ifstats64(nla):
fields = [(i, 'Q') for i in stats_names]
class ifmap(nla):
fields = (
('mem_start', 'Q'),
('mem_end', 'Q'),
('base_addr', 'Q'),
('irq', 'H'),
('dma', 'B'),
('port', 'B'),
)
@staticmethod
def protinfo(self, *argv, **kwarg):
proto_map = {AF_BRIDGE: protinfo_bridge}
return proto_map.get(self['family'], self.hex)
class ifinfo(nla):
prefix = 'IFLA_INFO_'
nla_map = (
('IFLA_INFO_UNSPEC', 'none'),
('IFLA_INFO_KIND', 'asciiz'),
('IFLA_INFO_DATA', 'info_data'),
('IFLA_INFO_XSTATS', 'hex'),
('IFLA_INFO_SLAVE_KIND', 'asciiz'),
('IFLA_INFO_SLAVE_DATA', 'info_slave_data'),
)
@staticmethod
def info_slave_data(self, *argv, **kwarg):
'''
Return IFLA_INFO_SLAVE_DATA type based on
IFLA_INFO_SLAVE_KIND or IFLA_INFO_KIND.
'''
kind = self.get_attr('IFLA_INFO_SLAVE_KIND')
if kind is None:
kind = self.get_attr('IFLA_INFO_KIND')
data_map = {
'bridge': self.bridge_slave_data,
'bridge_slave': self.bridge_slave_data,
'bond': self.bond_slave_data,
}
return data_map.get(kind, self.hex)
class bridge_slave_data(protinfo_bridge):
pass
class bond_slave_data(nla):
nla_map = (
('IFLA_BOND_SLAVE_UNSPEC', 'none'),
('IFLA_BOND_SLAVE_STATE', 'uint8'),
('IFLA_BOND_SLAVE_MII_STATUS', 'uint8'),
('IFLA_BOND_SLAVE_LINK_FAILURE_COUNT', 'uint32'),
('IFLA_BOND_SLAVE_PERM_HWADDR', 'l2addr'),
('IFLA_BOND_SLAVE_QUEUE_ID', 'uint16'),
('IFLA_BOND_SLAVE_AD_AGGREGATOR_ID', 'uint16'),
)
@staticmethod
def info_data(self, *argv, **kwarg):
'''
The function returns appropriate IFLA_INFO_DATA
type according to IFLA_INFO_KIND info. Return
'hex' type for all unknown kind's and when the
kind is not known.
'''
kind = self.get_attr('IFLA_INFO_KIND')
return self.data_map.get(kind, self.hex)
class veth_data(nla):
nla_map = (
('VETH_INFO_UNSPEC', 'none'),
('VETH_INFO_PEER', 'info_peer'),
)
@staticmethod
def info_peer(self, *argv, **kwarg):
return ifinfveth
class ipip_data(iptnl_data):
pass
class sit_data(iptnl_data):
nla_map = [
(x[0].replace('IPIP', 'SIT'), x[1]) for x in iptnl_data.nla_map
]
class ip6tnl_data(nla):
prefix = 'IFLA_'
nla_map = (
('IFLA_IP6TNL_UNSPEC', 'none'),
('IFLA_IP6TNL_LINK', 'uint32'),
('IFLA_IP6TNL_LOCAL', 'ip6addr'),
('IFLA_IP6TNL_REMOTE', 'ip6addr'),
('IFLA_IP6TNL_TTL', 'uint8'),
('IFLA_IP6TNL_TOS', 'uint8'),
('IFLA_IP6TNL_ENCAP_LIMIT', 'uint8'),
('IFLA_IP6TNL_FLOWINFO', 'be32'),
('IFLA_IP6TNL_FLAGS', 'uint32'),
('IFLA_IP6TNL_PROTO', 'uint8'),
('IFLA_IP6TNL_PMTUDISC', 'uint8'),
('IFLA_IP6TNL_6RD_PREFIX', 'ip6addr'),
('IFLA_IP6TNL_6RD_RELAY_PREFIX', 'ip4addr'),
('IFLA_IP6TNL_6RD_PREFIXLEN', 'uint16'),
('IFLA_IP6TNL_6RD_RELAY_PREFIXLEN', 'uint16'),
('IFLA_IP6TNL_ENCAP_TYPE', 'uint16'),
('IFLA_IP6TNL_ENCAP_FLAGS', 'uint16'),
('IFLA_IP6TNL_ENCAP_SPORT', 'be16'),
('IFLA_IP6TNL_ENCAP_DPORT', 'be16'),
('IFLA_IP6TNL_COLLECT_METADATA', 'flag'),
('IFLA_IP6TNL_FWMARK', 'uint32'),
)
class gre_data(nla):
prefix = 'IFLA_'
nla_map = (
('IFLA_GRE_UNSPEC', 'none'),
('IFLA_GRE_LINK', 'uint32'),
('IFLA_GRE_IFLAGS', 'gre_flags'),
('IFLA_GRE_OFLAGS', 'gre_flags'),
('IFLA_GRE_IKEY', 'be32'),
('IFLA_GRE_OKEY', 'be32'),
('IFLA_GRE_LOCAL', 'ip4addr'),
('IFLA_GRE_REMOTE', 'ip4addr'),
('IFLA_GRE_TTL', 'uint8'),
('IFLA_GRE_TOS', 'uint8'),
('IFLA_GRE_PMTUDISC', 'uint8'),
('IFLA_GRE_ENCAP_LIMIT', 'uint8'),
('IFLA_GRE_FLOWINFO', 'be32'),
('IFLA_GRE_FLAGS', 'uint32'),
('IFLA_GRE_ENCAP_TYPE', 'uint16'),
('IFLA_GRE_ENCAP_FLAGS', 'uint16'),
('IFLA_GRE_ENCAP_SPORT', 'be16'),
('IFLA_GRE_ENCAP_DPORT', 'be16'),
('IFLA_GRE_COLLECT_METADATA', 'flag'),
('IFLA_GRE_IGNORE_DF', 'uint8'),
('IFLA_GRE_FWMARK', 'uint32'),
)
class gre_flags(nla):
fields = [('value', '>H')]
sql_type = 'INTEGER'
def encode(self):
#
# for details see:
url = 'https://github.com/svinota/pyroute2/issues/531'
v = self.value
for flag in GRE_VALUES:
v &= ~flag
if v != 0:
log.warning(
'possibly incorrect GRE flags, ' 'see %s' % url
)
nla.encode(self)
class ip6gre_data(nla):
# Ostensibly the same as ip6gre_data except that local
# and remote are ipv6 addrs.
# As of Linux 4.8,IFLA_GRE_COLLECT_METADATA has not been
# implemented for IPv6.
# Linux uses the same enum names for v6 and v4 (in if_tunnel.h);
# Here we name them IFLA_IP6GRE_xxx instead to avoid conflicts
# with gre_data above.
prefix = 'IFLA_'
nla_map = (
('IFLA_IP6GRE_UNSPEC', 'none'),
('IFLA_IP6GRE_LINK', 'uint32'),
('IFLA_IP6GRE_IFLAGS', 'uint16'),
('IFLA_IP6GRE_OFLAGS', 'uint16'),
('IFLA_IP6GRE_IKEY', 'be32'),
('IFLA_IP6GRE_OKEY', 'be32'),
('IFLA_IP6GRE_LOCAL', 'ip6addr'),
('IFLA_IP6GRE_REMOTE', 'ip6addr'),
('IFLA_IP6GRE_TTL', 'uint8'),
('IFLA_IP6GRE_TOS', 'uint8'),
('IFLA_IP6GRE_PMTUDISC', 'uint8'),
('IFLA_IP6GRE_ENCAP_LIMIT', 'uint8'),
('IFLA_IP6GRE_FLOWINFO', 'be32'),
('IFLA_IP6GRE_FLAGS', 'uint32'),
('IFLA_IP6GRE_ENCAP_TYPE', 'uint16'),
('IFLA_IP6GRE_ENCAP_FLAGS', 'uint16'),
('IFLA_IP6GRE_ENCAP_SPORT', 'be16'),
('IFLA_IP6GRE_ENCAP_DPORT', 'be16'),
)
class macvlan_data(macvx_data):
pass
class macvtap_data(macvx_data):
nla_map = [
(x[0].replace('MACVLAN', 'MACVTAP'), x[1])
for x in macvx_data.nla_map
]
class bridge_data(nla):
prefix = 'IFLA_'
nla_map = (
('IFLA_BR_UNSPEC', 'none'),
('IFLA_BR_FORWARD_DELAY', 'uint32'),
('IFLA_BR_HELLO_TIME', 'uint32'),
('IFLA_BR_MAX_AGE', 'uint32'),
('IFLA_BR_AGEING_TIME', 'uint32'),
('IFLA_BR_STP_STATE', 'uint32'),
('IFLA_BR_PRIORITY', 'uint16'),
('IFLA_BR_VLAN_FILTERING', 'uint8'),
('IFLA_BR_VLAN_PROTOCOL', 'be16'),
('IFLA_BR_GROUP_FWD_MASK', 'uint16'),
('IFLA_BR_ROOT_ID', 'br_id'),
('IFLA_BR_BRIDGE_ID', 'br_id'),
('IFLA_BR_ROOT_PORT', 'uint16'),
('IFLA_BR_ROOT_PATH_COST', 'uint32'),
('IFLA_BR_TOPOLOGY_CHANGE', 'uint8'),
('IFLA_BR_TOPOLOGY_CHANGE_DETECTED', 'uint8'),
('IFLA_BR_HELLO_TIMER', 'uint64'),
('IFLA_BR_TCN_TIMER', 'uint64'),
('IFLA_BR_TOPOLOGY_CHANGE_TIMER', 'uint64'),
('IFLA_BR_GC_TIMER', 'uint64'),
('IFLA_BR_GROUP_ADDR', 'l2addr'),
('IFLA_BR_FDB_FLUSH', 'flag'),
('IFLA_BR_MCAST_ROUTER', 'uint8'),
('IFLA_BR_MCAST_SNOOPING', 'uint8'),
('IFLA_BR_MCAST_QUERY_USE_IFADDR', 'uint8'),
('IFLA_BR_MCAST_QUERIER', 'uint8'),
('IFLA_BR_MCAST_HASH_ELASTICITY', 'uint32'),
('IFLA_BR_MCAST_HASH_MAX', 'uint32'),
('IFLA_BR_MCAST_LAST_MEMBER_CNT', 'uint32'),
('IFLA_BR_MCAST_STARTUP_QUERY_CNT', 'uint32'),
('IFLA_BR_MCAST_LAST_MEMBER_INTVL', 'uint64'),
('IFLA_BR_MCAST_MEMBERSHIP_INTVL', 'uint64'),
('IFLA_BR_MCAST_QUERIER_INTVL', 'uint64'),
('IFLA_BR_MCAST_QUERY_INTVL', 'uint64'),
('IFLA_BR_MCAST_QUERY_RESPONSE_INTVL', 'uint64'),
('IFLA_BR_MCAST_STARTUP_QUERY_INTVL', 'uint64'),
('IFLA_BR_NF_CALL_IPTABLES', 'uint8'),
('IFLA_BR_NF_CALL_IP6TABLES', 'uint8'),
('IFLA_BR_NF_CALL_ARPTABLES', 'uint8'),
('IFLA_BR_VLAN_DEFAULT_PVID', 'uint16'),
('IFLA_BR_PAD', 'uint64'),
('IFLA_BR_VLAN_STATS_ENABLED', 'uint8'),
('IFLA_BR_MCAST_STATS_ENABLED', 'uint8'),
('IFLA_BR_MCAST_IGMP_VERSION', 'uint8'),
('IFLA_BR_MCAST_MLD_VERSION', 'uint8'),
)
class br_id(ifla_bridge_id):
pass
# IFLA_INFO_DATA plugin system prototype
data_map = {
'macvlan': macvlan_data,
'macvtap': macvtap_data,
'ipip': ipip_data,
'sit': sit_data,
'ip6tnl': ip6tnl_data,
'gre': gre_data,
'gretap': gre_data,
'ip6gre': ip6gre_data,
'ip6gretap': ip6gre_data,
'veth': veth_data,
'bridge': bridge_data,
'bridge_slave': bridge_slave_data,
}
# expand supported interface types
data_map.update(data_plugins)
@classmethod
def register_link_kind(cls, path=None, pkg=None, module=None):
cls.data_map.update(data_plugins)
if path is not None:
cls.data_map.update(load_plugins_by_path(path))
elif pkg is not None:
cls.data_map.update(load_plugins_by_pkg(pkg))
elif module is not None:
for name, link_class in module.items():
cls.data_map[name] = link_class
else:
raise TypeError('path or pkg required')
@classmethod
def unregister_link_kind(cls, kind):
return cls.data_map.pop(kind)
@classmethod
def list_link_kind(cls):
return cls.data_map
sql_extend = ((ifinfo, 'IFLA_LINKINFO'), (xdp, 'IFLA_XDP'))
@staticmethod
def af_spec(self, *argv, **kwarg):
specs = {
0: self.af_spec_inet,
AF_INET: self.af_spec_inet,
AF_INET6: self.af_spec_inet,
AF_BRIDGE: self.af_spec_bridge,
}
return specs.get(self['family'], self.hex)
class af_spec_bridge(nla):
prefix = 'IFLA_BRIDGE_'
# Bug-Url: https://github.com/svinota/pyroute2/issues/284
# resolve conflict with link()/flags
# IFLA_BRIDGE_FLAGS is for compatibility, in nla dicts
# IFLA_BRIDGE_VLAN_FLAGS overrides it
nla_map = (
(0, 'IFLA_BRIDGE_FLAGS', 'uint16'),
(0, 'IFLA_BRIDGE_VLAN_FLAGS', 'vlan_flags'),
(1, 'IFLA_BRIDGE_MODE', 'uint16'),
(2, 'IFLA_BRIDGE_VLAN_INFO', 'vlan_info'),
(3, 'IFLA_BRIDGE_VLAN_TUNNEL_INFO', 'vlan_tunnel_info'),
)
class vlan_flags(nla):
fields = [('value', 'H')]
def encode(self):
# convert flags
if isinstance(self['value'], basestring):
self['value'] = BRIDGE_FLAGS_NAMES[
'BRIDGE_FLAGS_' + self['value'].upper()
]
nla.encode(self)
class vlan_info(nla):
prefix = ''
fields = (('flags', 'H'), ('vid', 'H'))
@staticmethod
def flags2names(flags):
ret = []
for flag in BRIDGE_VLAN_VALUES:
if (flag & flags) == flag:
ret.append(BRIDGE_VLAN_VALUES[flag])
return ret
@staticmethod
def names2flags(flags):
ret = 0
for flag in flags:
ret |= BRIDGE_VLAN_NAMES[
'BRIDGE_VLAN_INFO_' + flag.upper()
]
return ret
def encode(self):
# convert flags
if isinstance(self['flags'], (set, tuple, list)):
self['flags'] = self.names2flags(self['flags'])
return super(nla, self).encode()
class vlan_tunnel_info(nla):
prefix = 'IFLA_BRIDGE_VLAN_TUNNEL_'
nla_map = (
('IFLA_BRIDGE_VLAN_TUNNEL_UNSPEC', 'none'),
('IFLA_BRIDGE_VLAN_TUNNEL_ID', 'uint32'),
('IFLA_BRIDGE_VLAN_TUNNEL_VID', 'uint16'),
('IFLA_BRIDGE_VLAN_TUNNEL_FLAGS', 'uint16'),
)
class af_spec_inet(nla):
nla_map = (
('AF_UNSPEC', 'none'),
('AF_UNIX', 'hex'),
('AF_INET', 'inet'),
('AF_AX25', 'hex'),
('AF_IPX', 'hex'),
('AF_APPLETALK', 'hex'),
('AF_NETROM', 'hex'),
('AF_BRIDGE', 'hex'),
('AF_ATMPVC', 'hex'),
('AF_X25', 'hex'),
('AF_INET6', 'inet6'),
)
class inet(nla):
# ./include/linux/inetdevice.h: struct ipv4_devconf
# ./include/uapi/linux/ip.h
field_names = (
'dummy',
'forwarding',
'mc_forwarding',
'proxy_arp',
'accept_redirects',
'secure_redirects',
'send_redirects',
'shared_media',
'rp_filter',
'accept_source_route',
'bootp_relay',
'log_martians',
'tag',
'arpfilter',
'medium_id',
'noxfrm',
'nopolicy',
'force_igmp_version',
'arp_announce',
'arp_ignore',
'promote_secondaries',
'arp_accept',
'arp_notify',
'accept_local',
'src_vmark',
'proxy_arp_pvlan',
'route_localnet',
'igmpv2_unsolicited_report_interval',
'igmpv3_unsolicited_report_interval',
)
fields = [(i, 'I') for i in field_names]
class inet6(nla):
prefix = 'IFLA_'
nla_map = (
('IFLA_INET6_UNSPEC', 'none'),
('IFLA_INET6_FLAGS', 'uint32'),
('IFLA_INET6_CONF', 'ipv6_devconf'),
('IFLA_INET6_STATS', 'ipv6_stats'),
('IFLA_INET6_MCAST', 'hex'),
('IFLA_INET6_CACHEINFO', 'ipv6_cache_info'),
('IFLA_INET6_ICMP6STATS', 'icmp6_stats'),
('IFLA_INET6_TOKEN', 'ip6addr'),
('IFLA_INET6_ADDR_GEN_MODE', 'uint8'),
)
class ipv6_devconf(nla):
# ./include/uapi/linux/ipv6.h
# DEVCONF_
field_names = (
'forwarding',
'hop_limit',
'mtu',
'accept_ra',
'accept_redirects',
'autoconf',
'dad_transmits',
'router_solicitations',
'router_solicitation_interval',
'router_solicitation_delay',
'use_tempaddr',
'temp_valid_lft',
'temp_preferred_lft',
'regen_max_retry',
'max_desync_factor',
'max_addresses',
'force_mld_version',
'accept_ra_defrtr',
'accept_ra_pinfo',
'accept_ra_rtr_pref',
'router_probe_interval',
'accept_ra_rt_info_max_plen',
'proxy_ndp',
'optimistic_dad',
'accept_source_route',
'mc_forwarding',
'disable_ipv6',
'accept_dad',
'force_tllao',
'ndisc_notify',
)
fields = [(i, 'I') for i in field_names]
class ipv6_cache_info(nla):
# ./include/uapi/linux/if_link.h: struct ifla_cacheinfo
fields = (
('max_reasm_len', 'I'),
('tstamp', 'I'),
('reachable_time', 'I'),
('retrans_time', 'I'),
)
class ipv6_stats(nla):
# ./include/uapi/linux/snmp.h
field_names = (
'num',
'inpkts',
'inoctets',
'indelivers',
'outforwdatagrams',
'outpkts',
'outoctets',
'inhdrerrors',
'intoobigerrors',
'innoroutes',
'inaddrerrors',
'inunknownprotos',
'intruncatedpkts',
'indiscards',
'outdiscards',
'outnoroutes',
'reasmtimeout',
'reasmreqds',
'reasmoks',
'reasmfails',
'fragoks',
'fragfails',
'fragcreates',
'inmcastpkts',
'outmcastpkts',
'inbcastpkts',
'outbcastpkts',
'inmcastoctets',
'outmcastoctets',
'inbcastoctets',
'outbcastoctets',
'csumerrors',
'noectpkts',
'ect1pkts',
'ect0pkts',
'cepkts',
)
fields = [(i, 'Q') for i in field_names]
class icmp6_stats(nla):
# ./include/uapi/linux/snmp.h
field_names = (
'num',
'inmsgs',
'inerrors',
'outmsgs',
'outerrors',
'csumerrors',
)
fields = [(i, 'Q') for i in field_names]
class ifinfmsg(ifinfbase, nlmsg):
def decode(self):
nlmsg.decode(self)
if self['flags'] & 1:
self['state'] = 'up'
else:
self['state'] = 'down'
class ifinfveth(ifinfbase, nla):
pass
Zerion Mini Shell 1.0