1
0
mirror of https://github.com/CumulusNetworks/ifupdown2.git synced 2024-05-06 15:54:50 +00:00

add support for single vxlan device (bridge-vlan-vni-map)

new attribute:

"bridge-vlan-vni-map": {
    "help": "Single vxlan support",
    "example": "bridge-vlan-vni-map 1000-1001=1000-1001",
}

example of config:

auto bridge
iface bridge
      bridge-vlan-aware yes
      bridge-ports vxlan0 swp1
      bridge-stp on
      bridge-vids 1000-1001
      bridge-pvid 1

auto vxlan0
iface vxlan0
      vxlan-local-tunnelip 27.0.0.9
      bridge-learning off
      # vlan 1000-1001 maps to vni 1000-1001
      bridge-vlan-vni-map 1000-1001=1000-1001

Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
This commit is contained in:
Julien Fortin
2020-05-14 02:16:47 +02:00
parent 7840bd2c09
commit e537a6e6d6
7 changed files with 368 additions and 33 deletions

1
debian/changelog vendored
View File

@@ -3,6 +3,7 @@ ifupdown2 (3.0.1-1) unstable; urgency=medium
* New. Enabled: bridge-always-up attribute
* New. Enabled: ES bond with "es-sys-mac" attribute
* New. Enabled: dhcp policy: dhclient_retry_on_failure
* New. Enabled: bridge-vlan-vni-map attribute (single vxlan device)
* Fix: start-networking script is back to handle mgmt & hotplug cases
-- Julien Fortin <julien@cumulusnetworks.com> Tue, 14 Apr 2020 23:42:42 +0200

View File

