Skip to content

Commit 01b5e89

Browse files
bcreeley13Jeff Kirsher
authored andcommitted
ice: Add VF promiscuous support
Implement promiscuous support for VF VSIs. Behaviour of promiscuous support is based on VF trust as well as the, introduced, vf-true-promisc flag. A trusted VF with vf-true-promisc disabled will be the default VSI, which means that all traffic without a matching destination MAC address in the device's internal switch will be forwarded to this VF VSI. A trusted VF with vf-true-promisc enabled will go into "true promiscuous mode". This amounts to the VF receiving all ingress and egress traffic that hits the device's internal switch. An untrusted VF will only receive traffic destined for that VF. The vf-true-promisc-support flag cannot be toggled while any VF is in promiscuous mode. This flag should be set prior to loading the iavf driver or spawning VF(s). Signed-off-by: Brett Creeley <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent a4e82a8 commit 01b5e89

File tree

4 files changed

+223
-2
lines changed

4 files changed

+223
-2
lines changed

drivers/net/ethernet/intel/ice/ice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ enum ice_pf_flags {
345345
ICE_FLAG_FW_LLDP_AGENT,
346346
ICE_FLAG_ETHTOOL_CTXT, /* set when ethtool holds RTNL lock */
347347
ICE_FLAG_LEGACY_RX,
348+
ICE_FLAG_VF_TRUE_PROMISC_ENA,
348349
ICE_FLAG_MDD_AUTO_RESET_VF,
349350
ICE_PF_FLAGS_NBITS /* must be last */
350351
};

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ struct ice_priv_flag {
157157
static const struct ice_priv_flag ice_gstrings_priv_flags[] = {
158158
ICE_PRIV_FLAG("link-down-on-close", ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA),
159159
ICE_PRIV_FLAG("fw-lldp-agent", ICE_FLAG_FW_LLDP_AGENT),
160+
ICE_PRIV_FLAG("vf-true-promisc-support",
161+
ICE_FLAG_VF_TRUE_PROMISC_ENA),
160162
ICE_PRIV_FLAG("mdd-auto-reset-vf", ICE_FLAG_MDD_AUTO_RESET_VF),
161163
ICE_PRIV_FLAG("legacy-rx", ICE_FLAG_LEGACY_RX),
162164
};
@@ -1308,6 +1310,16 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
13081310
ice_down(vsi);
13091311
ice_up(vsi);
13101312
}
1313+
/* don't allow modification of this flag when a single VF is in
1314+
* promiscuous mode because it's not supported
1315+
*/
1316+
if (test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, change_flags) &&
1317+
ice_is_any_vf_in_promisc(pf)) {
1318+
dev_err(dev, "Changing vf-true-promisc-support flag while VF(s) are in promiscuous mode not supported\n");
1319+
/* toggle bit back to previous state */
1320+
change_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags);
1321+
ret = -EAGAIN;
1322+
}
13111323
clear_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags);
13121324
return ret;
13131325
}

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

