* 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
"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,
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 []:
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])
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)
%(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):
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()
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
ifla_info_data = {}
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
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,
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')
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)
@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:
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
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)
# 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)
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
LOOPBACK = 0x1000000
KEEP_LINK_DOWN = 0x10000000
MGMT_INTF = 0x100000000
- ES_BOND = 0x1000000000
+ SINGLE_VXLAN = 0x1000000000
+ ES_BOND = 0x10000000000
@classmethod
def get_str(cls, flag):
###
+ 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:
"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 ""
self._link_cache = {}
self._addr_cache = {}
self._bridge_vlan_cache = {}
+ self._bridge_vlan_vni_cache = {}
# helper dictionaries
# ifindex: ifname
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
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:
"""
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)
# (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):
except:
pass
+ try:
+ del self._bridge_vlan_vni_cache[ifname]
+ except:
+ pass
+
try:
del self._ifname_by_ifindex[ifindex]
except KeyError:
{
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
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]
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' %
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
BRIDGE_VLAN_INFO_BRENTRY : 'BRIDGE_VLAN_INFO_BRENTRY'
}
- # Bridge flags
- BRIDGE_FLAGS_MASTER = 1
- BRIDGE_FLAGS_SELF = 2
-
- bridge_flags_to_string = {
- BRIDGE_FLAGS_MASTER : 'BRIDGE_FLAGS_MASTER',
- BRIDGE_FLAGS_SELF : 'BRIDGE_FLAGS_SELF'
+ # struct bridge_vlan_info {
+ # __u16 flags;
+ # __u16 vid;
+ # };
+
+ 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