@@ -441,6 +441,10 @@ class bridge(Addon, moduleBase):
"required": False,
"example": ["bridge-ports-condone-regex ^[a-zA-Z0-9]+_v[0-9]{1,4}$"]
},
"bridge-vlan-vni-map": {
"help": "Single vxlan support",
"example": "bridge-vlan-vni-map 1000-1001=1000-1001",
},
"bridge-always-up": {
"help": "Enabling this attribute on a bridge will enslave a dummy interface to the bridge",
"required": False,
@@ -917,8 +921,7 @@ class bridge(Addon, moduleBase):
def syntax_check_vxlan_in_vlan_aware_br(self, ifaceobj, ifaceobj_getfunc):
if not ifaceobj_getfunc:
return True
if (ifaceobj.link_kind & ifaceLinkKind.VXLAN
and ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT):
if (ifaceobj.link_kind & ifaceLinkKind.VXLAN and ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT):
if ifaceobj.get_attr_value('bridge-access'):
return True
for iface in ifaceobj.upperifaces if ifaceobj.upperifaces else []:
@@ -1555,7 +1558,7 @@ class bridge(Addon, moduleBase):
because kernel does honor vid info flags during deletes.
"""
if not isbridge and bportifaceobj.link_kind & ifaceLinkKind.VXLAN:
if not isbridge and (bportifaceobj.link_kind & ifaceLinkKind.VXLAN and not bportifaceobj.link_privflags & ifaceLinkPrivFlags.SINGLE_VXLAN):
if not vids or not pvid or len(vids) > 1 or vids[0] != pvid:
self._error_vxlan_in_vlan_aware_br(bportifaceobj,
bportifaceobj.upperifaces[0])
@@ -1628,6 +1631,9 @@ class bridge(Addon, moduleBase):
if vids_to_del:
if pvid_to_add in vids_to_del:
vids_to_del.remove(pvid_to_add)
vids_to_del = self.remove_bridge_vlans_mapped_to_vnis_from_vids_list(None, bportifaceobj, vids_to_del)
self.iproute2.bridge_vlan_del_vid_list_self(bportifaceobj.name,
self._compress_into_ranges(
vids_to_del), isbridge)
@@ -1662,6 +1668,47 @@ class bridge(Addon, moduleBase):
%(bportifaceobj.name, pvid_to_add, str(e)),
bportifaceobj)
def get_bridge_vlans_mapped_to_vnis_as_integer_list(self, ifaceobj):
"""
Get all vlans that the user wants to configured in vlan-vni maps
"""
try:
vids = []
for vlans_vnis_map in ifaceobj.get_attr_value("bridge-vlan-vni-map"):
vids.extend(self._ranges_to_ints([vlans_vnis_map.split("=")[0]]))
return vids
except Exception as e:
self.logger.debug("get_bridge_vlans_mapped_to_vnis_as_integer_list: %s" % str(e))
return []
def remove_bridge_vlans_mapped_to_vnis_from_vids_list(self, bridge_ifaceobj, vxlan_ifaceobj, vids_list):
"""
For single vxlan we need to remove the vlans mapped to vnis
from the vids list otherwise they will get removed from the brport
"""
if not (vxlan_ifaceobj.link_privflags & ifaceLinkPrivFlags.SINGLE_VXLAN):
return vids_list
user_config_vids = []
if bridge_ifaceobj:
for vid in self.get_bridge_vlans_mapped_to_vnis_as_integer_list(bridge_ifaceobj):
user_config_vids.append(vid)
if vxlan_ifaceobj:
for vid in self.get_bridge_vlans_mapped_to_vnis_as_integer_list(vxlan_ifaceobj):
user_config_vids.append(vid)
for vlan in user_config_vids:
try:
vids_list.remove(vlan)
except:
pass
return vids_list
def _apply_bridge_vlan_aware_port_settings_all(self, bportifaceobj,
bridge_vids=None,
bridge_pvid=None):
@@ -1916,6 +1963,7 @@ class bridge(Addon, moduleBase):
def up_apply_brports_attributes(self, ifaceobj, ifaceobj_getfunc, bridge_vlan_aware, target_ports=[], newly_enslaved_ports=[]):
ifname = ifaceobj.name
single_vxlan_device_ifaceobj = None
try:
brports_ifla_info_slave_data = dict()
@@ -2221,8 +2269,19 @@ class bridge(Addon, moduleBase):
pass
#
# SINGLE VXLAN - enable IFLA_BRPORT_VLAN_TUNNEL
#
#
if brport_ifaceobj.link_privflags & ifaceLinkPrivFlags.SINGLE_VXLAN:
single_vxlan_device_ifaceobj = brport_ifaceobj
brport_vlan_tunnel_cached_value = self.cache.get_link_info_slave_data_attribute(
brport_name,
Link.IFLA_BRPORT_VLAN_TUNNEL
)
if not brport_vlan_tunnel_cached_value:
self.logger.info("%s: %s: enabling vlan_tunnel on single vxlan device" % (ifname, brport_name))
brport_ifla_info_slave_data[Link.IFLA_BRPORT_VLAN_TUNNEL] = 1
else:
kind = None
@@ -2244,6 +2303,41 @@ class bridge(Addon, moduleBase):
except Exception as e:
self.log_error(str(e), ifaceobj)
if single_vxlan_device_ifaceobj:
self.apply_bridge_port_vlan_vni_map(single_vxlan_device_ifaceobj)
def apply_bridge_port_vlan_vni_map(self, ifaceobj):
"""
bridge vlan add vid <vlan-id> dev vxlan0
bridge vlan add dev vxlan0 vid <vlan-id> tunnel_info id <vni>
"""
vxlan_name = ifaceobj.name
try:
self.iproute2.batch_start()
for vlan_vni_map in ifaceobj.get_attr_value("bridge-vlan-vni-map"):
try:
vlans_str, vni_str = vlan_vni_map.split("=")
except:
return self.__warn_bridge_vlan_vni_map_syntax_error(vlan_vni_map)
vlans = self._ranges_to_ints([vlans_str])
vnis = self._ranges_to_ints([vni_str])
if len(vlans) != len(vnis):
return self.__warn_bridge_vlan_vni_map_syntax_error(vlan_vni_map)
# TODO: query the cache prio to executing those commands
self.iproute2.bridge_vlan_add_vid_list_self(vxlan_name, vlans, False)
self.iproute2.bridge_vlan_add_vlan_tunnel_info(vxlan_name, vlans, vnis)
self.iproute2.batch_commit()
except Exception as e:
self.log_error("%s: error while processing bridge-vlan-vni-map attribute: %s" % (vxlan_name, str(e)))
def __warn_bridge_vlan_vni_map_syntax_error(self, user_config_vlan_vni_map):
self.logger.warning("%s: syntax error: bridge-vlan-vni-map %s" % user_config_vlan_vni_map)
def is_qinq_bridge(self, ifaceobj, brport_name, running_brports, brport_ifaceobj_dict, ifaceobj_getfunc):
""" Detect QinQ bridge
Potential improvement: We could add a ifaceobj.link_privflags called
@@ -3259,6 +3353,21 @@ class bridge(Addon, moduleBase):
attr_name, vids = self.get_ifaceobj_bridge_vids(ifaceobj)
if vids:
vids = re.split(r'[\s\t]\s*', vids)
# Special treatment to make sure that the vlans mapped with vnis
# (in single-vxlan context) are not mistaken for regular vlans.
# We need to proactively remove them from the "running_vids"
vlans_mapped_with_vnis = self.get_bridge_vlans_mapped_to_vnis_as_integer_list(ifaceobj)
new_running_vids = []
user_config_vids = self._ranges_to_ints(vids)
for v in running_vids:
if v in user_config_vids:
new_running_vids.append(v)
elif v not in vlans_mapped_with_vnis:
new_running_vids.append(v)
running_vids = new_running_vids
#####################################################################
if not running_vids or not self._compare_vids(vids, running_vids, running_pvid, expand_range=False):
running_vids = [str(o) for o in running_vids]
ifaceobjcurr.update_config_with_status(attr_name,
@@ -3401,6 +3510,85 @@ class bridge(Addon, moduleBase):
self._query_check_l2protocol_tunnel_on_port(ifaceobj, ifaceobjcurr)
#
# bridge-vlan-vni-map
#
fail = False
cached_vlans, cached_vnis = self.get_vlan_vni_ranges(self.cache.get_vlan_vni(ifaceobj.name))
for bridge_vlan_vni_map in ifaceobj.get_attr_value("bridge-vlan-vni-map"):
if fail:
ifaceobjcurr.update_config_with_status("bridge-vlan-vni-map", bridge_vlan_vni_map, 1)
continue
try:
vlans_str, vni_str = bridge_vlan_vni_map.split("=")
except:
ifaceobjcurr.update_config_with_status("bridge-vlan-vni-map", bridge_vlan_vni_map, 1)
return self.__warn_bridge_vlan_vni_map_syntax_error(bridge_vlan_vni_map)
vlans_list = self._ranges_to_ints([vlans_str]) # self.bridge_vlan_vni_map_convert_user_config_to_set(vlans_str)
vnis_list = self._ranges_to_ints([vni_str]) #self.bridge_vlan_vni_map_convert_user_config_to_set(vni_str)
# since there can be multiple entry of bridge-vlan-vni-map
# we could simply check that all vlans and vnis are correctly
# set on the vxlan but we would probably miss the case where extra
# vlans and vnis were added. So we ned to keep a copy of the cache
# entry and pop vlans and svis from the cache copy as we iterate
# through the user config. After processing only extra vlans and
# vnis should be left.
try:
for vlan in vlans_list:
cached_vlans.remove(vlan)
except:
ifaceobjcurr.update_config_with_status("bridge-vlan-vni-map", bridge_vlan_vni_map, 1)
fail = True
continue
try:
for vni in vnis_list:
cached_vnis.remove(vni)
except:
ifaceobjcurr.update_config_with_status("bridge-vlan-vni-map", bridge_vlan_vni_map, 1)
fail = True
continue
ifaceobjcurr.update_config_with_status("bridge-vlan-vni-map", bridge_vlan_vni_map, 0)
if not fail and (cached_vlans or cached_vnis):
# cached_vlans and cached_vnis are not empty, it means more
# vlans-vni maps were configured on the bridge port
ifaceobjcurr.update_config_with_status(
"bridge-vlan-vni-map",
"%s=%s" % (cached_vlans, cached_vnis),
1
)
@staticmethod
def get_vlan_vni_ranges(bridge_vlan_tunnel):
vlans = []
vnis = []
tunnel_vlan_range = None
tunnel_vni_range = None
for tunnel_vlan, tunnel_vni, tunnel_flags in bridge_vlan_tunnel:
if tunnel_flags & Link.BRIDGE_VLAN_INFO_RANGE_BEGIN:
tunnel_vlan_range = tunnel_vlan
tunnel_vni_range = tunnel_vni
elif tunnel_flags & Link.BRIDGE_VLAN_INFO_RANGE_END:
vlans.extend(range(tunnel_vlan_range, tunnel_vlan + 1))
vnis.extend(range(tunnel_vni_range, tunnel_vni + 1))
else:
vlans.append(tunnel_vlan)
vnis.append(tunnel_vni)
return vlans, vnis
def _query_check_l2protocol_tunnel_on_port(self, ifaceobj, ifaceobjcurr):
user_config_l2protocol_tunnel = ifaceobj.get_attr_value_first('bridge-l2protocol-tunnel')

View File

@@ -156,6 +156,9 @@ class vxlan(Addon, moduleBase):
return True
def get_dependent_ifacenames(self, ifaceobj, ifaceobjs_all=None):
if ifaceobj.get_attr_value_first("bridge-vlan-vni-map"):
ifaceobj.link_privflags |= ifaceLinkPrivFlags.SINGLE_VXLAN
if self._is_vxlan_device(ifaceobj):
ifaceobj.link_kind |= ifaceLinkKind.VXLAN
self._set_global_local_ip(ifaceobj)
@@ -191,7 +194,10 @@ class vxlan(Addon, moduleBase):
@staticmethod
def _is_vxlan_device(ifaceobj):
return ifaceobj.link_kind & ifaceLinkKind.VXLAN or ifaceobj.get_attr_value_first('vxlan-id')
return ifaceobj.link_kind & ifaceLinkKind.VXLAN \
or ifaceobj.link_privflags & ifaceLinkPrivFlags.SINGLE_VXLAN \
or ifaceobj.get_attr_value_first("vxlan-id") \
or ifaceobj.get_attr_value_first("bridge-vlan-vni-map")
def __get_vlxan_purge_remotes(self, ifaceobj):
if not ifaceobj:
@@ -609,7 +615,8 @@ class vxlan(Addon, moduleBase):
def _up(self, ifaceobj):
vxlan_id_str = ifaceobj.get_attr_value_first("vxlan-id")
if not vxlan_id_str:
if not ifaceobj.link_privflags & ifaceLinkPrivFlags.SINGLE_VXLAN and not vxlan_id_str:
self.logger.warning("%s: missing vxlan-id attribute on vxlan device" % ifaceobj.name)
return
ifname = ifaceobj.name
@@ -634,7 +641,10 @@ class vxlan(Addon, moduleBase):
user_request_vxlan_info_data = {}
self.__config_vxlan_id(ifname, ifaceobj, vxlan_id_str, user_request_vxlan_info_data, cached_vxlan_ifla_info_data)
if vxlan_id_str:
# for single vxlan device we don't have a vxlan-id
self.__config_vxlan_id(ifname, ifaceobj, vxlan_id_str, user_request_vxlan_info_data, cached_vxlan_ifla_info_data)
self.__config_vxlan_learning(ifaceobj, link_exists, user_request_vxlan_info_data, cached_vxlan_ifla_info_data)
self.__config_vxlan_ageing(ifname, ifaceobj, link_exists, user_request_vxlan_info_data, cached_vxlan_ifla_info_data)
self.__config_vxlan_port(ifname, ifaceobj, link_exists, user_request_vxlan_info_data, cached_vxlan_ifla_info_data)
@@ -674,20 +684,30 @@ class vxlan(Addon, moduleBase):
# element: vxlan-id
self.logger.info('%s: vxlan already exists - no change detected' % ifname)
else:
try:
if flap_vxlan_device:
self.netlink.link_down_force(ifname)
self.netlink.link_add_vxlan_with_info_data(ifname, user_request_vxlan_info_data)
if flap_vxlan_device:
self.netlink.link_up_force(ifname)
except Exception as e:
if ifaceobj.link_privflags & ifaceLinkPrivFlags.SINGLE_VXLAN:
if link_exists:
self.log_error("%s: applying vxlan change failed: %s" % (ifname, str(e)), ifaceobj)
self.logger.warning("%s: updating existing single vxlan device is not support yet" % ifname)
else:
self.log_error("%s: vxlan creation failed: %s" % (ifname, str(e)), ifaceobj)
return
self.iproute2.link_add_single_vxlan(
ifname,
local,
user_request_vxlan_info_data.get(Link.IFLA_VXLAN_PORT)
)
else:
try:
if flap_vxlan_device:
self.netlink.link_down_force(ifname)
self.netlink.link_add_vxlan_with_info_data(ifname, user_request_vxlan_info_data)
if flap_vxlan_device:
self.netlink.link_up_force(ifname)
except Exception as e:
if link_exists:
self.log_error("%s: applying vxlan change failed: %s" % (ifname, str(e)), ifaceobj)
else:
self.log_error("%s: vxlan creation failed: %s" % (ifname, str(e)), ifaceobj)
return
vxlan_purge_remotes = self.__get_vlxan_purge_remotes(ifaceobj)

View File

@@ -79,6 +79,7 @@ class ifaceLinkKind():
class ifaceLinkPrivFlags():
""" This corresponds to kernel netdev->priv_flags
and can be BRIDGE_PORT, BOND_SLAVE etc """
UNKNOWN = 0x00000
BRIDGE_PORT = 0x00001
BOND_SLAVE = 0x00010
@@ -89,7 +90,8 @@ class ifaceLinkPrivFlags():
LOOPBACK = 0x1000000
KEEP_LINK_DOWN = 0x10000000
MGMT_INTF = 0x100000000
ES_BOND = 0x1000000000
SINGLE_VXLAN = 0x1000000000
ES_BOND = 0x10000000000
@classmethod
def get_str(cls, flag):

View File

@@ -269,6 +269,20 @@ class IPRoute2(Cache, Requirements):
###
def link_add_single_vxlan(self, ifname, ip, port):
self.logger.info("creating single vxlan device: %s" % ifname)
cmd = ["link add dev %s type vxlan external" % ifname]
if ip:
cmd.append("local %s" % ip)
if port:
cmd.append("dstport %s" % port)
self.__execute_or_batch(utils.ip_cmd, " ".join(cmd))
self.__update_cache_after_link_creation(ifname, "vxlan")
def link_create_vxlan(self, name, vxlanid, localtunnelip=None, svcnodeip=None,
remoteips=None, learning='on', ageing=None, ttl=None, physdev=None):
if svcnodeip and remoteips:
@@ -583,12 +597,18 @@ class IPRoute2(Cache, Requirements):
"vlan del vid %s dev %s %s" % (v, ifname, target)
)
@staticmethod
def bridge_vlan_add_vid_list(ifname, vids):
for v in vids:
utils.exec_command(
"%s vlan add vid %s dev %s" % (utils.bridge_cmd, v, ifname)
)
def bridge_vlan_add_vlan_tunnel_info(self, ifname, vids, vnis):
for i in range(0, len(vids)):
try:
self.__execute_or_batch(
utils.bridge_cmd,
"vlan add dev %s vid %s tunnel_info id %s" % (
ifname, vids[i], vnis[i]
)
)
except Exception as e:
if "exists" not in str(e).lower():
self.logger.error(e)
def bridge_vlan_add_vid_list_self(self, ifname, vids, is_bridge=True):
target = "self" if is_bridge else ""

View File

@@ -161,6 +161,7 @@ class _NetlinkCache:
self._link_cache = {}
self._addr_cache = {}
self._bridge_vlan_cache = {}
self._bridge_vlan_vni_cache = {}
# helper dictionaries
# ifindex: ifname
@@ -306,6 +307,11 @@ class _NetlinkCache:
except KeyError:
pass
try:
del self._bridge_vlan_vni_cache[slave]
except KeyError:
pass
def append_to_ignore_rtm_newlinkq(self, ifname):
"""
Register device 'ifname' to the ignore_rtm_newlinkq list pending
@@ -1022,6 +1028,10 @@ class _NetlinkCache:
except (KeyError, AttributeError):
return 0
def get_vlan_vni(self, ifname):
with self._cache_lock:
return self._bridge_vlan_vni_cache.get(ifname)
def get_pvid_and_vids(self, ifname):
"""
vlan-identifiers are stored in:
@@ -1352,6 +1362,7 @@ class _NetlinkCache:
"""
vlans_list = []
# Todo: acquire the lock only when really needed
with self._cache_lock:
ifla_af_spec = msg.get_attribute_value(Link.IFLA_AF_SPEC)
ifname = msg.get_attribute_value(Link.IFLA_IFNAME)
@@ -1385,6 +1396,9 @@ class _NetlinkCache:
# (flag, vlan) so that we can sort the list of tuples
vlans_list.append((vlan_id, vlan_flag))
elif x_type == Link.IFLA_BRIDGE_VLAN_TUNNEL_INFO:
self._bridge_vlan_vni_cache.update({ifname: x_value})
self._bridge_vlan_cache.update({ifname: vlans_list})
def force_add_slave(self, master, slave):
@@ -1516,6 +1530,11 @@ class _NetlinkCache:
except:
pass
try:
del self._bridge_vlan_vni_cache[ifname]
except:
pass
try:
del self._ifname_by_ifindex[ifindex]
except KeyError:

View File

@@ -1661,6 +1661,11 @@ class AttributeIFLA_AF_SPEC(Attribute):
{
Link.IFLA_BRIDGE_FLAGS: flags,
Link.IFLA_BRIDGE_VLAN_INFO: (vflags, vlanid)
Link.IFLA_BRIDGE_VLAN_TUNNEL_INFO: [
__u32 tunnel_id;
__u16 tunnel_vid;
__u16 tunnel_flags;
]
}
FROM: David Ahern
@@ -1722,6 +1727,13 @@ class AttributeIFLA_AF_SPEC(Attribute):
sub_attr_data = data[4:sub_attr_end]
if self.family == AF_BRIDGE:
# /* Bridge management nested attributes
# * [IFLA_AF_SPEC] = {
# * [IFLA_BRIDGE_FLAGS]
# * [IFLA_BRIDGE_MODE]
# * [IFLA_BRIDGE_VLAN_INFO]
# * }
# */
if sub_attr_type == Link.IFLA_BRIDGE_FLAGS:
self.value[Link.IFLA_BRIDGE_FLAGS] = unpack("=H", sub_attr_data[0:2])[0]
@@ -1730,6 +1742,38 @@ class AttributeIFLA_AF_SPEC(Attribute):
self.value[Link.IFLA_BRIDGE_VLAN_INFO] = []
self.value[Link.IFLA_BRIDGE_VLAN_INFO].append(tuple(unpack("=HH", sub_attr_data[0:4])))
elif sub_attr_type == Link.IFLA_BRIDGE_VLAN_TUNNEL_INFO:
# Link.IFLA_BRIDGE_VLAN_TUNNEL_INFO: {
# __u32 tunnel_id;
# __u16 tunnel_vid;
# __u16 tunnel_flags;
# }
# all the nested attributes are padded on 8 bytes
tunnel_id = 0
tunnel_vid = 0
tunnel_flags = 0
while sub_attr_data:
(s_sub_attr_length, s_sub_attr_type) = unpack("=HH", sub_attr_data[:4])
s_sub_attr_end = padded_length(s_sub_attr_length)
d = sub_attr_data[4:s_sub_attr_end]
if s_sub_attr_type == Link.IFLA_BRIDGE_VLAN_TUNNEL_ID:
tunnel_id = unpack("=L", d)[0]
elif s_sub_attr_type == Link.IFLA_BRIDGE_VLAN_TUNNEL_VID:
tunnel_vid = unpack("=L", d)[0]
elif s_sub_attr_type == Link.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS:
tunnel_flags = unpack("=L", d)[0]
sub_attr_data = sub_attr_data[s_sub_attr_end:]
if Link.IFLA_BRIDGE_VLAN_TUNNEL_INFO not in self.value:
self.value[Link.IFLA_BRIDGE_VLAN_TUNNEL_INFO] = []
self.value[Link.IFLA_BRIDGE_VLAN_TUNNEL_INFO].append((tunnel_id, tunnel_vid, tunnel_flags))
else:
self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for decoding IFLA_AF_SPEC sub-attribute '
'type %s (%d), length %d, padded to %d' %
@@ -4291,15 +4335,38 @@ class Link(NetlinkPacket, NetlinkPacket_IFLA_LINKINFO_Attributes):
IFLA_INET_CONF : 'IFLA_INET_CONF',
}
# /* Bridge Flags */
BRIDGE_FLAGS_MASTER = 1 # /* Bridge command to/from master */
BRIDGE_FLAGS_SELF = 2 # /* Bridge command to/from lowerdev */
bridge_flags_to_string = {
BRIDGE_FLAGS_MASTER : "BRIDGE_FLAGS_MASTER",
BRIDGE_FLAGS_SELF : "BRIDGE_FLAGS_SELF"
}
BRIDGE_MODE_VEB = 0 # /* Default loopback mode */
BRIDGE_MODE_VEPA = 1 # /* 802.1Qbg defined VEPA mode */
BRIDGE_MODE_UNDEF = 0xFFFF # /* mode undefined */
# /* Bridge management nested attributes
# * [IFLA_AF_SPEC] = {
# * [IFLA_BRIDGE_FLAGS]
# * [IFLA_BRIDGE_MODE]
# * [IFLA_BRIDGE_VLAN_INFO]
# * }
# */
# BRIDGE IFLA_AF_SPEC attributes
IFLA_BRIDGE_FLAGS = 0
IFLA_BRIDGE_MODE = 1
IFLA_BRIDGE_VLAN_INFO = 2
IFLA_BRIDGE_VLAN_TUNNEL_INFO = 3
ifla_bridge_af_spec_to_string = {
IFLA_BRIDGE_FLAGS : 'IFLA_BRIDGE_FLAGS',
IFLA_BRIDGE_MODE : 'IFLA_BRIDGE_MODE',
IFLA_BRIDGE_VLAN_INFO : 'IFLA_BRIDGE_VLAN_INFO'
IFLA_BRIDGE_VLAN_INFO : 'IFLA_BRIDGE_VLAN_INFO',
IFLA_BRIDGE_VLAN_TUNNEL_INFO : "IFLA_BRIDGE_VLAN_TUNNEL_INFO"
}
# BRIDGE_VLAN_INFO flags
@@ -4319,15 +4386,33 @@ class Link(NetlinkPacket, NetlinkPacket_IFLA_LINKINFO_Attributes):
BRIDGE_VLAN_INFO_BRENTRY : 'BRIDGE_VLAN_INFO_BRENTRY'
}
# Bridge flags
BRIDGE_FLAGS_MASTER = 1
BRIDGE_FLAGS_SELF = 2
# struct bridge_vlan_info {
# __u16 flags;
# __u16 vid;
# };
bridge_flags_to_string = {
BRIDGE_FLAGS_MASTER : 'BRIDGE_FLAGS_MASTER',
BRIDGE_FLAGS_SELF : 'BRIDGE_FLAGS_SELF'
IFLA_BRIDGE_VLAN_TUNNEL_UNSPEC = 0
IFLA_BRIDGE_VLAN_TUNNEL_ID = 1
IFLA_BRIDGE_VLAN_TUNNEL_VID = 2
IFLA_BRIDGE_VLAN_TUNNEL_FLAGS = 3
bridge_vlan_tunnel_to_string = {
IFLA_BRIDGE_VLAN_TUNNEL_UNSPEC: "IFLA_BRIDGE_VLAN_TUNNEL_UNSPEC",
IFLA_BRIDGE_VLAN_TUNNEL_ID: "IFLA_BRIDGE_VLAN_TUNNEL_ID",
IFLA_BRIDGE_VLAN_TUNNEL_VID: "IFLA_BRIDGE_VLAN_TUNNEL_VID",
IFLA_BRIDGE_VLAN_TUNNEL_FLAGS: "IFLA_BRIDGE_VLAN_TUNNEL_FLAGS",
}
# struct bridge_vlan_xstats {
# __u64 rx_bytes;
# __u64 rx_packets;
# __u64 tx_bytes;
# __u64 tx_packets;
# __u16 vid;
# __u16 flags;
# __u32 pad2;
# };
# filters for IFLA_EXT_MASK
RTEXT_FILTER_VF = 1 << 0
RTEXT_FILTER_BRVLAN = 1 << 1