From 7f0310a7a584b69ab05f99e75c9c7fb6711cee4d Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 13 Apr 2021 20:47:02 -0700 Subject: [PATCH] bridge: support values of auto, auto+, auto- for vni in bridge-vlan-vni-map = =auto /* sets vni = vlan */ =auto+2 /* sets vni = vlan+2 */ =auto-2 /* sets vni = vlan-2 */ example: $ifquery vxlan1 auto vxlan1 iface vxlan1 vxlan-local-tunnelip 27.0.0.30 bridge-vlan-vni-map 1000-1009=auto+2 2000-2020=auto-2 mstpctl-portbpdufilter yes mstpctl-bpduguard yes $ifup -v vxlan1 ... info: executing /sbin/bridge -force -batch - [vlan add vid 1000-1009 dev vxlan1 vlan add dev vxlan1 vid 1000-1009 tunnel_info id 1002-1011 vlan add vid 2000-2020 dev vxlan1 vlan add dev vxlan1 vid 2000-2020 tunnel_info id 1998-2018] ... changes include: - supporting the new syntax - moved vlan vni map handling into a utility function to be used by bridge tunnel_info and vxlan vnifilter Reviewed by: slaffer, david marshal, qzil, julien Signed-off-by: Roopa Prabhu Signed-off-by: Julien Fortin --- ifupdown2/addons/bridge.py | 11 ++++-- ifupdown2/addons/vxlan.py | 8 +++- ifupdown2/ifupdown/utils.py | 74 +++++++++++++++++++++++++++++++++++++ ifupdown2/lib/iproute2.py | 2 +- 4 files changed, 88 insertions(+), 7 deletions(-) diff --git a/ifupdown2/addons/bridge.py b/ifupdown2/addons/bridge.py index 8c670e2..426a5ad 100644 --- a/ifupdown2/addons/bridge.py +++ b/ifupdown2/addons/bridge.py @@ -2367,11 +2367,11 @@ class bridge(Bridge, moduleBase): if not bridge_vlan_vni_map_entry: continue - for vlan_vni_map in bridge_vlan_vni_map_entry.split(): + for vlan_vni_map_entry in bridge_vlan_vni_map_entry.split(): try: - vlans_str, vni_str = vlan_vni_map.split("=") + vlans_str, vni_str = utils.get_vlan_vni_in_map_entry(vlan_vni_map_entry) except: - return self.__warn_bridge_vlan_vni_map_syntax_error(vxlan_name, vlan_vni_map) + return self.__warn_bridge_vlan_vni_map_syntax_error(vxlan_name, vlan_vni_map_entry) # TODO: query the cache prio to executing those commands self.iproute2.bridge_vlan_add_vid_list_self(vxlan_name, [vlans_str], False) @@ -3367,6 +3367,9 @@ class bridge(Bridge, moduleBase): def _query_check_bridge_port_vidinfo(self, ifname, bridge_name, ifaceobj, ifaceobjcurr, ifaceobj_getfunc): running_pvid, running_vids = self.cache.get_pvid_and_vids(ifname) + if (ifaceobj.link_privflags & ifaceLinkPrivFlags.SINGLE_VXLAN): + return + # # bridge-access # @@ -3591,7 +3594,7 @@ class bridge(Bridge, moduleBase): for vlan_vni in bridge_vlan_vni_map_entry.split(): try: - vlans_str, vni_str = vlan_vni.split("=") + vlans_str, vni_str = utils.get_vlan_vni_in_map_entry(vlan_vni) except: fail = True diff --git a/ifupdown2/addons/vxlan.py b/ifupdown2/addons/vxlan.py index e5be386..163a63f 100644 --- a/ifupdown2/addons/vxlan.py +++ b/ifupdown2/addons/vxlan.py @@ -927,8 +927,12 @@ class vxlan(Addon, moduleBase): def single_vxlan_device_vni_filter(self, ifaceobj): vnis = [] for vlan_vni_map in ifaceobj.get_attr_value("bridge-vlan-vni-map"): - for ventry in vlan_vni_map.split(): - vnis.extend([ventry.split('=')[1]]) + try: + (vls, vis) = utils.get_vlan_vnis_in_map(vlan_vni_map) + vnis.extend(vis) + except Exception as e: + self.logger.error("%s: %s (%s)" %(ifaceobj.name, vlan_vni_map, str(e))) + return self.iproute2.bridge_link_update_vni_filter(ifaceobj.name, vnis) def _up(self, ifaceobj): diff --git a/ifupdown2/ifupdown/utils.py b/ifupdown2/ifupdown/utils.py index 9c375a9..1256182 100644 --- a/ifupdown2/ifupdown/utils.py +++ b/ifupdown2/ifupdown/utils.py @@ -41,6 +41,8 @@ class utils(): DEVNULL = open(os.devnull, 'w') vlan_aware_bridge_address_support = None + vni_max = 16777215 + _string_values = { "on": True, "yes": True, @@ -479,4 +481,76 @@ class utils(): else: return True + @classmethod + def get_vlan_vni_in_map_entry(cls, vlan_vni_map_entry): + # a good example for map is bridge-vlan-vni-map attribute + # format eg: = + # 1000-1004=5000-5004 + # 1000-1004=auto /* here vni = vlan */ + # 1000-1004=auto-10 /* here vni = vlan - 10 */ + # 1000-1004=auto+10 /* here vni = vlan + 10 */ + + vlan = None + vni = None + try: + (vlan, vni) = vlan_vni_map_entry.split('=', 1) + if vni == 'auto': + vni = vlan + elif vni.startswith('auto'): + vnistart = 0 + vniend = 0 + if vni.startswith('auto+'): + vni = vni.split('+', 1)[1] + vint = int(vni) + if vint < 0: + raise Exception("invalid auto vni suffix %d" % (vint)) + if '-' in vlan: + (vstart, vend) = vlan.split('-', 1) + vnistart = int(vstart) + vint + vniend = int(vend) + vint + else: + vnistart = int(vlan) + vint + elif vni.startswith('auto-'): + vni = vni.split('-', 1)[1] + vint = int(vni) + if vint < 0: + raise Exception("invalid auto vni suffix %d" % (vint)) + if '-' in vlan: + (vstart, vend) = vlan.split('-', 1) + vnistart = int(vstart) - vint + vniend = int(vend) - vint + else: + vnistart = int(vlan) - vint + if (vnistart <= 0 or (vniend > 0 and (vniend < vnistart)) or + (vnistart > cls.vni_max) or (vniend > cls.vni_max)): + raise Exception("invalid vni - unable to derive auto vni %s" % (vni)) + if vniend > 0: + vni = '%d-%d' % (vnistart, vniend) + else: + vni = '%d' % (vnistart) + except Exception as e: + raise Exception(str(e)) + return + return (vlan, vni) + + @classmethod + def get_vlan_vnis_in_map(cls, vlan_vni_map): + # a good example for map is bridge-vlan-vni-map attribute + # format eg: = + # 1000-1004=5000-5004 + # 1000-1004=auto /* here vni = vlan */ + # 1000-1004=auto-10 /* here vni = vlan - 10 */ + # 1000-1004=auto+10 /* here vni = vlan + 10 */ + vnis = [] + vlans = [] + for ventry in vlan_vni_map.split(): + try: + (vlan, vni) = cls.get_vlan_vni_in_map_entry(ventry) + except Exception as e: + cls.logger.error("invalid vlan vni map entry - %s (%s)" % (ventry, str(e))) + raise + vlans.extend([vlan]) + vnis.extend([vni]) + return (vlans, vnis) + fcntl.fcntl(utils.DEVNULL, fcntl.F_SETFD, fcntl.FD_CLOEXEC) diff --git a/ifupdown2/lib/iproute2.py b/ifupdown2/lib/iproute2.py index 9b8a922..25d668f 100644 --- a/ifupdown2/lib/iproute2.py +++ b/ifupdown2/lib/iproute2.py @@ -865,7 +865,7 @@ class IPRoute2(Cache, Requirements): if vend: rvnis.extend(['%s-%s' %(vstart,vend)]) else: - rvnis.extend([vstart]) + rvnis.extend([str(vstart)]) vnis_int = utils.ranges_to_ints(vnis) rvnis_int = utils.ranges_to_ints(rvnis) (vnis_to_del, vnis_to_add) = utils.diff_ids(vnis_int,