Commit f657a6e1 authored by Greg Rose's avatar Greg Rose Committed by Jeff Kirsher

i40e: Fix VF driver MAC address configuration

Fix a problem where the 'ip link show' command would display stale
link address information after the link address was set via the 'ip
link set' command.  In addition, fix problem with the user being
allowed to overwrite the administratively set VF MAC address.

Change-Id: I669ed14e55f2b633ef7b456b713632b08468671c
Signed-off-by: default avatarGreg Rose <gregory.v.rose@intel.com>
Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: default avatarSibai Li <sibai.li@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 7efa84b7
......@@ -1330,6 +1330,37 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
(u8 *)&stats, sizeof(stats));
}
/**
* i40e_check_vf_permission
* @vf: pointer to the vf info
* @macaddr: pointer to the MAC Address being checked
*
* Check if the VF has permission to add or delete unicast MAC address
* filters and return error code -EPERM if not. Then check if the
* address filter requested is broadcast or zero and if so return
* an invalid MAC address error code.
**/
static inline int i40e_check_vf_permission(struct i40e_vf *vf, u8 *macaddr)
{
struct i40e_pf *pf = vf->pf;
int ret = 0;
if (is_broadcast_ether_addr(macaddr) ||
is_zero_ether_addr(macaddr)) {
dev_err(&pf->pdev->dev, "invalid VF MAC addr %pM\n", macaddr);
ret = I40E_ERR_INVALID_MAC_ADDR;
} else if (vf->pf_set_mac && !is_multicast_ether_addr(macaddr)) {
/* If the host VMM administrator has set the VF MAC address
* administratively via the ndo_set_vf_mac command then deny
* permission to the VF to add or delete unicast MAC addresses.
*/
dev_err(&pf->pdev->dev,
"VF attempting to override administratively set MAC address\nPlease reload the VF driver to resume normal operation\n");
ret = -EPERM;
}
return ret;
}
/**
* i40e_vc_add_mac_addr_msg
* @vf: pointer to the vf info
......@@ -1345,24 +1376,20 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
struct i40e_pf *pf = vf->pf;
struct i40e_vsi *vsi = NULL;
u16 vsi_id = al->vsi_id;
i40e_status aq_ret = 0;
i40e_status ret = 0;
int i;
if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) ||
!i40e_vc_isvalid_vsi_id(vf, vsi_id)) {
aq_ret = I40E_ERR_PARAM;
ret = I40E_ERR_PARAM;
goto error_param;
}
for (i = 0; i < al->num_elements; i++) {
if (is_broadcast_ether_addr(al->list[i].addr) ||
is_zero_ether_addr(al->list[i].addr)) {
dev_err(&pf->pdev->dev, "invalid VF MAC addr %pMAC\n",
al->list[i].addr);
aq_ret = I40E_ERR_INVALID_MAC_ADDR;
ret = i40e_check_vf_permission(vf, al->list[i].addr);
if (ret)
goto error_param;
}
}
vsi = pf->vsi[vsi_id];
......@@ -1383,7 +1410,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
if (!f) {
dev_err(&pf->pdev->dev,
"Unable to add VF MAC filter\n");
aq_ret = I40E_ERR_PARAM;
ret = I40E_ERR_PARAM;
goto error_param;
}
}
......@@ -1395,7 +1422,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
error_param:
/* send the response to the vf */
return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
aq_ret);
ret);
}
/**
......@@ -1413,15 +1440,21 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
struct i40e_pf *pf = vf->pf;
struct i40e_vsi *vsi = NULL;
u16 vsi_id = al->vsi_id;
i40e_status aq_ret = 0;
i40e_status ret = 0;
int i;
if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) ||
!i40e_vc_isvalid_vsi_id(vf, vsi_id)) {
aq_ret = I40E_ERR_PARAM;
ret = I40E_ERR_PARAM;
goto error_param;
}
for (i = 0; i < al->num_elements; i++) {
ret = i40e_check_vf_permission(vf, al->list[i].addr);
if (ret)
goto error_param;
}
vsi = pf->vsi[vsi_id];
/* delete addresses from the list */
......@@ -1436,7 +1469,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
error_param:
/* send the response to the vf */
return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
aq_ret);
ret);
}
/**
......@@ -1918,6 +1951,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
goto error_param;
}
memcpy(vf->default_lan_addr.addr, mac, ETH_ALEN);
vf->pf_set_mac = true;
dev_info(&pf->pdev->dev, "Reload the VF driver to make this change effective.\n");
ret = 0;
......
......@@ -83,6 +83,7 @@ struct i40e_vf {
struct i40e_virtchnl_ether_addr default_lan_addr;
struct i40e_virtchnl_ether_addr default_fcoe_addr;
u16 port_vlan_id;
bool pf_set_mac; /* The VMM admin set the VF MAC address */
/* VSI indices - actual VSI pointers are maintained in the PF structure
* When assigned, these will be non-zero, because VSI 0 is always
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment