def _check_addresses_in_bridge(self, ifaceobj, hwaddress): """ If the device is a bridge, make sure the addresses are in the bridge """ if ifaceobj.link_kind & ifaceLinkKind.VLAN: bridgename = ifaceobj.lowerifaces[0] vlan = self._get_vlan_id(ifaceobj) if self.cache.bridge_is_vlan_aware(bridgename): fdb_addrs = self._get_bridge_fdbs(bridgename, str(vlan)) if not fdb_addrs: return False hwaddress_int = utils.mac_str_to_int(hwaddress) for mac in fdb_addrs: if utils.mac_str_to_int(mac) == hwaddress_int: return True return False return True
def link_set_address(self, ifname, address): if utils.mac_str_to_int(address) != self.cache.get_link_address_raw( ifname): self.link_down(ifname) self.__execute_or_batch( utils.ip_cmd, "link set dev %s address %s" % (ifname, address)) self.link_up(ifname)
def link_set_address_and_keep_down(self, ifname, address, keep_down=False): if utils.mac_str_to_int(address) != self.cache.get_link_address_raw( ifname): self.link_down(ifname) self.__execute_or_batch( utils.ip_cmd, "link set dev %s address %s" % (ifname, address)) if not keep_down: self.link_up_force(ifname)
def _up(self, ifaceobj, ifaceobj_getfunc=None): try: link_exists, bond_slaves = self.create_or_set_bond_config(ifaceobj) bond_slaves = self._add_slaves( ifaceobj, bond_slaves, ifaceobj_getfunc, ) if not self.bond_mac_mgmt or not link_exists or ifaceobj.get_attr_value_first( "hwaddress"): return # check if the bond mac address is correctly inherited from it's # first slave. There's a case where that might not be happening: # $ ip link show swp1 | grep ether # link/ether 08:00:27:04:d8:01 brd ff:ff:ff:ff:ff:ff # $ ip link show swp2 | grep ether # link/ether 08:00:27:04:d8:02 brd ff:ff:ff:ff:ff:ff # $ ip link add dev bond0 type bond # $ ip link set dev swp1 master bond0 # $ ip link set dev swp2 master bond0 # $ ip link show bond0 | grep ether # link/ether 08:00:27:04:d8:01 brd ff:ff:ff:ff:ff:ff # $ ip link add dev bond1 type bond # $ ip link set dev swp1 master bond1 # $ ip link show swp1 | grep ether # link/ether 08:00:27:04:d8:01 brd ff:ff:ff:ff:ff:ff # $ ip link show swp2 | grep ether # link/ether 08:00:27:04:d8:01 brd ff:ff:ff:ff:ff:ff # $ ip link show bond0 | grep ether # link/ether 08:00:27:04:d8:01 brd ff:ff:ff:ff:ff:ff # $ ip link show bond1 | grep ether # link/ether 08:00:27:04:d8:01 brd ff:ff:ff:ff:ff:ff # $ # ifupdown2 will automatically correct and fix this unexpected behavior bond_mac = self.cache.get_link_address(ifaceobj.name) if bond_slaves: first_slave_ifname = bond_slaves[0] first_slave_mac = self.cache.get_link_info_slave_data_attribute( first_slave_ifname, Link.IFLA_BOND_SLAVE_PERM_HWADDR) if first_slave_mac and bond_mac != first_slave_mac: self.logger.info( "%s: invalid bond mac detected - resetting to %s's mac (%s)" % (ifaceobj.name, first_slave_ifname, first_slave_mac)) self.netlink.link_set_address( ifaceobj.name, first_slave_mac, utils.mac_str_to_int(first_slave_mac)) except Exception as e: self.log_error(str(e), ifaceobj)
def translate_addrvirtual_user_config_to_list(self, ifaceobj, address_virtual_list): """ # Translate: # address-virtual 00:11:22:33:44:01 2001:0db8::0370:7334/64 11.0.1.1/24 11.0.1.2/24 # To: # [ # { # "ifname": "macvlan_ifname", # "hwaddress": "macvlan_hwaddress", # "ips": [str(IPNetwork), ] # }, # ] """ user_config_list = [] if not address_virtual_list: return user_config_list macvlan_prefix = self._get_macvlan_prefix(ifaceobj) for index, addr_virtual in enumerate(address_virtual_list): av_attrs = addr_virtual.split() mac = av_attrs[0] if mac: mac = mac.lower() if not self.check_mac_address(ifaceobj, mac): continue config = { "ifname": "%s%d" % (macvlan_prefix, index), "mode": "private" } if mac != "none": config["hwaddress"] = mac config["hwaddress_int"] = utils.mac_str_to_int(mac) ip_network_obj_list = [] for ip in av_attrs[1:]: ip_network_obj_list.append(ipnetwork.IPNetwork(ip)) config["ips"] = ip_network_obj_list user_config_list.append(config) return user_config_list
def query_check_macvlan_config(self, ifaceobj, ifaceobjcurr, attr_name, user_config_address_virtual_ipv6_addr, virtual_addr_list_raw, macvlan_config_list): """ macvlan_config_list = [ { "ifname": "macvlan_ifname", "hwaddress": "macvlan_hwaddress", "ips": [str(IPNetwork), ] }, ] """ is_vrr = attr_name == "vrrp" macvlans_running_ipv6_addr = [] if not virtual_addr_list_raw: return macvlans_running_ipv6_addr macvlan_config_queue = deque(macvlan_config_list) while macvlan_config_queue: ip4_config = None ip6_config = None config = macvlan_config_queue.popleft() if is_vrr: ip4_config = config ip6_config = macvlan_config_queue.popleft() macvlan_ifacename = config.get("ifname") if not self.cache.link_exists(macvlan_ifacename): ifaceobjcurr.update_config_with_status(attr_name, "", 1) continue macvlan_hwaddress = config.get("hwaddress") macvlan_hwaddress_int = config.get("hwaddress_int") if user_config_address_virtual_ipv6_addr: macvlans_running_ipv6_addr.append( self.cache.get_link_ipv6_addrgen_mode(macvlan_ifacename)) # Check mac and ip address rhwaddress = ip4_macvlan_hwaddress = self.cache.get_link_address( macvlan_ifacename) raddrs = ip4_running_addrs = self.cache.get_managed_ip_addresses( ifname=macvlan_ifacename, ifaceobj_list=[ifaceobj], with_address_virtual=True) if not is_vrr: ips = config.get("ips") if not rhwaddress: ifaceobjcurr.update_config_with_status(attr_name, "", 1) continue try: if utils.mac_str_to_int(rhwaddress) == macvlan_hwaddress_int \ and self.compare_user_config_vs_running_state(raddrs, ips) \ and self._check_addresses_in_bridge(ifaceobj, macvlan_hwaddress): ifaceobjcurr.update_config_with_status( attr_name, " ".join(virtual_addr_list_raw), 0) else: if raddrs: address_virtual_value = "%s %s" % ( rhwaddress, " ".join(raddrs)) else: address_virtual_value = rhwaddress ifaceobjcurr.update_config_with_status( attr_name, address_virtual_value, 1) except Exception as e: self.logger.debug("addressvirtual: %s" % str(e)) if raddrs: address_virtual_value = "%s %s" % (rhwaddress, " ".join(raddrs)) else: address_virtual_value = rhwaddress ifaceobjcurr.update_config_with_status( attr_name, address_virtual_value, 1) else: # VRRP ok = False # check macvlan ip4 hwaddress (only if ip4 were provided by the user) if not ip4_config.get( "ips") or ip4_macvlan_hwaddress == ip4_config.get( "hwaddress"): ip6_macvlan_ifname = ip6_config.get("ifname") ip6_macvlan_hwaddress = ip6_config.get("hwaddress") # check macvlan ip6 hwaddress (only if ip6 were provided by the user) if not ip6_config.get( "ips") or self.cache.get_link_address_raw( ip6_macvlan_ifname) == ip6_config.get( "hwaddress_int"): # check all ip4 if self.compare_user_config_vs_running_state( ip4_running_addrs, ip4_config.get("ips") ) and self._check_addresses_in_bridge( ifaceobj, ip4_macvlan_hwaddress): ip6_running_addrs = self.cache.get_managed_ip_addresses( ifname=ip6_macvlan_ifname, ifaceobj_list=[ifaceobj], with_address_virtual=True) # check all ip6 if self.compare_user_config_vs_running_state( ip6_running_addrs, ip6_config.get("ips") ) and self._check_addresses_in_bridge( ifaceobj, ip6_macvlan_hwaddress): ifaceobjcurr.update_config_with_status( attr_name, "%s %s" % (ip4_config.get("id"), " ".join( ip4_config.get("ips") + ip6_config.get("ips"))), 0) ok = True if not ok: ifaceobjcurr.update_config_with_status( attr_name, "%s %s" % (ip4_config.get("id"), " ".join( ip4_config.get("ips") + ip6_config.get("ips"))), 1) return macvlans_running_ipv6_addr
def translate_vrr_user_config_to_list(self, ifaceobj, vrr_config_list, ifquery=False): """ If (IPv4 addresses provided): 00:00:5e:00:01:<V> else if (IPv6 addresses provided): 00:00:5e:00:02:<V> vrrp 1 10.0.0.15/24 vrrp 1 2001:0db8::0370:7334/64 # Translate: # vrrp 255 10.0.0.15/24 10.0.0.2/1 # To: # [ # { # "ifname": "macvlan_ifname", # "hwaddress": "macvlan_hwaddress", # "mode": "macvlan_mode", # "ips": [str(IPNetwork), ] # }, # ] """ ifname = ifaceobj.name user_config_list = [] for index, config in enumerate(vrr_config_list or []): vrrp_id, ip_addrs = config.split(" ", 1) hex_id = '%02x' % int(vrrp_id) ip4 = [] ip6 = [] for ip_addr in ip_addrs.split(): ip_network_obj = ipnetwork.IPNetwork(ip_addr) is_ip6 = ip_network_obj.version == 6 if is_ip6: ip6.append(ip_network_obj) else: ip4.append(ip_network_obj) macvlan_ip4_ifname = "%s%s" % (self.get_vrrp_prefix(ifname, "4"), vrrp_id) macvlan_ip6_ifname = "%s%s" % (self.get_vrrp_prefix(ifname, "6"), vrrp_id) if ip4 or ifquery: merged_with_existing_obj = False macvlan_ip4_mac = "00:00:5e:00:01:%s" % hex_id macvlan_ip4_mac_int = utils.mac_str_to_int(macvlan_ip4_mac) # if the vrr config is defined in different lines for the same ID # we need to save the ip4 and ip6 in the objects we previously # created, example: # vrrp 255 10.0.0.15/24 10.0.0.2/15 # vrrp 255 fe80::a00:27ff:fe04:42/64 for obj in user_config_list: if obj.get("hwaddress_int") == macvlan_ip4_mac_int: obj["ips"] += ip4 merged_with_existing_obj = True if not merged_with_existing_obj: # if ip4 config wasn't merge with an existing object # we need to insert it in our list user_config_list.append({ "ifname": macvlan_ip4_ifname, "hwaddress": macvlan_ip4_mac, "hwaddress_int": macvlan_ip4_mac_int, "mode": "bridge", "ips": ip4, "id": vrrp_id }) elif not ip4 and not ifquery: # special check to see if all ipv4 were removed from the vrrp # configuration, if so we need to remove the associated macvlan if self.cache.link_exists(macvlan_ip4_ifname): self.netlink.link_del(macvlan_ip4_ifname) if ip6 or ifquery: merged_with_existing_obj = False macvlan_ip6_mac = "00:00:5e:00:02:%s" % hex_id macvlan_ip6_mac_int = utils.mac_str_to_int(macvlan_ip6_mac) # if the vrr config is defined in different lines for the same ID # we need to save the ip4 and ip6 in the objects we previously # created, example: # vrrp 255 10.0.0.15/24 10.0.0.2/15 # vrrp 255 fe80::a00:27ff:fe04:42/64 for obj in user_config_list: if obj.get("hwaddress_int") == macvlan_ip6_mac_int: obj["ips"] += ip6 merged_with_existing_obj = True if not merged_with_existing_obj: # if ip6 config wasn't merge with an existing object # we need to insert it in our list user_config_list.append({ "ifname": macvlan_ip6_ifname, "hwaddress": macvlan_ip6_mac, "hwaddress_int": macvlan_ip6_mac_int, "mode": "bridge", "ips": ip6, "id": vrrp_id }) elif not ip6 and not ifquery: # special check to see if all ipv6 were removed from the vrrp # configuration, if so we need to remove the associated macvlan if self.cache.link_exists(macvlan_ip6_ifname): self.netlink.link_del(macvlan_ip6_ifname) if not ifquery: # check if vrrp attribute was removed/re-assigned old_vrr_ids = set() try: for old_ifaceobj in statemanager.statemanager_api.get_ifaceobjs( ifname) or []: for vrr_config in old_ifaceobj.get_attr_value( "vrrp") or []: try: old_vrr_ids.add(vrr_config.split()[0]) except Exception: continue if old_vrr_ids: for config in user_config_list: try: old_vrr_ids.remove(config["id"]) except KeyError: pass for id_to_remove in old_vrr_ids: macvlan_ip4_ifname = "%s%s" % (self.get_vrrp_prefix( ifname, "4"), id_to_remove) macvlan_ip6_ifname = "%s%s" % (self.get_vrrp_prefix( ifname, "6"), id_to_remove) if self.cache.link_exists(macvlan_ip4_ifname): self.netlink.link_del(macvlan_ip4_ifname) if self.cache.link_exists(macvlan_ip6_ifname): self.netlink.link_del(macvlan_ip6_ifname) except Exception as e: self.logger.debug( "%s: vrrp: failure while removing unused macvlan(s)" % ifname) return user_config_list