Commit b5569892 authored by Anjali Singhai Jain's avatar Anjali Singhai Jain Committed by Jeff Kirsher

i40e: Add vf-true-promisc-support priv flag

This patch adds priv-flag knob to configure global true promisc
support. With this patch the user can decide the flavor of
promiscuous that the VFs will see when promiscuous mode is enabled
on the interface. Since this a global setting for the whole device,
the priv-flag is exposed only on the first PF of the device.

The default is true promisc support is off, which means the promisc
mode for the VF will be limited/defport mode.

For the PF, we still will be in limited promisc unless in MFP mode
irrespective of the flavor picked through this knob.

Usage:
On PF0
ethtool --show-priv-flags p261p1
Private flags for p261p1:
MFP                    : off
LinkPolling            : off
flow-director-atr      : on
veb-stats              : off
hw-atr-eviction        : off
vf-true-promisc-support: off

to enable setting true promisc
ethtool --set-priv-flags p261p1 vf-true-promisc-support on

At this point if the VF is set to trust and promisc is enabled
on the VF through
ip link set ... promisc on
The VF/VFs will be able to see ALL ingress traffic

Change-Id: I8fac4b6eb1af9ca77b5376b79c50bdce5055bd94
Signed-off-by: default avatarAnjali Singhai Jain <anjali.singhai@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent f3d58497
...@@ -97,11 +97,12 @@ ...@@ -97,11 +97,12 @@
#define I40E_INT_NAME_STR_LEN (IFNAMSIZ + 16) #define I40E_INT_NAME_STR_LEN (IFNAMSIZ + 16)
/* Ethtool Private Flags */ /* Ethtool Private Flags */
#define I40E_PRIV_FLAGS_NPAR_FLAG BIT(0) #define I40E_PRIV_FLAGS_MFP_FLAG BIT(0)
#define I40E_PRIV_FLAGS_LINKPOLL_FLAG BIT(1) #define I40E_PRIV_FLAGS_LINKPOLL_FLAG BIT(1)
#define I40E_PRIV_FLAGS_FD_ATR BIT(2) #define I40E_PRIV_FLAGS_FD_ATR BIT(2)
#define I40E_PRIV_FLAGS_VEB_STATS BIT(3) #define I40E_PRIV_FLAGS_VEB_STATS BIT(3)
#define I40E_PRIV_FLAGS_HW_ATR_EVICT BIT(5) #define I40E_PRIV_FLAGS_HW_ATR_EVICT BIT(4)
#define I40E_PRIV_FLAGS_TRUE_PROMISC_SUPPORT BIT(5)
#define I40E_NVM_VERSION_LO_SHIFT 0 #define I40E_NVM_VERSION_LO_SHIFT 0
#define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT) #define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT)
...@@ -358,6 +359,7 @@ struct i40e_pf { ...@@ -358,6 +359,7 @@ struct i40e_pf {
#define I40E_FLAG_STOP_FW_LLDP BIT_ULL(47) #define I40E_FLAG_STOP_FW_LLDP BIT_ULL(47)
#define I40E_FLAG_HAVE_10GBASET_PHY BIT_ULL(48) #define I40E_FLAG_HAVE_10GBASET_PHY BIT_ULL(48)
#define I40E_FLAG_PF_MAC BIT_ULL(50) #define I40E_FLAG_PF_MAC BIT_ULL(50)
#define I40E_FLAG_TRUE_PROMISC_SUPPORT BIT_ULL(51)
/* tracks features that get auto disabled by errors */ /* tracks features that get auto disabled by errors */
u64 auto_disable_flags; u64 auto_disable_flags;
......
...@@ -1972,10 +1972,12 @@ i40e_status i40e_aq_add_vsi(struct i40e_hw *hw, ...@@ -1972,10 +1972,12 @@ i40e_status i40e_aq_add_vsi(struct i40e_hw *hw,
* @seid: vsi number * @seid: vsi number
* @set: set unicast promiscuous enable/disable * @set: set unicast promiscuous enable/disable
* @cmd_details: pointer to command details structure or NULL * @cmd_details: pointer to command details structure or NULL
* @rx_only_promisc: flag to decide if egress traffic gets mirrored in promisc
**/ **/
i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw, i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw,
u16 seid, bool set, u16 seid, bool set,
struct i40e_asq_cmd_details *cmd_details) struct i40e_asq_cmd_details *cmd_details,
bool rx_only_promisc)
{ {
struct i40e_aq_desc desc; struct i40e_aq_desc desc;
struct i40e_aqc_set_vsi_promiscuous_modes *cmd = struct i40e_aqc_set_vsi_promiscuous_modes *cmd =
...@@ -1988,8 +1990,9 @@ i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw, ...@@ -1988,8 +1990,9 @@ i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw,
if (set) { if (set) {
flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST; flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST;
if (((hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver >= 5)) || if (rx_only_promisc &&
(hw->aq.api_maj_ver > 1)) (((hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver >= 5)) ||
(hw->aq.api_maj_ver > 1)))
flags |= I40E_AQC_SET_VSI_PROMISC_TX; flags |= I40E_AQC_SET_VSI_PROMISC_TX;
} }
......
...@@ -230,6 +230,17 @@ static const char i40e_gstrings_test[][ETH_GSTRING_LEN] = { ...@@ -230,6 +230,17 @@ static const char i40e_gstrings_test[][ETH_GSTRING_LEN] = {
#define I40E_TEST_LEN (sizeof(i40e_gstrings_test) / ETH_GSTRING_LEN) #define I40E_TEST_LEN (sizeof(i40e_gstrings_test) / ETH_GSTRING_LEN)
static const char i40e_priv_flags_strings_gl[][ETH_GSTRING_LEN] = {
"MFP",
"LinkPolling",
"flow-director-atr",
"veb-stats",
"hw-atr-eviction",
"vf-true-promisc-support",
};
#define I40E_PRIV_FLAGS_GL_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings_gl)
static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = { static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = {
"NPAR", "NPAR",
"LinkPolling", "LinkPolling",
...@@ -1158,6 +1169,10 @@ static void i40e_get_drvinfo(struct net_device *netdev, ...@@ -1158,6 +1169,10 @@ static void i40e_get_drvinfo(struct net_device *netdev,
sizeof(drvinfo->fw_version)); sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, pci_name(pf->pdev), strlcpy(drvinfo->bus_info, pci_name(pf->pdev),
sizeof(drvinfo->bus_info)); sizeof(drvinfo->bus_info));
if (pf->hw.pf_id == 0)
drvinfo->n_priv_flags = I40E_PRIV_FLAGS_GL_STR_LEN;
else
drvinfo->n_priv_flags = I40E_PRIV_FLAGS_STR_LEN;
} }
static void i40e_get_ringparam(struct net_device *netdev, static void i40e_get_ringparam(struct net_device *netdev,
...@@ -1385,6 +1400,9 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset) ...@@ -1385,6 +1400,9 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset)
return I40E_VSI_STATS_LEN(netdev); return I40E_VSI_STATS_LEN(netdev);
} }
case ETH_SS_PRIV_FLAGS: case ETH_SS_PRIV_FLAGS:
if (pf->hw.pf_id == 0)
return I40E_PRIV_FLAGS_GL_STR_LEN;
else
return I40E_PRIV_FLAGS_STR_LEN; return I40E_PRIV_FLAGS_STR_LEN;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -1583,11 +1601,19 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset, ...@@ -1583,11 +1601,19 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
/* BUG_ON(p - data != I40E_STATS_LEN * ETH_GSTRING_LEN); */ /* BUG_ON(p - data != I40E_STATS_LEN * ETH_GSTRING_LEN); */
break; break;
case ETH_SS_PRIV_FLAGS: case ETH_SS_PRIV_FLAGS:
if (pf->hw.pf_id == 0) {
for (i = 0; i < I40E_PRIV_FLAGS_GL_STR_LEN; i++) {
memcpy(data, i40e_priv_flags_strings_gl[i],
ETH_GSTRING_LEN);
data += ETH_GSTRING_LEN;
}
} else {
for (i = 0; i < I40E_PRIV_FLAGS_STR_LEN; i++) { for (i = 0; i < I40E_PRIV_FLAGS_STR_LEN; i++) {
memcpy(data, i40e_priv_flags_strings[i], memcpy(data, i40e_priv_flags_strings[i],
ETH_GSTRING_LEN); ETH_GSTRING_LEN);
data += ETH_GSTRING_LEN; data += ETH_GSTRING_LEN;
} }
}
break; break;
default: default:
break; break;
...@@ -2848,8 +2874,6 @@ static u32 i40e_get_priv_flags(struct net_device *dev) ...@@ -2848,8 +2874,6 @@ static u32 i40e_get_priv_flags(struct net_device *dev)
struct i40e_pf *pf = vsi->back; struct i40e_pf *pf = vsi->back;
u32 ret_flags = 0; u32 ret_flags = 0;
ret_flags |= pf->hw.func_caps.npar_enable ?
I40E_PRIV_FLAGS_NPAR_FLAG : 0;
ret_flags |= pf->flags & I40E_FLAG_LINK_POLLING_ENABLED ? ret_flags |= pf->flags & I40E_FLAG_LINK_POLLING_ENABLED ?
I40E_PRIV_FLAGS_LINKPOLL_FLAG : 0; I40E_PRIV_FLAGS_LINKPOLL_FLAG : 0;
ret_flags |= pf->flags & I40E_FLAG_FD_ATR_ENABLED ? ret_flags |= pf->flags & I40E_FLAG_FD_ATR_ENABLED ?
...@@ -2858,6 +2882,10 @@ static u32 i40e_get_priv_flags(struct net_device *dev) ...@@ -2858,6 +2882,10 @@ static u32 i40e_get_priv_flags(struct net_device *dev)
I40E_PRIV_FLAGS_VEB_STATS : 0; I40E_PRIV_FLAGS_VEB_STATS : 0;
ret_flags |= pf->auto_disable_flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE ? ret_flags |= pf->auto_disable_flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE ?
0 : I40E_PRIV_FLAGS_HW_ATR_EVICT; 0 : I40E_PRIV_FLAGS_HW_ATR_EVICT;
if (pf->hw.pf_id == 0) {
ret_flags |= pf->flags & I40E_FLAG_TRUE_PROMISC_SUPPORT ?
I40E_PRIV_FLAGS_TRUE_PROMISC_SUPPORT : 0;
}
return ret_flags; return ret_flags;
} }
...@@ -2872,7 +2900,10 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags) ...@@ -2872,7 +2900,10 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
struct i40e_netdev_priv *np = netdev_priv(dev); struct i40e_netdev_priv *np = netdev_priv(dev);
struct i40e_vsi *vsi = np->vsi; struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back; struct i40e_pf *pf = vsi->back;
u16 sw_flags = 0, valid_flags = 0;
bool reset_required = false; bool reset_required = false;
bool promisc_change = false;
int ret;
/* NOTE: MFP is not settable */ /* NOTE: MFP is not settable */
...@@ -2902,6 +2933,33 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags) ...@@ -2902,6 +2933,33 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
reset_required = true; reset_required = true;
} }
if (pf->hw.pf_id == 0) {
if ((flags & I40E_PRIV_FLAGS_TRUE_PROMISC_SUPPORT) &&
!(pf->flags & I40E_FLAG_TRUE_PROMISC_SUPPORT)) {
pf->flags |= I40E_FLAG_TRUE_PROMISC_SUPPORT;
promisc_change = true;
} else if (!(flags & I40E_PRIV_FLAGS_TRUE_PROMISC_SUPPORT) &&
(pf->flags & I40E_FLAG_TRUE_PROMISC_SUPPORT)) {
pf->flags &= ~I40E_FLAG_TRUE_PROMISC_SUPPORT;
promisc_change = true;
}
}
if (promisc_change) {
if (!(pf->flags & I40E_FLAG_TRUE_PROMISC_SUPPORT))
sw_flags = I40E_AQ_SET_SWITCH_CFG_PROMISC;
valid_flags = I40E_AQ_SET_SWITCH_CFG_PROMISC;
ret = i40e_aq_set_switch_config(&pf->hw, sw_flags, valid_flags,
NULL);
if (ret && pf->hw.aq.asq_last_status != I40E_AQ_RC_ESRCH) {
dev_info(&pf->pdev->dev,
"couldn't set switch config bits, err %s aq_err %s\n",
i40e_stat_str(&pf->hw, ret),
i40e_aq_str(&pf->hw,
pf->hw.aq.asq_last_status));
/* not a fatal problem, just keep going */
}
}
if ((flags & I40E_PRIV_FLAGS_HW_ATR_EVICT) && if ((flags & I40E_PRIV_FLAGS_HW_ATR_EVICT) &&
(pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE)) (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE))
pf->auto_disable_flags &= ~I40E_FLAG_HW_ATR_EVICT_CAPABLE; pf->auto_disable_flags &= ~I40E_FLAG_HW_ATR_EVICT_CAPABLE;
......
...@@ -2128,7 +2128,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) ...@@ -2128,7 +2128,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
aq_ret = i40e_aq_set_vsi_unicast_promiscuous( aq_ret = i40e_aq_set_vsi_unicast_promiscuous(
&vsi->back->hw, &vsi->back->hw,
vsi->seid, vsi->seid,
cur_promisc, NULL); cur_promisc, NULL,
true);
if (aq_ret) { if (aq_ret) {
retval = retval =
i40e_aq_rc_to_posix(aq_ret, i40e_aq_rc_to_posix(aq_ret,
...@@ -10407,6 +10408,7 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf, bool printconfig) ...@@ -10407,6 +10408,7 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf, bool printconfig)
**/ **/
static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
{ {
u16 flags = 0;
int ret; int ret;
/* find out what's out there already */ /* find out what's out there already */
...@@ -10420,6 +10422,32 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) ...@@ -10420,6 +10422,32 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
} }
i40e_pf_reset_stats(pf); i40e_pf_reset_stats(pf);
/* set the switch config bit for the whole device to
* support limited promisc or true promisc
* when user requests promisc. The default is limited
* promisc.
*/
if ((pf->hw.pf_id == 0) &&
!(pf->flags & I40E_FLAG_TRUE_PROMISC_SUPPORT))
flags = I40E_AQ_SET_SWITCH_CFG_PROMISC;
if (pf->hw.pf_id == 0) {
u16 valid_flags;
valid_flags = I40E_AQ_SET_SWITCH_CFG_PROMISC;
ret = i40e_aq_set_switch_config(&pf->hw, flags, valid_flags,
NULL);
if (ret && pf->hw.aq.asq_last_status != I40E_AQ_RC_ESRCH) {
dev_info(&pf->pdev->dev,
"couldn't set switch config bits, err %s aq_err %s\n",
i40e_stat_str(&pf->hw, ret),
i40e_aq_str(&pf->hw,
pf->hw.aq.asq_last_status));
/* not a fatal problem, just keep going */
}
}
/* first time setup */ /* first time setup */
if (pf->lan_vsi == I40E_NO_VSI || reinit) { if (pf->lan_vsi == I40E_NO_VSI || reinit) {
struct i40e_vsi *vsi = NULL; struct i40e_vsi *vsi = NULL;
......
...@@ -130,7 +130,8 @@ i40e_status i40e_aq_set_vsi_broadcast(struct i40e_hw *hw, ...@@ -130,7 +130,8 @@ i40e_status i40e_aq_set_vsi_broadcast(struct i40e_hw *hw,
u16 vsi_id, bool set_filter, u16 vsi_id, bool set_filter,
struct i40e_asq_cmd_details *cmd_details); struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw, i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw,
u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details); u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details,
bool rx_only_promisc);
i40e_status i40e_aq_set_vsi_multicast_promiscuous(struct i40e_hw *hw, i40e_status i40e_aq_set_vsi_multicast_promiscuous(struct i40e_hw *hw,
u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details); u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details);
enum i40e_status_code i40e_aq_set_vsi_mc_promisc_on_vlan(struct i40e_hw *hw, enum i40e_status_code i40e_aq_set_vsi_mc_promisc_on_vlan(struct i40e_hw *hw,
......
...@@ -1562,7 +1562,8 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, ...@@ -1562,7 +1562,8 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
} }
} else { } else {
aq_ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid, aq_ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid,
allmulti, NULL); allmulti, NULL,
true);
aq_err = pf->hw.aq.asq_last_status; aq_err = pf->hw.aq.asq_last_status;
if (aq_ret) if (aq_ret)
dev_err(&pf->pdev->dev, dev_err(&pf->pdev->dev,
......
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