import re
import time
import itertools
-from collections import Counter
+from collections import OrderedDict, Counter
try:
from ifupdown2.lib.addon import Bridge
vxlan_name = ifaceobj.name
try:
self.iproute2.batch_start()
- for bridge_vlan_vni_map_entry in ifaceobj.get_attr_value("bridge-vlan-vni-map"):
+ bridge_vlan_tunnel_info_running_config = self.iproute2.bridge_vlan_tunnel_show(vxlan_name)
+ all_user_config = OrderedDict()
+
+ for bridge_vlan_vni_map_entry in ifaceobj.get_attr_value("bridge-vlan-vni-map"):
if not bridge_vlan_vni_map_entry:
continue
except:
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)
- self.iproute2.bridge_vlan_add_vlan_tunnel_info(vxlan_name, vlans_str, vni_str)
+ # we need to convert vlan_str and vni_str back to a map {vlan: vni}
+ for vlan, vni in zip(utils.ranges_to_ints([vlans_str]), utils.ranges_to_ints([vni_str])):
+ all_user_config[vlan] = vni
+
+ vlan_vni_to_remove = OrderedDict()
+ for k, v in set(bridge_vlan_tunnel_info_running_config.items()) - set(all_user_config.items()):
+ vlan_vni_to_remove[k] = v
+
+ vlan_vni_to_add = OrderedDict()
+ for k, v in set(all_user_config.items()) - set(bridge_vlan_tunnel_info_running_config.items()):
+ vlan_vni_to_add[k] = v
+
+ # convert back to ranges to reduce the number of bridge commands
+ for (start_vlan, end_vlan), (start_vni, end_vni) in zip(utils.ints_to_ranges(vlan_vni_to_remove.keys()), utils.ints_to_ranges(vlan_vni_to_remove.values())):
+ vlan_str = ("%s-%s" % (start_vlan, end_vlan)) if start_vlan != end_vlan else start_vlan
+ vni_str = ("%s-%s" % (start_vni, end_vni)) if start_vni != end_vni else start_vni
+ self.iproute2.bridge_vlan_del_vid_list_self(vxlan_name, [vlans_str], False)
+ self.iproute2.bridge_vlan_del_vlan_tunnel_info(vxlan_name, vlan_str, vni_str)
+
+ for (start_vlan, end_vlan), (start_vni, end_vni) in zip(utils.ints_to_ranges(vlan_vni_to_add.keys()), utils.ints_to_ranges(vlan_vni_to_add.values())):
+ vlan_str = ("%s-%s" % (start_vlan, end_vlan)) if start_vlan != end_vlan else start_vlan
+ vni_str = ("%s-%s" % (start_vni, end_vni)) if start_vni != end_vni else start_vni
+ self.iproute2.bridge_vlan_add_vid_list_self(vxlan_name, [vlans_str], False)
+ self.iproute2.bridge_vlan_add_vlan_tunnel_info(vxlan_name, vlans_str, vni_str)
self.iproute2.batch_commit()
except Exception as e:
"vlan del vid %s dev %s %s" % (v, ifname, target)
)
+ def bridge_vlan_del_vlan_tunnel_info(self, ifname, vids, vnis):
+ self.__execute_or_batch(
+ utils.bridge_cmd,
+ "vlan del dev %s vid %s tunnel_info id %s" % (
+ ifname, vids, vnis
+ )
+ )
+
def bridge_vlan_add_vlan_tunnel_info(self, ifname, vids, vnis):
try:
self.__execute_or_batch(
if "exists" not in str(e).lower():
self.logger.error(e)
+ def bridge_vlan_tunnel_show(self, ifname):
+ tunnel_info = {}
+ try:
+ for entry in utils.exec_command("%s vlan tunnel dev %s" % (utils.bridge_cmd, ifname)).splitlines()[1:]:
+
+ if not entry:
+ continue
+
+ entry_list = entry.split()
+ length = len(entry_list)
+
+ if length > 2:
+ # if len == 3, we need to remove the ifname from the list
+ # $ bridge vlan tunnel show dev vxlan42
+ # port vlan ids tunnel id
+ # vxlan42 1042 1542
+ entry_list = entry_list[1:]
+
+ if length < 2:
+ continue
+
+ vnis = utils.ranges_to_ints([entry_list[0]])
+ tunnel_ids = utils.ranges_to_ints([entry_list[1]])
+
+ for vni, tunnel_id in zip(vnis, tunnel_ids):
+ tunnel_info[int(vni)] = int(tunnel_id)
+
+ except Exception as e:
+ self.logger.debug("iproute2: bridge vlan tunnel dev %s: %s" % (ifname, str(e)))
+ return tunnel_info
+
@staticmethod
def bridge_vlan_add_vid_list(ifname, vids):
for v in vids:
"vlan add vid %s dev %s %s" % (v, ifname, target)
)
+ def bridge_vlan_del_vid_list_self(self, ifname, vids, is_bridge=True):
+ target = "self" if is_bridge else ""
+ for v in vids:
+ self.__execute_or_batch(
+ utils.bridge_cmd,
+ "vlan del vid %s dev %s %s" % (v, ifname, target)
+ )
+
def bridge_vlan_del_pvid(self, ifname, pvid):
self.__execute_or_batch(
utils.bridge_cmd,