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
Exemple #2
0
 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)
Exemple #3
0
    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)
Exemple #4
0
    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