Skip to content

Commit ed4c068

Browse files
bcreeley13Jeff Kirsher
authored andcommitted
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 <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 26a9152 commit ed4c068

File tree

1 file changed

+99
-100
lines changed

1 file changed

+99
-100
lines changed

drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c

Lines changed: 99 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -34,37 +34,6 @@ static int ice_check_vf_init(struct ice_pf *pf, struct ice_vf *vf)
3434
return 0;
3535
}
3636

37-
/**
38-
* ice_err_to_virt err - translate errors for VF return code
39-
* @ice_err: error return code
40-
*/
41-
static enum virtchnl_status_code ice_err_to_virt_err(enum ice_status ice_err)
42-
{
43-
switch (ice_err) {
44-
case ICE_SUCCESS:
45-
return VIRTCHNL_STATUS_SUCCESS;
46-
case ICE_ERR_BAD_PTR:
47-
case ICE_ERR_INVAL_SIZE:
48-
case ICE_ERR_DEVICE_NOT_SUPPORTED:
49-
case ICE_ERR_PARAM:
50-
case ICE_ERR_CFG:
51-
return VIRTCHNL_STATUS_ERR_PARAM;
52-
case ICE_ERR_NO_MEMORY:
53-
return VIRTCHNL_STATUS_ERR_NO_MEMORY;
54-
case ICE_ERR_NOT_READY:
55-
case ICE_ERR_RESET_FAILED:
56-
case ICE_ERR_FW_API_VER:
57-
case ICE_ERR_AQ_ERROR:
58-
case ICE_ERR_AQ_TIMEOUT:
59-
case ICE_ERR_AQ_FULL:
60-
case ICE_ERR_AQ_NO_WORK:
61-
case ICE_ERR_AQ_EMPTY:
62-
return VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
63-
default:
64-
return VIRTCHNL_STATUS_ERR_NOT_SUPPORTED;
65-
}
66-
}
67-
6837
/**
6938
* ice_vc_vf_broadcast - Broadcast a message to all VFs on PF
7039
* @pf: pointer to the PF structure
@@ -2483,6 +2452,83 @@ static bool ice_can_vf_change_mac(struct ice_vf *vf)
24832452
return true;
24842453
}
24852454

2455+
/**
2456+
* ice_vc_add_mac_addr - attempt to add the MAC address passed in
2457+
* @vf: pointer to the VF info
2458+
* @vsi: pointer to the VF's VSI
2459+
* @mac_addr: MAC address to add
2460+
*/
2461+
static int
2462+
ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi, u8 *mac_addr)
2463+
{
2464+
struct device *dev = ice_pf_to_dev(vf->pf);
2465+
enum ice_status status;
2466+
2467+
/* default unicast MAC already added */
2468+
if (ether_addr_equal(mac_addr, vf->dflt_lan_addr.addr))
2469+
return 0;
2470+
2471+
if (is_unicast_ether_addr(mac_addr) && !ice_can_vf_change_mac(vf)) {
2472+
dev_err(dev, "VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n");
2473+
return -EPERM;
2474+
}
2475+
2476+
status = ice_vsi_cfg_mac_fltr(vsi, mac_addr, true);
2477+
if (status == ICE_ERR_ALREADY_EXISTS) {
2478+
dev_err(dev, "MAC %pM already exists for VF %d\n", mac_addr,
2479+
vf->vf_id);
2480+
return -EEXIST;
2481+
} else if (status) {
2482+
dev_err(dev, "Failed to add MAC %pM for VF %d\n, error %d\n",
2483+
mac_addr, vf->vf_id, status);
2484+
return -EIO;
2485+
}
2486+
2487+
/* only set dflt_lan_addr once */
2488+
if (is_zero_ether_addr(vf->dflt_lan_addr.addr) &&
2489+
is_unicast_ether_addr(mac_addr))
2490+
ether_addr_copy(vf->dflt_lan_addr.addr, mac_addr);
2491+
2492+
vf->num_mac++;
2493+
2494+
return 0;
2495+
}
2496+
2497+
/**
2498+
* ice_vc_del_mac_addr - attempt to delete the MAC address passed in
2499+
* @vf: pointer to the VF info
2500+
* @vsi: pointer to the VF's VSI
2501+
* @mac_addr: MAC address to delete
2502+
*/
2503+
static int
2504+
ice_vc_del_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi, u8 *mac_addr)
2505+
{
2506+
struct device *dev = ice_pf_to_dev(vf->pf);
2507+
enum ice_status status;
2508+
2509+
if (!ice_can_vf_change_mac(vf) &&
2510+
ether_addr_equal(mac_addr, vf->dflt_lan_addr.addr))
2511+
return 0;
2512+
2513+
status = ice_vsi_cfg_mac_fltr(vsi, mac_addr, false);
2514+
if (status == ICE_ERR_DOES_NOT_EXIST) {
2515+
dev_err(dev, "MAC %pM does not exist for VF %d\n", mac_addr,
2516+
vf->vf_id);
2517+
return -ENOENT;
2518+
} else if (status) {
2519+
dev_err(dev, "Failed to delete MAC %pM for VF %d, error %d\n",
2520+
mac_addr, vf->vf_id, status);
2521+
return -EIO;
2522+
}
2523+
2524+
if (ether_addr_equal(mac_addr, vf->dflt_lan_addr.addr))
2525+
eth_zero_addr(vf->dflt_lan_addr.addr);
2526+
2527+
vf->num_mac--;
2528+
2529+
return 0;
2530+
}
2531+
24862532
/**
24872533
* ice_vc_handle_mac_addr_msg
24882534
* @vf: pointer to the VF info
@@ -2494,38 +2540,39 @@ static bool ice_can_vf_change_mac(struct ice_vf *vf)
24942540
static int
24952541
ice_vc_handle_mac_addr_msg(struct ice_vf *vf, u8 *msg, bool set)
24962542
{
2543+
int (*ice_vc_cfg_mac)
2544+
(struct ice_vf *vf, struct ice_vsi *vsi, u8 *mac_addr);
24972545
enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
24982546
struct virtchnl_ether_addr_list *al =
24992547
(struct virtchnl_ether_addr_list *)msg;
25002548
struct ice_pf *pf = vf->pf;
25012549
enum virtchnl_ops vc_op;
2502-
enum ice_status status;
25032550
struct ice_vsi *vsi;
2504-
struct device *dev;
2505-
int mac_count = 0;
25062551
int i;
25072552

2508-
dev = ice_pf_to_dev(pf);
2509-
2510-
if (set)
2553+
if (set) {
25112554
vc_op = VIRTCHNL_OP_ADD_ETH_ADDR;
2512-
else
2555+
ice_vc_cfg_mac = ice_vc_add_mac_addr;
2556+
} else {
25132557
vc_op = VIRTCHNL_OP_DEL_ETH_ADDR;
2558+
ice_vc_cfg_mac = ice_vc_del_mac_addr;
2559+
}
25142560

25152561
if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) ||
25162562
!ice_vc_isvalid_vsi_id(vf, al->vsi_id)) {
25172563
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
25182564
goto handle_mac_exit;
25192565
}
25202566

2567+
/* If this VF is not privileged, then we can't add more than a
2568+
* limited number of addresses. Check to make sure that the
2569+
* additions do not push us over the limit.
2570+
*/
25212571
if (set && !ice_is_vf_trusted(vf) &&
25222572
(vf->num_mac + al->num_elements) > ICE_MAX_MACADDR_PER_VF) {
2523-
dev_err(dev,
2573+
dev_err(ice_pf_to_dev(pf),
25242574
"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",
25252575
vf->vf_id);
2526-
/* There is no need to let VF know about not being trusted
2527-
* to add more MAC addr, so we can just return success message.
2528-
*/
25292576
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
25302577
goto handle_mac_exit;
25312578
}
@@ -2537,70 +2584,22 @@ ice_vc_handle_mac_addr_msg(struct ice_vf *vf, u8 *msg, bool set)
25372584
}
25382585