Lines changed: 204 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,37 @@ 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+
3768
/**
3869
* ice_vc_vf_broadcast - Broadcast a message to all VFs on PF
3970
* @pf: pointer to the PF structure
@@ -2059,6 +2090,173 @@ int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena)
20592090
return ret;
20602091
}
20612092

2093+
/**
2094+
* ice_is_any_vf_in_promisc - check if any VF(s) are in promiscuous mode
2095+
* @pf: PF structure for accessing VF(s)
2096+
*
2097+
* Return false if no VF(s) are in unicast and/or multicast promiscuous mode,
2098+
* else return true
2099+
*/
2100+
bool ice_is_any_vf_in_promisc(struct ice_pf *pf)
2101+
{
2102+
int vf_idx;
2103+
2104+
ice_for_each_vf(pf, vf_idx) {
2105+
struct ice_vf *vf = &pf->vf[vf_idx];
2106+
2107+
/* found a VF that has promiscuous mode configured */
2108+
if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) ||
2109+
test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states))
2110+
return true;
2111+
}
2112+
2113+
return false;
2114+
}
2115+
2116+
/**
2117+
* ice_vc_cfg_promiscuous_mode_msg
2118+
* @vf: pointer to the VF info
2119+
* @msg: pointer to the msg buffer
2120+
*
2121+
* called from the VF to configure VF VSIs promiscuous mode
2122+
*/
2123+
static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
2124+
{
2125+
enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
2126+
struct virtchnl_promisc_info *info =
2127+
(struct virtchnl_promisc_info *)msg;
2128+
struct ice_pf *pf = vf->pf;
2129+
struct ice_vsi *vsi;
2130+
struct device *dev;
2131+
bool rm_promisc;
2132+
int ret = 0;
2133+
2134+
if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
2135+
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2136+
goto error_param;
2137+
}
2138+
2139+
if (!ice_vc_isvalid_vsi_id(vf, info->vsi_id)) {
2140+
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2141+
goto error_param;
2142+
}
2143+
2144+
vsi = pf->vsi[vf->lan_vsi_idx];
2145+
if (!vsi) {
2146+
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2147+
goto error_param;
2148+
}
2149+
2150+
dev = ice_pf_to_dev(pf);
2151+
if (!test_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
2152+
dev_err(dev, "Unprivileged VF %d is attempting to configure promiscuous mode\n",
2153+
vf->vf_id);
2154+
/* Leave v_ret alone, lie to the VF on purpose. */
2155+
goto error_param;
2156+
}
2157+
2158+
rm_promisc = !(info->flags & FLAG_VF_UNICAST_PROMISC) &&
2159+
!(info->flags & FLAG_VF_MULTICAST_PROMISC);
2160+
2161+
if (vsi->num_vlan || vf->port_vlan_info) {
2162+
struct ice_vsi *pf_vsi = ice_get_main_vsi(pf);
2163+
struct net_device *pf_netdev;
2164+
2165+
if (!pf_vsi) {
2166+
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2167+
goto error_param;
2168+
}
2169+
2170+
pf_netdev = pf_vsi->netdev;
2171+
2172+
ret = ice_set_vf_spoofchk(pf_netdev, vf->vf_id, rm_promisc);
2173+
if (ret) {
2174+
dev_err(dev, "Failed to update spoofchk to %s for VF %d VSI %d when setting promiscuous mode\n",
2175+
rm_promisc ? "ON" : "OFF", vf->vf_id,
2176+
vsi->vsi_num);
2177+
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2178+
}
2179+
2180+
ret = ice_cfg_vlan_pruning(vsi, true, !rm_promisc);
2181+
if (ret) {
2182+
dev_err(dev, "Failed to configure VLAN pruning in promiscuous mode\n");
2183+
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2184+
goto error_param;
2185+
}
2186+
}
2187+
2188+
if (!test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags)) {
2189+
bool set_dflt_vsi = !!(info->flags & FLAG_VF_UNICAST_PROMISC);
2190+
2191+
if (set_dflt_vsi && !ice_is_dflt_vsi_in_use(pf->first_sw))
2192+
/* only attempt to set the default forwarding VSI if
2193+
* it's not currently set
2194+
*/
2195+
ret = ice_set_dflt_vsi(pf->first_sw, vsi);
2196+
else if (!set_dflt_vsi &&
2197+
ice_is_vsi_dflt_vsi(pf->first_sw, vsi))
2198+
/* only attempt to free the default forwarding VSI if we
2199+
* are the owner
2200+
*/
2201+
ret = ice_clear_dflt_vsi(pf->first_sw);
2202+
2203+
if (ret) {
2204+
dev_err(dev, "%sable VF %d as the default VSI failed, error %d\n",
2205+
set_dflt_vsi ? "en" : "dis", vf->vf_id, ret);
2206+
v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
2207+
goto error_param;
2208+
}
2209+
} else {
2210+
enum ice_status status;
2211+
u8 promisc_m;
2212+
2213+
if (info->flags & FLAG_VF_UNICAST_PROMISC) {
2214+
if (vf->port_vlan_info || vsi->num_vlan)
2215+
promisc_m = ICE_UCAST_VLAN_PROMISC_BITS;
2216+
else
2217+
promisc_m = ICE_UCAST_PROMISC_BITS;
2218+
} else if (info->flags & FLAG_VF_MULTICAST_PROMISC) {
2219+
if (vf->port_vlan_info || vsi->num_vlan)
2220+
promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
2221+
else
2222+
promisc_m = ICE_MCAST_PROMISC_BITS;
2223+
} else {
2224+
if (vf->port_vlan_info || vsi->num_vlan)
2225+
promisc_m = ICE_UCAST_VLAN_PROMISC_BITS;
2226+
else
2227+
promisc_m = ICE_UCAST_PROMISC_BITS;
2228+
}
2229+
2230+
/* Configure multicast/unicast with or without VLAN promiscuous
2231+
* mode
2232+
*/
2233+
status = ice_vf_set_vsi_promisc(vf, vsi, promisc_m, rm_promisc);
2234+
if (status) {
2235+
dev_err(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d failed, error: %d\n",
2236+
rm_promisc ? "dis" : "en", vf->vf_id, status);
2237+
v_ret = ice_err_to_virt_err(status);
2238+
goto error_param;
2239+
} else {
2240+
dev_dbg(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d succeeded\n",
2241+
rm_promisc ? "dis" : "en", vf->vf_id);
2242+
}
2243+
}
2244+
2245+
if (info->flags & FLAG_VF_MULTICAST_PROMISC)
2246+
set_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states);
2247+
else
2248+
clear_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states);
2249+
2250+
if (info->flags & FLAG_VF_UNICAST_PROMISC)
2251+
set_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states);
2252+
else
2253+
clear_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states);
2254+
2255+
error_param:
2256+
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
2257+
v_ret, NULL, 0);
2258+
}
2259+
20622260
/**
20632261
* ice_vc_get_stats_msg
20642262
* @vf: pointer to the VF info
@@ -2992,8 +3190,9 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
29923190
goto error_param;
29933191
}
29943192

2995-
if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) ||
2996-
test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states))
3193+
if ((test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) ||
3194+
test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) &&
3195+
test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags))
29973196
vlan_promisc = true;
29983197

29993198
if (add_v) {
@@ -3317,6 +3516,9 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
33173516
case VIRTCHNL_OP_GET_STATS:
33183517
err = ice_vc_get_stats_msg(vf, msg);
33193518
break;
3519+
case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
3520+
err = ice_vc_cfg_promiscuous_mode_msg(vf, msg);
3521+
break;
33203522
case VIRTCHNL_OP_ADD_VLAN:
33213523
err = ice_vc_add_vlan_msg(vf, msg);
33223524
break;

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ void ice_set_vf_state_qs_dis(struct ice_vf *vf);
128128
int
129129
ice_get_vf_stats(struct net_device *netdev, int vf_id,
130130
struct ifla_vf_stats *vf_stats);
131+
bool ice_is_any_vf_in_promisc(struct ice_pf *pf);
131132
void
132133
ice_vf_lan_overflow_event(struct ice_pf *pf, struct ice_rq_event_info *event);
133134
void ice_print_vfs_mdd_events(struct ice_pf *pf);
@@ -219,5 +220,10 @@ ice_get_vf_stats(struct net_device __always_unused *netdev,
219220
{
220221
return -EOPNOTSUPP;
221222
}
223+
224+
static inline bool ice_is_any_vf_in_promisc(struct ice_pf __always_unused *pf)
225+
{
226+
return false;
227+
}
222228
#endif /* CONFIG_PCI_IOV */
223229
#endif /* _ICE_VIRTCHNL_PF_H_ */

0 commit comments

Comments
 (0)