ice: Enable ip link show on the PF to display VF unicast MAC(s)
Currently when there are SR-IOV VF(s) and the user does "ip link show <pf interface>" the VF unicast MAC addresses all show 00:00:00:00:00:00 if the unicast MAC was set via VIRTCHNL (i.e. not administratively set by the host PF). This is misleading to the host administrator. Fix this by setting the VF's dflt_lan_addr.addr when the VF's unicast MAC address is configured via VIRTCHNL. There are a couple cases where we don't allow the dflt_lan_addr.addr field to be written. First, If the VF's pf_set_mac field is true and the VF is not trusted, then we don't allow the dflt_lan_addr.addr to be modified. Second, if the dflt_lan_addr.addr has already been set (i.e. via VIRTCHNL). Also a small refactor was done to separate the flow for add and delete MAC addresses in order to simplify the logic for error conditions and set/clear the VF's dflt_lan_addr.addr field. Signed-off-by: Brett Creeley <brett.creeley@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
		
							parent
							
								
									26a91525cc
								
							
						
					
					
						commit
						ed4c068d46
					
				| @ -34,37 +34,6 @@ static int ice_check_vf_init(struct ice_pf *pf, struct ice_vf *vf) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 |  | ||||||
|  * ice_err_to_virt err - translate errors for VF return code |  | ||||||
|  * @ice_err: error return code |  | ||||||
|  */ |  | ||||||
| static enum virtchnl_status_code ice_err_to_virt_err(enum ice_status ice_err) |  | ||||||
| { |  | ||||||
| 	switch (ice_err) { |  | ||||||
| 	case ICE_SUCCESS: |  | ||||||
| 		return VIRTCHNL_STATUS_SUCCESS; |  | ||||||
| 	case ICE_ERR_BAD_PTR: |  | ||||||
| 	case ICE_ERR_INVAL_SIZE: |  | ||||||
| 	case ICE_ERR_DEVICE_NOT_SUPPORTED: |  | ||||||
| 	case ICE_ERR_PARAM: |  | ||||||
| 	case ICE_ERR_CFG: |  | ||||||
| 		return VIRTCHNL_STATUS_ERR_PARAM; |  | ||||||
| 	case ICE_ERR_NO_MEMORY: |  | ||||||
| 		return VIRTCHNL_STATUS_ERR_NO_MEMORY; |  | ||||||
| 	case ICE_ERR_NOT_READY: |  | ||||||
| 	case ICE_ERR_RESET_FAILED: |  | ||||||
| 	case ICE_ERR_FW_API_VER: |  | ||||||
| 	case ICE_ERR_AQ_ERROR: |  | ||||||
| 	case ICE_ERR_AQ_TIMEOUT: |  | ||||||
| 	case ICE_ERR_AQ_FULL: |  | ||||||
| 	case ICE_ERR_AQ_NO_WORK: |  | ||||||
| 	case ICE_ERR_AQ_EMPTY: |  | ||||||
| 		return VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR; |  | ||||||
| 	default: |  | ||||||
| 		return VIRTCHNL_STATUS_ERR_NOT_SUPPORTED; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * ice_vc_vf_broadcast - Broadcast a message to all VFs on PF |  * ice_vc_vf_broadcast - Broadcast a message to all VFs on PF | ||||||
|  * @pf: pointer to the PF structure |  * @pf: pointer to the PF structure | ||||||
| @ -2483,6 +2452,83 @@ static bool ice_can_vf_change_mac(struct ice_vf *vf) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * ice_vc_add_mac_addr - attempt to add the MAC address passed in | ||||||
|  |  * @vf: pointer to the VF info | ||||||
|  |  * @vsi: pointer to the VF's VSI | ||||||
|  |  * @mac_addr: MAC address to add | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi, u8 *mac_addr) | ||||||
|  | { | ||||||
|  | 	struct device *dev = ice_pf_to_dev(vf->pf); | ||||||
|  | 	enum ice_status status; | ||||||
|  | 
 | ||||||
|  | 	/* default unicast MAC already added */ | ||||||
|  | 	if (ether_addr_equal(mac_addr, vf->dflt_lan_addr.addr)) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	if (is_unicast_ether_addr(mac_addr) && !ice_can_vf_change_mac(vf)) { | ||||||
|  | 		dev_err(dev, "VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n"); | ||||||
|  | 		return -EPERM; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	status = ice_vsi_cfg_mac_fltr(vsi, mac_addr, true); | ||||||
|  | 	if (status == ICE_ERR_ALREADY_EXISTS) { | ||||||
|  | 		dev_err(dev, "MAC %pM already exists for VF %d\n", mac_addr, | ||||||
|  | 			vf->vf_id); | ||||||
|  | 		return -EEXIST; | ||||||
|  | 	} else if (status) { | ||||||
|  | 		dev_err(dev, "Failed to add MAC %pM for VF %d\n, error %d\n", | ||||||
|  | 			mac_addr, vf->vf_id, status); | ||||||
|  | 		return -EIO; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* only set dflt_lan_addr once */ | ||||||
|  | 	if (is_zero_ether_addr(vf->dflt_lan_addr.addr) && | ||||||
|  | 	    is_unicast_ether_addr(mac_addr)) | ||||||
|  | 		ether_addr_copy(vf->dflt_lan_addr.addr, mac_addr); | ||||||
|  | 
 | ||||||
|  | 	vf->num_mac++; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * ice_vc_del_mac_addr - attempt to delete the MAC address passed in | ||||||
|  |  * @vf: pointer to the VF info | ||||||
|  |  * @vsi: pointer to the VF's VSI | ||||||
|  |  * @mac_addr: MAC address to delete | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | ice_vc_del_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi, u8 *mac_addr) | ||||||
|  | { | ||||||
|  | 	struct device *dev = ice_pf_to_dev(vf->pf); | ||||||
|  | 	enum ice_status status; | ||||||
|  | 
 | ||||||
|  | 	if (!ice_can_vf_change_mac(vf) && | ||||||
|  | 	    ether_addr_equal(mac_addr, vf->dflt_lan_addr.addr)) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	status = ice_vsi_cfg_mac_fltr(vsi, mac_addr, false); | ||||||
|  | 	if (status == ICE_ERR_DOES_NOT_EXIST) { | ||||||
|  | 		dev_err(dev, "MAC %pM does not exist for VF %d\n", mac_addr, | ||||||
|  | 			vf->vf_id); | ||||||
|  | 		return -ENOENT; | ||||||
|  | 	} else if (status) { | ||||||
|  | 		dev_err(dev, "Failed to delete MAC %pM for VF %d, error %d\n", | ||||||
|  | 			mac_addr, vf->vf_id, status); | ||||||
|  | 		return -EIO; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (ether_addr_equal(mac_addr, vf->dflt_lan_addr.addr)) | ||||||
|  | 		eth_zero_addr(vf->dflt_lan_addr.addr); | ||||||
|  | 
 | ||||||
|  | 	vf->num_mac--; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * ice_vc_handle_mac_addr_msg |  * ice_vc_handle_mac_addr_msg | ||||||
|  * @vf: pointer to the VF info |  * @vf: pointer to the VF info | ||||||
| @ -2494,23 +2540,23 @@ static bool ice_can_vf_change_mac(struct ice_vf *vf) | |||||||
| static int | static int | ||||||
| ice_vc_handle_mac_addr_msg(struct ice_vf *vf, u8 *msg, bool set) | ice_vc_handle_mac_addr_msg(struct ice_vf *vf, u8 *msg, bool set) | ||||||
| { | { | ||||||
|  | 	int (*ice_vc_cfg_mac) | ||||||
|  | 		(struct ice_vf *vf, struct ice_vsi *vsi, u8 *mac_addr); | ||||||
| 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; | 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; | ||||||
| 	struct virtchnl_ether_addr_list *al = | 	struct virtchnl_ether_addr_list *al = | ||||||
| 	    (struct virtchnl_ether_addr_list *)msg; | 	    (struct virtchnl_ether_addr_list *)msg; | ||||||
| 	struct ice_pf *pf = vf->pf; | 	struct ice_pf *pf = vf->pf; | ||||||
| 	enum virtchnl_ops vc_op; | 	enum virtchnl_ops vc_op; | ||||||
| 	enum ice_status status; |  | ||||||
| 	struct ice_vsi *vsi; | 	struct ice_vsi *vsi; | ||||||
| 	struct device *dev; |  | ||||||
| 	int mac_count = 0; |  | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	dev = ice_pf_to_dev(pf); | 	if (set) { | ||||||
| 
 |  | ||||||
| 	if (set) |  | ||||||
| 		vc_op = VIRTCHNL_OP_ADD_ETH_ADDR; | 		vc_op = VIRTCHNL_OP_ADD_ETH_ADDR; | ||||||
| 	else | 		ice_vc_cfg_mac = ice_vc_add_mac_addr; | ||||||
|  | 	} else { | ||||||
| 		vc_op = VIRTCHNL_OP_DEL_ETH_ADDR; | 		vc_op = VIRTCHNL_OP_DEL_ETH_ADDR; | ||||||
|  | 		ice_vc_cfg_mac = ice_vc_del_mac_addr; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) || | 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) || | ||||||
| 	    !ice_vc_isvalid_vsi_id(vf, al->vsi_id)) { | 	    !ice_vc_isvalid_vsi_id(vf, al->vsi_id)) { | ||||||
| @ -2518,14 +2564,15 @@ ice_vc_handle_mac_addr_msg(struct ice_vf *vf, u8 *msg, bool set) | |||||||
| 		goto handle_mac_exit; | 		goto handle_mac_exit; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/* If this VF is not privileged, then we can't add more than a
 | ||||||
|  | 	 * limited number of addresses. Check to make sure that the | ||||||
|  | 	 * additions do not push us over the limit. | ||||||
|  | 	 */ | ||||||
| 	if (set && !ice_is_vf_trusted(vf) && | 	if (set && !ice_is_vf_trusted(vf) && | ||||||
| 	    (vf->num_mac + al->num_elements) > ICE_MAX_MACADDR_PER_VF) { | 	    (vf->num_mac + al->num_elements) > ICE_MAX_MACADDR_PER_VF) { | ||||||
| 		dev_err(dev, | 		dev_err(ice_pf_to_dev(pf), | ||||||
| 			"Can't add more MAC addresses, because VF-%d is not trusted, switch the VF to trusted mode in order to add more functionalities\n", | 			"Can't add more MAC addresses, because VF-%d is not trusted, switch the VF to trusted mode in order to add more functionalities\n", | ||||||
| 			vf->vf_id); | 			vf->vf_id); | ||||||
| 		/* There is no need to let VF know about not being trusted
 |  | ||||||
| 		 * to add more MAC addr, so we can just return success message. |  | ||||||
| 		 */ |  | ||||||
| 		v_ret = VIRTCHNL_STATUS_ERR_PARAM; | 		v_ret = VIRTCHNL_STATUS_ERR_PARAM; | ||||||
| 		goto handle_mac_exit; | 		goto handle_mac_exit; | ||||||
| 	} | 	} | ||||||
| @ -2537,70 +2584,22 @@ ice_vc_handle_mac_addr_msg(struct ice_vf *vf, u8 *msg, bool set) | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < al->num_elements; i++) { | 	for (i = 0; i < al->num_elements; i++) { | ||||||
| 		u8 *maddr = al->list[i].addr; | 		u8 *mac_addr = al->list[i].addr; | ||||||
|  | 		int result; | ||||||
| 
 | 
 | ||||||
| 		if (ether_addr_equal(maddr, vf->dflt_lan_addr.addr) || | 		if (is_broadcast_ether_addr(mac_addr) || | ||||||
| 		    is_broadcast_ether_addr(maddr)) { | 		    is_zero_ether_addr(mac_addr)) | ||||||
| 			if (set) { | 			continue; | ||||||
| 				/* VF is trying to add filters that the PF
 |  | ||||||
| 				 * already added. Just continue. |  | ||||||
| 				 */ |  | ||||||
| 				dev_info(dev, |  | ||||||
| 					 "MAC %pM already set for VF %d\n", |  | ||||||
| 					 maddr, vf->vf_id); |  | ||||||
| 				continue; |  | ||||||
| 			} else { |  | ||||||
| 				/* VF can't remove dflt_lan_addr/bcast MAC */ |  | ||||||
| 				dev_err(dev, |  | ||||||
| 					"VF can't remove default MAC address or MAC %pM programmed by PF for VF %d\n", |  | ||||||
| 					maddr, vf->vf_id); |  | ||||||
| 				continue; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		/* check for the invalid cases and bail if necessary */ | 		result = ice_vc_cfg_mac(vf, vsi, mac_addr); | ||||||
| 		if (is_zero_ether_addr(maddr)) { | 		if (result == -EEXIST || result == -ENOENT) { | ||||||
| 			dev_err(dev, | 			continue; | ||||||
| 				"invalid MAC %pM provided for VF %d\n", | 		} else if (result) { | ||||||
| 				maddr, vf->vf_id); | 			v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR; | ||||||
| 			v_ret = VIRTCHNL_STATUS_ERR_PARAM; |  | ||||||
| 			goto handle_mac_exit; | 			goto handle_mac_exit; | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		if (is_unicast_ether_addr(maddr) && |  | ||||||
| 		    !ice_can_vf_change_mac(vf)) { |  | ||||||
| 			dev_err(dev, |  | ||||||
| 				"can't change unicast MAC for untrusted VF %d\n", |  | ||||||
| 				vf->vf_id); |  | ||||||
| 			v_ret = VIRTCHNL_STATUS_ERR_PARAM; |  | ||||||
| 			goto handle_mac_exit; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		/* program the updated filter list */ |  | ||||||
| 		status = ice_vsi_cfg_mac_fltr(vsi, maddr, set); |  | ||||||
| 		if (status == ICE_ERR_DOES_NOT_EXIST || |  | ||||||
| 		    status == ICE_ERR_ALREADY_EXISTS) { |  | ||||||
| 			dev_info(dev, |  | ||||||
| 				 "can't %s MAC filters %pM for VF %d, error %d\n", |  | ||||||
| 				 set ? "add" : "remove", maddr, vf->vf_id, |  | ||||||
| 				 status); |  | ||||||
| 		} else if (status) { |  | ||||||
| 			dev_err(dev, |  | ||||||
| 				"can't %s MAC filters for VF %d, error %d\n", |  | ||||||
| 				set ? "add" : "remove", vf->vf_id, status); |  | ||||||
| 			v_ret = ice_err_to_virt_err(status); |  | ||||||
| 			goto handle_mac_exit; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		mac_count++; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Track number of MAC filters programmed for the VF VSI */ |  | ||||||
| 	if (set) |  | ||||||
| 		vf->num_mac += mac_count; |  | ||||||
| 	else |  | ||||||
| 		vf->num_mac -= mac_count; |  | ||||||
| 
 |  | ||||||
| handle_mac_exit: | handle_mac_exit: | ||||||
| 	/* send the response to the VF */ | 	/* send the response to the VF */ | ||||||
| 	return ice_vc_send_msg_to_vf(vf, vc_op, v_ret, NULL, 0); | 	return ice_vc_send_msg_to_vf(vf, vc_op, v_ret, NULL, 0); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user