25392586
for (i = 0; i < al->num_elements; i++) {
2540-
u8 *maddr = al->list[i].addr;
2587+
u8 *mac_addr = al->list[i].addr;
2588+
int result;
25412589

2542-
if (ether_addr_equal(maddr, vf->dflt_lan_addr.addr) ||
2543-
is_broadcast_ether_addr(maddr)) {
2544-
if (set) {
2545-
/* VF is trying to add filters that the PF
2546-
* already added. Just continue.
2547-
*/
2548-
dev_info(dev,
2549-
"MAC %pM already set for VF %d\n",
2550-
maddr, vf->vf_id);
2551-
continue;
2552-
} else {
2553-
/* VF can't remove dflt_lan_addr/bcast MAC */
2554-
dev_err(dev,
2555-
"VF can't remove default MAC address or MAC %pM programmed by PF for VF %d\n",
2556-
maddr, vf->vf_id);
2557-
continue;
2558-
}
2559-
}
2560-
2561-
/* check for the invalid cases and bail if necessary */
2562-
if (is_zero_ether_addr(maddr)) {
2563-
dev_err(dev,
2564-
"invalid MAC %pM provided for VF %d\n",
2565-
maddr, vf->vf_id);
2566-
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2567-
goto handle_mac_exit;
2568-
}
2569-
2570-
if (is_unicast_ether_addr(maddr) &&
2571-
!ice_can_vf_change_mac(vf)) {
2572-
dev_err(dev,
2573-
"can't change unicast MAC for untrusted VF %d\n",
2574-
vf->vf_id);
2575-
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2576-
goto handle_mac_exit;
2577-
}
2590+
if (is_broadcast_ether_addr(mac_addr) ||
2591+
is_zero_ether_addr(mac_addr))
2592+
continue;
25782593

2579-
/* program the updated filter list */
2580-
status = ice_vsi_cfg_mac_fltr(vsi, maddr, set);
2581-
if (status == ICE_ERR_DOES_NOT_EXIST ||
2582-
status == ICE_ERR_ALREADY_EXISTS) {
2583-
dev_info(dev,
2584-
"can't %s MAC filters %pM for VF %d, error %d\n",
2585-
set ? "add" : "remove", maddr, vf->vf_id,
2586-
status);
2587-
} else if (status) {
2588-
dev_err(dev,
2589-
"can't %s MAC filters for VF %d, error %d\n",
2590-
set ? "add" : "remove", vf->vf_id, status);
2591-
v_ret = ice_err_to_virt_err(status);
2594+
result = ice_vc_cfg_mac(vf, vsi, mac_addr);
2595+
if (result == -EEXIST || result == -ENOENT) {
2596+
continue;
2597+
} else if (result) {
2598+
v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
25922599
goto handle_mac_exit;
25932600
}
2594-
2595-
mac_count++;
25962601
}
25972602

2598-
/* Track number of MAC filters programmed for the VF VSI */
2599-
if (set)
2600-
vf->num_mac += mac_count;
2601-
else
2602-
vf->num_mac -= mac_count;
2603-
26042603
handle_mac_exit:
26052604
/* send the response to the VF */
26062605
return ice_vc_send_msg_to_vf(vf, vc_op, v_ret, NULL, 0);

0 commit comments

Comments
 (0)