Files
freebsd/tests/atf_python/sys/netlink/netlink_route.py
T
Kevin Bowling 2019f3d86f rtnetlink: Add native SR-IOV VF status
Add a transport neutral kernel snapshot for NIC-specific SR-IOV VF
status and an optional iflib provider method.  Providers gather state
under driver defined synchronization.

Honor RTEXT_FILTER_VF on RTM_GETLINK requests and encode the status as
native typed route Netlink attributes.  Represent VFs, driver
namespaces, and namespace fields as directly repeated nested attributes.
Presence masks in consumers can distinguish omission from false or zero.

Drivers may add custom status under stable, versioned namespaces.  The
named, typed representation lets generic transports and consumers carry
or display fields without knowing their driver-specific schemas, while
the driver retains ownership of their names and meanings.

Document the ABI and add parser and RTM_GETLINK coverage.

Reviewed by:	melifaro, iflib (gallatin), kgalazka (previous version)
Sponsored by:	BBOX.io
Differential Revision:	https://reviews.freebsd.org/D58776
2026-09-06 06:51:52 -07:00

955 lines
26 KiB
Python

import socket
import struct
from ctypes import c_int
from ctypes import c_ubyte
from ctypes import c_uint
from ctypes import c_ushort
from ctypes import sizeof
from ctypes import Structure
from enum import auto
from enum import Enum
from atf_python.sys.netlink.attrs import NlAttr
from atf_python.sys.netlink.attrs import NlAttrIp
from atf_python.sys.netlink.attrs import NlAttrNested
from atf_python.sys.netlink.attrs import NlAttrStr
from atf_python.sys.netlink.attrs import NlAttrU16
from atf_python.sys.netlink.attrs import NlAttrU32
from atf_python.sys.netlink.attrs import NlAttrU64
from atf_python.sys.netlink.attrs import NlAttrU8
from atf_python.sys.netlink.message import StdNetlinkMessage
from atf_python.sys.netlink.message import NlMsgProps
from atf_python.sys.netlink.message import NlMsgCategory
from atf_python.sys.netlink.utils import AttrDescr
from atf_python.sys.netlink.utils import get_bitmask_str
from atf_python.sys.netlink.utils import prepare_attrs_map
class RtattrType(Enum):
RTA_UNSPEC = 0
RTA_DST = 1
RTA_SRC = 2
RTA_IIF = 3
RTA_OIF = 4
RTA_GATEWAY = 5
RTA_PRIORITY = 6
RTA_PREFSRC = 7
RTA_METRICS = 8
RTA_MULTIPATH = 9
# RTA_PROTOINFO = 10
RTA_KNH_ID = 10
RTA_FLOW = 11
RTA_CACHEINFO = 12
RTA_SESSION = 13
# RTA_MP_ALGO = 14
RTA_RTFLAGS = 14
RTA_TABLE = 15
RTA_MARK = 16
RTA_MFC_STATS = 17
RTA_VIA = 18
RTA_NEWDST = 19
RTA_PREF = 20
RTA_ENCAP_TYPE = 21
RTA_ENCAP = 22
RTA_EXPIRES = 23
RTA_PAD = 24
RTA_UID = 25
RTA_TTL_PROPAGATE = 26
RTA_IP_PROTO = 27
RTA_SPORT = 28
RTA_DPORT = 29
RTA_NH_ID = 30
class NlRtMsgType(Enum):
RTM_NEWLINK = 16
RTM_DELLINK = 17
RTM_GETLINK = 18
RTM_SETLINK = 19
RTM_NEWADDR = 20
RTM_DELADDR = 21
RTM_GETADDR = 22
RTM_NEWROUTE = 24
RTM_DELROUTE = 25
RTM_GETROUTE = 26
RTM_NEWNEIGH = 28
RTM_DELNEIGH = 29
RTM_GETNEIGH = 30
RTM_NEWRULE = 32
RTM_DELRULE = 33
RTM_GETRULE = 34
RTM_NEWQDISC = 36
RTM_DELQDISC = 37
RTM_GETQDISC = 38
RTM_NEWTCLASS = 40
RTM_DELTCLASS = 41
RTM_GETTCLASS = 42
RTM_NEWTFILTER = 44
RTM_DELTFILTER = 45
RTM_GETTFILTER = 46
RTM_NEWACTION = 48
RTM_DELACTION = 49
RTM_GETACTION = 50
RTM_NEWPREFIX = 52
RTM_GETMULTICAST = 58
RTM_GETANYCAST = 62
RTM_NEWNEIGHTBL = 64
RTM_GETNEIGHTBL = 66
RTM_SETNEIGHTBL = 67
RTM_NEWNDUSEROPT = 68
RTM_NEWADDRLABEL = 72
RTM_DELADDRLABEL = 73
RTM_GETADDRLABEL = 74
RTM_GETDCB = 78
RTM_SETDCB = 79
RTM_NEWNETCONF = 80
RTM_GETNETCONF = 82
RTM_NEWMDB = 84
RTM_DELMDB = 85
RTM_GETMDB = 86
RTM_NEWNSID = 88
RTM_DELNSID = 89
RTM_GETNSID = 90
RTM_NEWSTATS = 92
RTM_GETSTATS = 94
class RtAttr(Structure):
_fields_ = [
("rta_len", c_ushort),
("rta_type", c_ushort),
]
class RtMsgHdr(Structure):
_fields_ = [
("rtm_family", c_ubyte),
("rtm_dst_len", c_ubyte),
("rtm_src_len", c_ubyte),
("rtm_tos", c_ubyte),
("rtm_table", c_ubyte),
("rtm_protocol", c_ubyte),
("rtm_scope", c_ubyte),
("rtm_type", c_ubyte),
("rtm_flags", c_uint),
]
class RtMsgFlags(Enum):
RTM_F_NOTIFY = 0x100
RTM_F_CLONED = 0x200
RTM_F_EQUALIZE = 0x400
RTM_F_PREFIX = 0x800
RTM_F_LOOKUP_TABLE = 0x1000
RTM_F_FIB_MATCH = 0x2000
RTM_F_OFFLOAD = 0x4000
RTM_F_TRAP = 0x8000
RTM_F_OFFLOAD_FAILED = 0x20000000
class RtScope(Enum):
RT_SCOPE_UNIVERSE = 0
RT_SCOPE_SITE = 200
RT_SCOPE_LINK = 253
RT_SCOPE_HOST = 254
RT_SCOPE_NOWHERE = 255
class RtType(Enum):
RTN_UNSPEC = 0
RTN_UNICAST = auto()
RTN_LOCAL = auto()
RTN_BROADCAST = auto()
RTN_ANYCAST = auto()
RTN_MULTICAST = auto()
RTN_BLACKHOLE = auto()
RTN_UNREACHABLE = auto()
RTN_PROHIBIT = auto()
RTN_THROW = auto()
RTN_NAT = auto()
RTN_XRESOLVE = auto()
class RtProto(Enum):
RTPROT_UNSPEC = 0
RTPROT_REDIRECT = 1
RTPROT_KERNEL = 2
RTPROT_BOOT = 3
RTPROT_STATIC = 4
RTPROT_GATED = 8
RTPROT_RA = 9
RTPROT_MRT = 10
RTPROT_ZEBRA = 11
RTPROT_BIRD = 12
RTPROT_DNROUTED = 13
RTPROT_XORP = 14
RTPROT_NTK = 15
RTPROT_DHCP = 16
RTPROT_MROUTED = 17
RTPROT_KEEPALIVED = 18
RTPROT_BABEL = 42
RTPROT_OPENR = 99
RTPROT_BGP = 186
RTPROT_ISIS = 187
RTPROT_OSPF = 188
RTPROT_RIP = 189
RTPROT_EIGRP = 192
class NlRtaxType(Enum):
RTAX_UNSPEC = 0
RTAX_LOCK = auto()
RTAX_MTU = auto()
RTAX_WINDOW = auto()
RTAX_RTT = auto()
RTAX_RTTVAR = auto()
RTAX_SSTHRESH = auto()
RTAX_CWND = auto()
RTAX_ADVMSS = auto()
RTAX_REORDERING = auto()
RTAX_HOPLIMIT = auto()
RTAX_INITCWND = auto()
RTAX_FEATURES = auto()
RTAX_RTO_MIN = auto()
RTAX_INITRWND = auto()
RTAX_QUICKACK = auto()
RTAX_CC_ALGO = auto()
RTAX_FASTOPEN_NO_COOKIE = auto()
class RtFlagsBSD(Enum):
RTF_UP = 0x1
RTF_GATEWAY = 0x2
RTF_HOST = 0x4
RTF_REJECT = 0x8
RTF_DYNAMIC = 0x10
RTF_MODIFIED = 0x20
RTF_DONE = 0x40
RTF_XRESOLVE = 0x200
RTF_LLINFO = 0x400
RTF_LLDATA = 0x400
RTF_STATIC = 0x800
RTF_BLACKHOLE = 0x1000
RTF_PROTO2 = 0x4000
RTF_PROTO1 = 0x8000
RTF_PROTO3 = 0x40000
RTF_FIXEDMTU = 0x80000
RTF_PINNED = 0x100000
RTF_LOCAL = 0x200000
RTF_BROADCAST = 0x400000
RTF_MULTICAST = 0x800000
RTF_STICKY = 0x10000000
RTF_RNH_LOCKED = 0x40000000
RTF_GWFLAG_COMPAT = 0x80000000
class NlRtGroup(Enum):
RTNLGRP_NONE = 0
RTNLGRP_LINK = auto()
RTNLGRP_NOTIFY = auto()
RTNLGRP_NEIGH = auto()
RTNLGRP_TC = auto()
RTNLGRP_IPV4_IFADDR = auto()
RTNLGRP_IPV4_MROUTE = auto()
RTNLGRP_IPV4_ROUTE = auto()
RTNLGRP_IPV4_RULE = auto()
RTNLGRP_IPV6_IFADDR = auto()
RTNLGRP_IPV6_MROUTE = auto()
RTNLGRP_IPV6_ROUTE = auto()
RTNLGRP_IPV6_IFINFO = auto()
RTNLGRP_DECnet_IFADDR = auto()
RTNLGRP_NOP2 = auto()
RTNLGRP_DECnet_ROUTE = auto()
RTNLGRP_DECnet_RULE = auto()
RTNLGRP_NOP4 = auto()
RTNLGRP_IPV6_PREFIX = auto()
RTNLGRP_IPV6_RULE = auto()
RTNLGRP_ND_USEROPT = auto()
RTNLGRP_PHONET_IFADDR = auto()
RTNLGRP_PHONET_ROUTE = auto()
RTNLGRP_DCB = auto()
RTNLGRP_IPV4_NETCONF = auto()
RTNLGRP_IPV6_NETCONF = auto()
RTNLGRP_MDB = auto()
RTNLGRP_MPLS_ROUTE = auto()
RTNLGRP_NSID = auto()
RTNLGRP_MPLS_NETCONF = auto()
RTNLGRP_IPV4_MROUTE_R = auto()
RTNLGRP_IPV6_MROUTE_R = auto()
RTNLGRP_NEXTHOP = auto()
RTNLGRP_BRVLAN = auto()
class IfinfoMsg(Structure):
_fields_ = [
("ifi_family", c_ubyte),
("__ifi_pad", c_ubyte),
("ifi_type", c_ushort),
("ifi_index", c_int),
("ifi_flags", c_uint),
("ifi_change", c_uint),
]
class IflattrType(Enum):
IFLA_UNSPEC = 0
IFLA_ADDRESS = 1
IFLA_BROADCAST = 2
IFLA_IFNAME = 3
IFLA_MTU = 4
IFLA_LINK = 5
IFLA_QDISC = 6
IFLA_STATS = 7
IFLA_COST = 8
IFLA_PRIORITY = 9
IFLA_MASTER = 10
IFLA_WIRELESS = 11
IFLA_PROTINFO = 12
IFLA_TXQLEN = 13
IFLA_MAP = 14
IFLA_WEIGHT = 15
IFLA_OPERSTATE = 16
IFLA_LINKMODE = 17
IFLA_LINKINFO = 18
IFLA_NET_NS_PID = 19
IFLA_IFALIAS = 20
IFLA_NUM_VF = 21
IFLA_VFINFO_LIST = 22
IFLA_STATS64 = 23
IFLA_VF_PORTS = 24
IFLA_PORT_SELF = 25
IFLA_AF_SPEC = 26
IFLA_GROUP = 27
IFLA_NET_NS_FD = 28
IFLA_EXT_MASK = 29
IFLA_PROMISCUITY = 30
IFLA_NUM_TX_QUEUES = 31
IFLA_NUM_RX_QUEUES = 32
IFLA_CARRIER = 33
IFLA_PHYS_PORT_ID = 34
IFLA_CARRIER_CHANGES = 35
IFLA_PHYS_SWITCH_ID = 36
IFLA_LINK_NETNSID = 37
IFLA_PHYS_PORT_NAME = 38
IFLA_PROTO_DOWN = 39
IFLA_GSO_MAX_SEGS = 40
IFLA_GSO_MAX_SIZE = 41
IFLA_PAD = 42
IFLA_XDP = 43
IFLA_EVENT = 44
IFLA_NEW_NETNSID = 45
IFLA_IF_NETNSID = 46
IFLA_CARRIER_UP_COUNT = 47
IFLA_CARRIER_DOWN_COUNT = 48
IFLA_NEW_IFINDEX = 49
IFLA_MIN_MTU = 50
IFLA_MAX_MTU = 51
IFLA_PROP_LIST = 52
IFLA_ALT_IFNAME = 53
IFLA_PERM_ADDRESS = 54
IFLA_PROTO_DOWN_REASON = 55
IFLA_PARENT_DEV_NAME = 56
IFLA_PARENT_DEV_BUS_NAME = 57
IFLA_GRO_MAX_SIZE = 58
IFLA_TSO_MAX_SEGS = 59
IFLA_ALLMULTI = 60
IFLA_DEVLINK_PORT = 61
IFLA_GSO_IPV4_MAX_SIZE = 62
IFLA_GRO_IPV4_MAX_SIZE = 63
IFLA_FREEBSD = 64
IFLA_FREEBSD_VF = 65
class IflafAttrType(Enum):
IFLAF_UNSPEC = 0
IFLAF_ORIG_IFNAME = 1
IFLAF_ORIG_HWADDR = 2
IFLAF_CAPS = 3
IFLAF_VF_STATUS = 5
class IflafVfStatusType(Enum):
IFLAF_VFS_UNSPEC = 0
IFLAF_VFS_ERROR = 1
IFLAF_VFS_PF_LINK_STATE = 2
IFLAF_VFS_PF_LINK_SPEED = 3
class IflafVfType(Enum):
IFLAF_VF_UNSPEC = 0
IFLAF_VF_INDEX = 1
IFLAF_VF_CONFIGURED = 2
IFLAF_VF_INITIALIZED = 3
IFLAF_VF_MAC = 4
IFLAF_VF_VLAN_MODE = 5
IFLAF_VF_VLAN = 6
IFLAF_VF_VLAN_PCP = 7
IFLAF_VF_VLAN_PROTO = 8
IFLAF_VF_VLAN_COUNT = 9
IFLAF_VF_VLAN_LIMIT = 10
IFLAF_VF_NUM_TX_QUEUES = 11
IFLAF_VF_NUM_RX_QUEUES = 12
IFLAF_VF_MIN_TX_RATE = 13
IFLAF_VF_MAX_TX_RATE = 14
IFLAF_VF_ALLOW_SET_MAC = 15
IFLAF_VF_ALLOW_SET_VLAN = 16
IFLAF_VF_MAC_ANTI_SPOOF = 17
IFLAF_VF_ALLOW_PROMISC = 18
IFLAF_VF_TRAFFIC_ALLOWED = 19
IFLAF_VF_FAULT_BLOCKED = 20
IFLAF_VF_QUARANTINED = 21
IFLAF_VF_API_VERSION = 22
IFLAF_VF_LINK_STATE_POLICY = 23
IFLAF_VF_DRIVER = 24
class IflafVfDriverType(Enum):
IFLAF_VFD_UNSPEC = 0
IFLAF_VFD_NAME = 1
IFLAF_VFD_VERSION = 2
IFLAF_VFD_FIELD = 3
class IflafVfDriverFieldType(Enum):
IFLAF_VFDF_UNSPEC = 0
IFLAF_VFDF_NAME = 1
IFLAF_VFDF_BOOL = 2
IFLAF_VFDF_NUMBER = 3
IFLAF_VFDF_STRING = 4
IFLAF_VFDF_BINARY = 5
class IflinkInfo(Enum):
IFLA_INFO_UNSPEC = 0
IFLA_INFO_KIND = auto()
IFLA_INFO_DATA = auto()
IFLA_INFO_XSTATS = auto()
IFLA_INFO_SLAVE_KIND = auto()
IFLA_INFO_SLAVE_DATA = auto()
class IfLinkInfoDataVlan(Enum):
IFLA_VLAN_UNSPEC = 0
IFLA_VLAN_ID = auto()
IFLA_VLAN_FLAGS = auto()
IFLA_VLAN_EGRESS_QOS = auto()
IFLA_VLAN_INGRESS_QOS = auto()
IFLA_VLAN_PROTOCOL = auto()
class IfaddrMsg(Structure):
_fields_ = [
("ifa_family", c_ubyte),
("ifa_prefixlen", c_ubyte),
("ifa_flags", c_ubyte),
("ifa_scope", c_ubyte),
("ifa_index", c_uint),
]
class IfaAttrType(Enum):
IFA_UNSPEC = 0
IFA_ADDRESS = 1
IFA_LOCAL = 2
IFA_LABEL = 3
IFA_BROADCAST = 4
IFA_ANYCAST = 5
IFA_CACHEINFO = 6
IFA_MULTICAST = 7
IFA_FLAGS = 8
IFA_RT_PRIORITY = 9
IFA_TARGET_NETNSID = 10
IFA_FREEBSD = 11
class IfafAttrType(Enum):
IFAF_UNSPEC = 0
IFAF_VHID = 1
IFAF_FLAGS = 2
class IfaCacheInfo(Structure):
_fields_ = [
("ifa_prefered", c_uint), # seconds till the end of the prefix considered preferred
("ifa_valid", c_uint), # seconds till the end of the prefix considered valid
("cstamp", c_uint), # creation time in 1ms intervals from the boot time
("tstamp", c_uint), # update time in 1ms intervals from the boot time
]
class IfaFlags(Enum):
IFA_F_TEMPORARY = 0x01
IFA_F_NODAD = 0x02
IFA_F_OPTIMISTIC = 0x04
IFA_F_DADFAILED = 0x08
IFA_F_HOMEADDRESS = 0x10
IFA_F_DEPRECATED = 0x20
IFA_F_TENTATIVE = 0x40
IFA_F_PERMANENT = 0x80
IFA_F_MANAGETEMPADDR = 0x100
IFA_F_NOPREFIXROUTE = 0x200
IFA_F_MCAUTOJOIN = 0x400
IFA_F_STABLE_PRIVACY = 0x800
class IfafFlags6(Enum):
IN6_IFF_ANYCAST = 0x01
IN6_IFF_TENTATIVE = 0x02
IN6_IFF_DUPLICATED = 0x04
IN6_IFF_DETACHED = 0x08
IN6_IFF_DEPRECATED = 0x10
IN6_IFF_NODAD = 0x20
IN6_IFF_AUTOCONF = 0x40
IN6_IFF_TEMPORARY = 0x80
IN6_IFF_PREFER_SOURCE = 0x100
class NdMsg(Structure):
_fields_ = [
("ndm_family", c_ubyte),
("ndm_pad1", c_ubyte),
("ndm_pad2", c_ubyte),
("ndm_ifindex", c_uint),
("ndm_state", c_ushort),
("ndm_flags", c_ubyte),
("ndm_type", c_ubyte),
]
class NdAttrType(Enum):
NDA_UNSPEC = 0
NDA_DST = 1
NDA_LLADDR = 2
NDA_CACHEINFO = 3
NDA_PROBES = 4
NDA_VLAN = 5
NDA_PORT = 6
NDA_VNI = 7
NDA_IFINDEX = 8
NDA_MASTER = 9
NDA_LINK_NETNSID = 10
NDA_SRC_VNI = 11
NDA_PROTOCOL = 12
NDA_NH_ID = 13
NDA_FDB_EXT_ATTRS = 14
NDA_FLAGS_EXT = 15
NDA_NDM_STATE_MASK = 16
NDA_NDM_FLAGS_MASK = 17
class NlAttrRtFlags(NlAttrU32):
def _print_attr_value(self):
s = get_bitmask_str(RtFlagsBSD, self.u32)
return " rtflags={}".format(s)
class NlAttrIfindex(NlAttrU32):
def _print_attr_value(self):
try:
ifname = socket.if_indextoname(self.u32)
return " iface={}(#{})".format(ifname, self.u32)
except OSError:
pass
return " iface=if#{}".format(self.u32)
class NlAttrTable(NlAttrU32):
def _print_attr_value(self):
return " rtable={}".format(self.u32)
class NlAttrNhId(NlAttrU32):
def _print_attr_value(self):
return " nh_id={}".format(self.u32)
class NlAttrKNhId(NlAttrU32):
def _print_attr_value(self):
return " knh_id={}".format(self.u32)
class NlAttrMac(NlAttr):
def _print_attr_value(self):
return ' mac="' + ":".join(["{:02X}".format(b) for b in self._data]) + '"'
class NlAttrIfStats(NlAttr):
def _print_attr_value(self):
return " stats={...}"
class NlAttrCacheInfo(NlAttr):
def __init__(self, nla_type, data):
super().__init__(nla_type, data)
self.ci = IfaCacheInfo.from_buffer_copy(data)
@staticmethod
def _validate(data):
nla_len, nla_type = struct.unpack("@HH", data[:4])
data_len = nla_len - 4
if data_len != sizeof(IfaCacheInfo):
raise ValueError(
"Error validating attr {}: wrong size".format(nla_type)
) # noqa: E501
def _print_attr_value(self):
return " ifa_prefered={} ifa_valid={} cstamp={} tstamp={}".format(
self.ci.ifa_prefered, self.ci.ifa_valid, self.ci.cstamp, self.ci.tstamp)
class NlAttrVia(NlAttr):
def __init__(self, nla_type, family, addr: str):
super().__init__(nla_type, b"")
self.addr = addr
self.family = family
@staticmethod
def _validate(data):
nla_len, nla_type = struct.unpack("@HH", data[:4])
data_len = nla_len - 4
if data_len == 0:
raise ValueError(
"Error validating attr {}: empty data".format(nla_type)
) # noqa: E501
family = int(data_len[0])
if family not in (socket.AF_INET, socket.AF_INET6):
raise ValueError(
"Error validating attr {}: unsupported AF {}".format( # noqa: E501
nla_type, family
)
)
if family == socket.AF_INET:
expected_len = 1 + 4
else:
expected_len = 1 + 16
if data_len != expected_len:
raise ValueError(
"Error validating attr {}: expected len {} got {}".format( # noqa: E501
nla_type, expected_len, data_len
)
)
@property
def nla_len(self):
if self.family == socket.AF_INET6:
return 21
else:
return 9
@classmethod
def _parse(cls, data):
nla_len, nla_type, family = struct.unpack("@HHB", data[:5])
off = 5
if family == socket.AF_INET:
addr = socket.inet_ntop(family, data[off:off + 4])
else:
addr = socket.inet_ntop(family, data[off:off + 16])
return cls(nla_type, family, addr)
def __bytes__(self):
addr = socket.inet_pton(self.family, self.addr)
return self._to_bytes(struct.pack("@B", self.family) + addr)
def _print_attr_value(self):
return " via={}".format(self.addr)
rtnl_route_attrs = prepare_attrs_map(
[
AttrDescr(RtattrType.RTA_DST, NlAttrIp),
AttrDescr(RtattrType.RTA_SRC, NlAttrIp),
AttrDescr(RtattrType.RTA_IIF, NlAttrIfindex),
AttrDescr(RtattrType.RTA_OIF, NlAttrIfindex),
AttrDescr(RtattrType.RTA_GATEWAY, NlAttrIp),
AttrDescr(RtattrType.RTA_TABLE, NlAttrTable),
AttrDescr(RtattrType.RTA_PRIORITY, NlAttrU32),
AttrDescr(RtattrType.RTA_VIA, NlAttrVia),
AttrDescr(RtattrType.RTA_NH_ID, NlAttrNhId),
AttrDescr(RtattrType.RTA_KNH_ID, NlAttrKNhId),
AttrDescr(RtattrType.RTA_RTFLAGS, NlAttrRtFlags),
AttrDescr(
RtattrType.RTA_METRICS,
NlAttrNested,
[
AttrDescr(NlRtaxType.RTAX_MTU, NlAttrU32),
],
),
]
)
rtnl_iflaf_vf_driver_field_attrs = [
AttrDescr(IflafVfDriverFieldType.IFLAF_VFDF_NAME, NlAttrStr),
AttrDescr(IflafVfDriverFieldType.IFLAF_VFDF_BOOL, NlAttrU8),
AttrDescr(IflafVfDriverFieldType.IFLAF_VFDF_NUMBER, NlAttrU64),
AttrDescr(IflafVfDriverFieldType.IFLAF_VFDF_STRING, NlAttrStr),
AttrDescr(IflafVfDriverFieldType.IFLAF_VFDF_BINARY, NlAttr),
]
rtnl_iflaf_vf_driver_attrs = [
AttrDescr(IflafVfDriverType.IFLAF_VFD_NAME, NlAttrStr),
AttrDescr(IflafVfDriverType.IFLAF_VFD_VERSION, NlAttrU32),
AttrDescr(
IflafVfDriverType.IFLAF_VFD_FIELD,
NlAttrNested,
rtnl_iflaf_vf_driver_field_attrs,
),
]
rtnl_iflaf_vf_attrs = [
AttrDescr(IflafVfType.IFLAF_VF_INDEX, NlAttrU32),
AttrDescr(IflafVfType.IFLAF_VF_CONFIGURED, NlAttrU8),
AttrDescr(IflafVfType.IFLAF_VF_INITIALIZED, NlAttrU8),
AttrDescr(IflafVfType.IFLAF_VF_MAC, NlAttrMac),
AttrDescr(IflafVfType.IFLAF_VF_VLAN_MODE, NlAttrU8),
AttrDescr(IflafVfType.IFLAF_VF_VLAN, NlAttrU16),
AttrDescr(IflafVfType.IFLAF_VF_VLAN_PCP, NlAttrU8),
AttrDescr(IflafVfType.IFLAF_VF_VLAN_PROTO, NlAttrU16),
AttrDescr(IflafVfType.IFLAF_VF_VLAN_COUNT, NlAttrU32),
AttrDescr(IflafVfType.IFLAF_VF_VLAN_LIMIT, NlAttrU32),
AttrDescr(IflafVfType.IFLAF_VF_NUM_TX_QUEUES, NlAttrU16),
AttrDescr(IflafVfType.IFLAF_VF_NUM_RX_QUEUES, NlAttrU16),
AttrDescr(IflafVfType.IFLAF_VF_MIN_TX_RATE, NlAttrU64),
AttrDescr(IflafVfType.IFLAF_VF_MAX_TX_RATE, NlAttrU64),
AttrDescr(IflafVfType.IFLAF_VF_ALLOW_SET_MAC, NlAttrU8),
AttrDescr(IflafVfType.IFLAF_VF_ALLOW_SET_VLAN, NlAttrU8),
AttrDescr(IflafVfType.IFLAF_VF_MAC_ANTI_SPOOF, NlAttrU8),
AttrDescr(IflafVfType.IFLAF_VF_ALLOW_PROMISC, NlAttrU8),
AttrDescr(IflafVfType.IFLAF_VF_TRAFFIC_ALLOWED, NlAttrU8),
AttrDescr(IflafVfType.IFLAF_VF_FAULT_BLOCKED, NlAttrU8),
AttrDescr(IflafVfType.IFLAF_VF_QUARANTINED, NlAttrU8),
AttrDescr(IflafVfType.IFLAF_VF_API_VERSION, NlAttrStr),
AttrDescr(IflafVfType.IFLAF_VF_LINK_STATE_POLICY, NlAttrU8),
AttrDescr(
IflafVfType.IFLAF_VF_DRIVER,
NlAttrNested,
rtnl_iflaf_vf_driver_attrs,
),
]
rtnl_iflaf_vf_status_attrs = [
AttrDescr(IflafVfStatusType.IFLAF_VFS_ERROR, NlAttrU32),
AttrDescr(IflafVfStatusType.IFLAF_VFS_PF_LINK_STATE, NlAttrU8),
AttrDescr(IflafVfStatusType.IFLAF_VFS_PF_LINK_SPEED, NlAttrU64),
]
rtnl_ifla_attrs = prepare_attrs_map(
[
AttrDescr(IflattrType.IFLA_ADDRESS, NlAttrMac),
AttrDescr(IflattrType.IFLA_BROADCAST, NlAttrMac),
AttrDescr(IflattrType.IFLA_IFNAME, NlAttrStr),
AttrDescr(IflattrType.IFLA_MTU, NlAttrU32),
AttrDescr(IflattrType.IFLA_LINK, NlAttrU32),
AttrDescr(IflattrType.IFLA_PROMISCUITY, NlAttrU32),
AttrDescr(IflattrType.IFLA_OPERSTATE, NlAttrU8),
AttrDescr(IflattrType.IFLA_CARRIER, NlAttrU8),
AttrDescr(IflattrType.IFLA_IFALIAS, NlAttrStr),
AttrDescr(IflattrType.IFLA_NUM_VF, NlAttrU32),
AttrDescr(IflattrType.IFLA_STATS64, NlAttrIfStats),
AttrDescr(IflattrType.IFLA_NEW_IFINDEX, NlAttrU32),
AttrDescr(
IflattrType.IFLA_LINKINFO,
NlAttrNested,
[
AttrDescr(IflinkInfo.IFLA_INFO_KIND, NlAttrStr),
AttrDescr(IflinkInfo.IFLA_INFO_DATA, NlAttr),
],
),
AttrDescr(
IflattrType.IFLA_FREEBSD,
NlAttrNested,
[
AttrDescr(IflafAttrType.IFLAF_ORIG_HWADDR, NlAttrMac),
AttrDescr(
IflafAttrType.IFLAF_VF_STATUS,
NlAttrNested,
rtnl_iflaf_vf_status_attrs,
),
],
),
AttrDescr(
IflattrType.IFLA_FREEBSD_VF,
NlAttrNested,
rtnl_iflaf_vf_attrs,
),
]
)
rtnl_ifa_attrs = prepare_attrs_map(
[
AttrDescr(IfaAttrType.IFA_ADDRESS, NlAttrIp),
AttrDescr(IfaAttrType.IFA_LOCAL, NlAttrIp),
AttrDescr(IfaAttrType.IFA_LABEL, NlAttrStr),
AttrDescr(IfaAttrType.IFA_BROADCAST, NlAttrIp),
AttrDescr(IfaAttrType.IFA_ANYCAST, NlAttrIp),
AttrDescr(IfaAttrType.IFA_FLAGS, NlAttrU32),
AttrDescr(IfaAttrType.IFA_CACHEINFO, NlAttrCacheInfo),
AttrDescr(
IfaAttrType.IFA_FREEBSD,
NlAttrNested,
[
AttrDescr(IfafAttrType.IFAF_VHID, NlAttrU32),
AttrDescr(IfafAttrType.IFAF_FLAGS, NlAttrU32),
],
),
]
)
rtnl_nd_attrs = prepare_attrs_map(
[
AttrDescr(NdAttrType.NDA_DST, NlAttrIp),
AttrDescr(NdAttrType.NDA_IFINDEX, NlAttrIfindex),
AttrDescr(NdAttrType.NDA_FLAGS_EXT, NlAttrU32),
AttrDescr(NdAttrType.NDA_LLADDR, NlAttrMac),
]
)
class BaseNetlinkRtMessage(StdNetlinkMessage):
pass
class NetlinkRtMessage(BaseNetlinkRtMessage):
messages = [
NlMsgProps(NlRtMsgType.RTM_NEWROUTE, NlMsgCategory.NEW),
NlMsgProps(NlRtMsgType.RTM_DELROUTE, NlMsgCategory.DELETE),
NlMsgProps(NlRtMsgType.RTM_GETROUTE, NlMsgCategory.GET),
]
nl_attrs_map = rtnl_route_attrs
def __init__(self, helper, nlm_type):
super().__init__(helper, nlm_type)
self.base_hdr = RtMsgHdr()
def parse_base_header(self, data):
if len(data) < sizeof(RtMsgHdr):
raise ValueError("length less than rtmsg header")
rtm_hdr = RtMsgHdr.from_buffer_copy(data)
return (rtm_hdr, sizeof(RtMsgHdr))
def print_base_header(self, hdr, prepend=""):
family = self.helper.get_af_name(hdr.rtm_family)
print(
"{}family={}, dst_len={}, src_len={}, tos={}, table={}, protocol={}({}), scope={}({}), type={}({}), flags={}({})".format( # noqa: E501
prepend,
family,
hdr.rtm_dst_len,
hdr.rtm_src_len,
hdr.rtm_tos,
hdr.rtm_table,
self.helper.get_attr_byval(RtProto, hdr.rtm_protocol),
hdr.rtm_protocol,
self.helper.get_attr_byval(RtScope, hdr.rtm_scope),
hdr.rtm_scope,
self.helper.get_attr_byval(RtType, hdr.rtm_type),
hdr.rtm_type,
self.helper.get_bitmask_str(RtMsgFlags, hdr.rtm_flags),
hdr.rtm_flags,
)
)
class NetlinkIflaMessage(BaseNetlinkRtMessage):
messages = [
NlMsgProps(NlRtMsgType.RTM_NEWLINK, NlMsgCategory.NEW),
NlMsgProps(NlRtMsgType.RTM_DELLINK, NlMsgCategory.DELETE),
NlMsgProps(NlRtMsgType.RTM_GETLINK, NlMsgCategory.GET),
]
nl_attrs_map = rtnl_ifla_attrs
def __init__(self, helper, nlm_type):
super().__init__(helper, nlm_type)
self.base_hdr = IfinfoMsg()
def parse_base_header(self, data):
if len(data) < sizeof(IfinfoMsg):
raise ValueError("length less than IfinfoMsg header")
rtm_hdr = IfinfoMsg.from_buffer_copy(data)
return (rtm_hdr, sizeof(IfinfoMsg))
def print_base_header(self, hdr, prepend=""):
family = self.helper.get_af_name(hdr.ifi_family)
print(
"{}family={}, ifi_type={}, ifi_index={}, ifi_flags={}, ifi_change={}".format( # noqa: E501
prepend,
family,
hdr.ifi_type,
hdr.ifi_index,
hdr.ifi_flags,
hdr.ifi_change,
)
)
class NetlinkIfaMessage(BaseNetlinkRtMessage):
messages = [
NlMsgProps(NlRtMsgType.RTM_NEWADDR, NlMsgCategory.NEW),
NlMsgProps(NlRtMsgType.RTM_DELADDR, NlMsgCategory.DELETE),
NlMsgProps(NlRtMsgType.RTM_GETADDR, NlMsgCategory.GET),
]
nl_attrs_map = rtnl_ifa_attrs
def __init__(self, helper, nlm_type):
super().__init__(helper, nlm_type)
self.base_hdr = IfaddrMsg()
def parse_base_header(self, data):
if len(data) < sizeof(IfaddrMsg):
raise ValueError("length less than IfaddrMsg header")
rtm_hdr = IfaddrMsg.from_buffer_copy(data)
return (rtm_hdr, sizeof(IfaddrMsg))
def print_base_header(self, hdr, prepend=""):
family = self.helper.get_af_name(hdr.ifa_family)
print(
"{}family={}, ifa_prefixlen={}, ifa_flags={}, ifa_scope={}, ifa_index={}".format( # noqa: E501
prepend,
family,
hdr.ifa_prefixlen,
hdr.ifa_flags,
hdr.ifa_scope,
hdr.ifa_index,
)
)
class NetlinkNdMessage(BaseNetlinkRtMessage):
messages = [
NlMsgProps(NlRtMsgType.RTM_NEWNEIGH, NlMsgCategory.NEW),
NlMsgProps(NlRtMsgType.RTM_DELNEIGH, NlMsgCategory.DELETE),
NlMsgProps(NlRtMsgType.RTM_GETNEIGH, NlMsgCategory.GET),
]
nl_attrs_map = rtnl_nd_attrs
def __init__(self, helper, nlm_type):
super().__init__(helper, nlm_type)
self.base_hdr = NdMsg()
def parse_base_header(self, data):
if len(data) < sizeof(NdMsg):
raise ValueError("length less than NdMsg header")
nd_hdr = NdMsg.from_buffer_copy(data)
return (nd_hdr, sizeof(NdMsg))
def print_base_header(self, hdr, prepend=""):
family = self.helper.get_af_name(hdr.ndm_family)
print(
"{}family={}, ndm_ifindex={}, ndm_state={}, ndm_flags={}".format( # noqa: E501
prepend,
family,
hdr.ndm_ifindex,
hdr.ndm_state,
hdr.ndm_flags,
)
)
handler_classes = {
"netlink_route": [
NetlinkRtMessage,
NetlinkIflaMessage,
NetlinkIfaMessage,
NetlinkNdMessage,
],
}