ice: Introduce enabling promiscuous mode on multiple VF's
In current implementation default VSI switch filter is only able to forward traffic to a single VSI. This limits promiscuous mode with private flag 'vf-true-promisc-support' to a single VF. Enabling it on the second VF won't work. Also allmulticast support doesn't seem to be properly implemented when vf-true-promisc-support is true. Use standard ice_add_rule_internal() function that already implements forwarding to multiple VSI's instead of constructing AQ call manually. Add switch filter for allmulticast mode when vf-true-promisc-support is enabled. The same filter is added regardless of the flag - it doesn't matter for this case. Remove unnecessary fields in switch structure. From now on book keeping will be done by ice_add_rule_internal(). Refactor unnecessarily passed function arguments. To test: 1) Create 2 VM's, and two VF's. Attach VF's to VM's. 2) Enable promiscuous mode on both of them and check if traffic is seen on both of them. Signed-off-by: Michal Wilczynski <michal.wilczynski@intel.com> Tested-by: Marek Szlosek <marek.szlosek@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
parent
623cd87006
commit
d7393425e7
@ -248,8 +248,6 @@ struct ice_sw {
|
||||
struct ice_pf *pf;
|
||||
u16 sw_id; /* switch ID for this switch */
|
||||
u16 bridge_mode; /* VEB/VEPA/Port Virtualizer */
|
||||
struct ice_vsi *dflt_vsi; /* default VSI for this switch */
|
||||
u8 dflt_vsi_ena:1; /* true if above dflt_vsi is enabled */
|
||||
};
|
||||
|
||||
enum ice_pf_state {
|
||||
|
@ -133,8 +133,8 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
|
||||
if (ice_vsi_add_vlan_zero(uplink_vsi))
|
||||
goto err_def_rx;
|
||||
|
||||
if (!ice_is_dflt_vsi_in_use(uplink_vsi->vsw)) {
|
||||
if (ice_set_dflt_vsi(uplink_vsi->vsw, uplink_vsi))
|
||||
if (!ice_is_dflt_vsi_in_use(uplink_vsi->port_info)) {
|
||||
if (ice_set_dflt_vsi(uplink_vsi))
|
||||
goto err_def_rx;
|
||||
rule_added = true;
|
||||
}
|
||||
@ -151,7 +151,7 @@ err_override_control:
|
||||
ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override);
|
||||
err_override_uplink:
|
||||
if (rule_added)
|
||||
ice_clear_dflt_vsi(uplink_vsi->vsw);
|
||||
ice_clear_dflt_vsi(uplink_vsi);
|
||||
err_def_rx:
|
||||
ice_fltr_add_mac_and_broadcast(uplink_vsi,
|
||||
uplink_vsi->port_info->mac.perm_addr,
|
||||
@ -411,7 +411,7 @@ static void ice_eswitch_release_env(struct ice_pf *pf)
|
||||
|
||||
ice_vsi_update_security(ctrl_vsi, ice_vsi_ctx_clear_allow_override);
|
||||
ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override);
|
||||
ice_clear_dflt_vsi(uplink_vsi->vsw);
|
||||
ice_clear_dflt_vsi(uplink_vsi);
|
||||
ice_fltr_add_mac_and_broadcast(uplink_vsi,
|
||||
uplink_vsi->port_info->mac.perm_addr,
|
||||
ICE_FWD_TO_VSI);
|
||||
|
@ -1292,7 +1292,7 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
|
||||
* promiscuous mode because it's not supported
|
||||
*/
|
||||
if (test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, change_flags) &&
|
||||
ice_is_any_vf_in_promisc(pf)) {
|
||||
ice_is_any_vf_in_unicast_promisc(pf)) {
|
||||
dev_err(dev, "Changing vf-true-promisc-support flag while VF(s) are in promiscuous mode not supported\n");
|
||||
/* toggle bit back to previous state */
|
||||
change_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags);
|
||||
|
@ -3006,8 +3006,8 @@ int ice_vsi_release(struct ice_vsi *vsi)
|
||||
}
|
||||
}
|
||||
|
||||
if (ice_is_vsi_dflt_vsi(pf->first_sw, vsi))
|
||||
ice_clear_dflt_vsi(pf->first_sw);
|
||||
if (ice_is_vsi_dflt_vsi(vsi))
|
||||
ice_clear_dflt_vsi(vsi);
|
||||
ice_fltr_remove_all(vsi);
|
||||
ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
|
||||
err = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx);
|
||||
@ -3690,116 +3690,97 @@ void ice_update_rx_ring_stats(struct ice_rx_ring *rx_ring, u64 pkts, u64 bytes)
|
||||
|
||||
/**
|
||||
* ice_is_dflt_vsi_in_use - check if the default forwarding VSI is being used
|
||||
* @sw: switch to check if its default forwarding VSI is free
|
||||
* @pi: port info of the switch with default VSI
|
||||
*
|
||||
* Return true if the default forwarding VSI is already being used, else returns
|
||||
* false signalling that it's available to use.
|
||||
* Return true if the there is a single VSI in default forwarding VSI list
|
||||
*/
|
||||
bool ice_is_dflt_vsi_in_use(struct ice_sw *sw)
|
||||
bool ice_is_dflt_vsi_in_use(struct ice_port_info *pi)
|
||||
{
|
||||
return (sw->dflt_vsi && sw->dflt_vsi_ena);
|
||||
bool exists = false;
|
||||
|
||||
ice_check_if_dflt_vsi(pi, 0, &exists);
|
||||
return exists;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_is_vsi_dflt_vsi - check if the VSI passed in is the default VSI
|
||||
* @sw: switch for the default forwarding VSI to compare against
|
||||
* @vsi: VSI to compare against default forwarding VSI
|
||||
*
|
||||
* If this VSI passed in is the default forwarding VSI then return true, else
|
||||
* return false
|
||||
*/
|
||||
bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi)
|
||||
bool ice_is_vsi_dflt_vsi(struct ice_vsi *vsi)
|
||||
{
|
||||
return (sw->dflt_vsi == vsi && sw->dflt_vsi_ena);
|
||||
return ice_check_if_dflt_vsi(vsi->port_info, vsi->idx, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_set_dflt_vsi - set the default forwarding VSI
|
||||
* @sw: switch used to assign the default forwarding VSI
|
||||
* @vsi: VSI getting set as the default forwarding VSI on the switch
|
||||
*
|
||||
* If the VSI passed in is already the default VSI and it's enabled just return
|
||||
* success.
|
||||
*
|
||||
* If there is already a default VSI on the switch and it's enabled then return
|
||||
* -EEXIST since there can only be one default VSI per switch.
|
||||
*
|
||||
* Otherwise try to set the VSI passed in as the switch's default VSI and
|
||||
* return the result.
|
||||
* Otherwise try to set the VSI passed in as the switch's default VSI and
|
||||
* return the result.
|
||||
*/
|
||||
int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi)
|
||||
int ice_set_dflt_vsi(struct ice_vsi *vsi)
|
||||
{
|
||||
struct device *dev;
|
||||
int status;
|
||||
|
||||
if (!sw || !vsi)
|
||||
if (!vsi)
|
||||
return -EINVAL;
|
||||
|
||||
dev = ice_pf_to_dev(vsi->back);
|
||||
|
||||
/* the VSI passed in is already the default VSI */
|
||||
if (ice_is_vsi_dflt_vsi(sw, vsi)) {
|
||||
if (ice_is_vsi_dflt_vsi(vsi)) {
|
||||
dev_dbg(dev, "VSI %d passed in is already the default forwarding VSI, nothing to do\n",
|
||||
vsi->vsi_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* another VSI is already the default VSI for this switch */
|
||||
if (ice_is_dflt_vsi_in_use(sw)) {
|
||||
dev_err(dev, "Default forwarding VSI %d already in use, disable it and try again\n",
|
||||
sw->dflt_vsi->vsi_num);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
status = ice_cfg_dflt_vsi(&vsi->back->hw, vsi->idx, true, ICE_FLTR_RX);
|
||||
status = ice_cfg_dflt_vsi(vsi->port_info, vsi->idx, true, ICE_FLTR_RX);
|
||||
if (status) {
|
||||
dev_err(dev, "Failed to set VSI %d as the default forwarding VSI, error %d\n",
|
||||
vsi->vsi_num, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
sw->dflt_vsi = vsi;
|
||||
sw->dflt_vsi_ena = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_clear_dflt_vsi - clear the default forwarding VSI
|
||||
* @sw: switch used to clear the default VSI
|
||||
* @vsi: VSI to remove from filter list
|
||||
*
|
||||
* If the switch has no default VSI or it's not enabled then return error.
|
||||
*
|
||||
* Otherwise try to clear the default VSI and return the result.
|
||||
*/
|
||||
int ice_clear_dflt_vsi(struct ice_sw *sw)
|
||||
int ice_clear_dflt_vsi(struct ice_vsi *vsi)
|
||||
{
|
||||
struct ice_vsi *dflt_vsi;
|
||||
struct device *dev;
|
||||
int status;
|
||||
|
||||
if (!sw)
|
||||
if (!vsi)
|
||||
return -EINVAL;
|
||||
|
||||
dev = ice_pf_to_dev(sw->pf);
|
||||
|
||||
dflt_vsi = sw->dflt_vsi;
|
||||
dev = ice_pf_to_dev(vsi->back);
|
||||
|
||||
/* there is no default VSI configured */
|
||||
if (!ice_is_dflt_vsi_in_use(sw))
|
||||
if (!ice_is_dflt_vsi_in_use(vsi->port_info))
|
||||
return -ENODEV;
|
||||
|
||||
status = ice_cfg_dflt_vsi(&dflt_vsi->back->hw, dflt_vsi->idx, false,
|
||||
status = ice_cfg_dflt_vsi(vsi->port_info, vsi->idx, false,
|
||||
ICE_FLTR_RX);
|
||||
if (status) {
|
||||
dev_err(dev, "Failed to clear the default forwarding VSI %d, error %d\n",
|
||||
dflt_vsi->vsi_num, status);
|
||||
vsi->vsi_num, status);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
sw->dflt_vsi = NULL;
|
||||
sw->dflt_vsi_ena = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -102,13 +102,10 @@ int ice_vsi_cfg_mac_fltr(struct ice_vsi *vsi, const u8 *macaddr, bool set);
|
||||
|
||||
bool ice_is_safe_mode(struct ice_pf *pf);
|
||||
bool ice_is_rdma_ena(struct ice_pf *pf);
|
||||
bool ice_is_dflt_vsi_in_use(struct ice_sw *sw);
|
||||
|
||||
bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi);
|
||||
|
||||
int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi);
|
||||
|
||||
int ice_clear_dflt_vsi(struct ice_sw *sw);
|
||||
bool ice_is_dflt_vsi_in_use(struct ice_port_info *pi);
|
||||
bool ice_is_vsi_dflt_vsi(struct ice_vsi *vsi);
|
||||
int ice_set_dflt_vsi(struct ice_vsi *vsi);
|
||||
int ice_clear_dflt_vsi(struct ice_vsi *vsi);
|
||||
int ice_set_min_bw_limit(struct ice_vsi *vsi, u64 min_tx_rate);
|
||||
int ice_set_max_bw_limit(struct ice_vsi *vsi, u64 max_tx_rate);
|
||||
int ice_get_link_speed_kbps(struct ice_vsi *vsi);
|
||||
|
@ -410,8 +410,8 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
|
||||
clear_bit(ICE_VSI_PROMISC_CHANGED, vsi->state);
|
||||
if (vsi->current_netdev_flags & IFF_PROMISC) {
|
||||
/* Apply Rx filter rule to get traffic from wire */
|
||||
if (!ice_is_dflt_vsi_in_use(pf->first_sw)) {
|
||||
err = ice_set_dflt_vsi(pf->first_sw, vsi);
|
||||
if (!ice_is_dflt_vsi_in_use(vsi->port_info)) {
|
||||
err = ice_set_dflt_vsi(vsi);
|
||||
if (err && err != -EEXIST) {
|
||||
netdev_err(netdev, "Error %d setting default VSI %i Rx rule\n",
|
||||
err, vsi->vsi_num);
|
||||
@ -424,8 +424,8 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
|
||||
}
|
||||
} else {
|
||||
/* Clear Rx filter to remove traffic from wire */
|
||||
if (ice_is_vsi_dflt_vsi(pf->first_sw, vsi)) {
|
||||
err = ice_clear_dflt_vsi(pf->first_sw);
|
||||
if (ice_is_vsi_dflt_vsi(vsi)) {
|
||||
err = ice_clear_dflt_vsi(vsi);
|
||||
if (err) {
|
||||
netdev_err(netdev, "Error %d clearing default VSI %i Rx rule\n",
|
||||
err, vsi->vsi_num);
|
||||
@ -6990,12 +6990,6 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
|
||||
goto err_init_ctrlq;
|
||||
}
|
||||
|
||||
if (pf->first_sw->dflt_vsi_ena)
|
||||
dev_info(dev, "Clearing default VSI, re-enable after reset completes\n");
|
||||
/* clear the default VSI configuration if it exists */
|
||||
pf->first_sw->dflt_vsi = NULL;
|
||||
pf->first_sw->dflt_vsi_ena = false;
|
||||
|
||||
ice_clear_pxe_mode(hw);
|
||||
|
||||
err = ice_init_nvm(hw);
|
||||
|
@ -1762,7 +1762,8 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
|
||||
lkup_type == ICE_SW_LKUP_ETHERTYPE ||
|
||||
lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
|
||||
lkup_type == ICE_SW_LKUP_PROMISC ||
|
||||
lkup_type == ICE_SW_LKUP_PROMISC_VLAN) {
|
||||
lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
|
||||
lkup_type == ICE_SW_LKUP_DFLT) {
|
||||
sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
|
||||
} else if (lkup_type == ICE_SW_LKUP_VLAN) {
|
||||
sw_buf->res_type =
|
||||
@ -2255,8 +2256,6 @@ ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
|
||||
pi->sw_id = swid;
|
||||
pi->pf_vf_num = pf_vf_num;
|
||||
pi->is_vf = is_vf;
|
||||
pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
|
||||
pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
|
||||
break;
|
||||
default:
|
||||
ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n");
|
||||
@ -2691,7 +2690,8 @@ ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
|
||||
lkup_type == ICE_SW_LKUP_ETHERTYPE ||
|
||||
lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
|
||||
lkup_type == ICE_SW_LKUP_PROMISC ||
|
||||
lkup_type == ICE_SW_LKUP_PROMISC_VLAN)
|
||||
lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
|
||||
lkup_type == ICE_SW_LKUP_DFLT)
|
||||
rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
|
||||
ICE_AQC_SW_RULES_T_VSI_LIST_SET;
|
||||
else if (lkup_type == ICE_SW_LKUP_VLAN)
|
||||
@ -3873,7 +3873,7 @@ ice_rem_adv_rule_info(struct ice_hw *hw, struct list_head *rule_head)
|
||||
|
||||
/**
|
||||
* ice_cfg_dflt_vsi - change state of VSI to set/clear default
|
||||
* @hw: pointer to the hardware structure
|
||||
* @pi: pointer to the port_info structure
|
||||
* @vsi_handle: VSI handle to set as default
|
||||
* @set: true to add the above mentioned switch rule, false to remove it
|
||||
* @direction: ICE_FLTR_RX or ICE_FLTR_TX
|
||||
@ -3881,80 +3881,101 @@ ice_rem_adv_rule_info(struct ice_hw *hw, struct list_head *rule_head)
|
||||
* add filter rule to set/unset given VSI as default VSI for the switch
|
||||
* (represented by swid)
|
||||
*/
|
||||
int ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction)
|
||||
int
|
||||
ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
|
||||
u8 direction)
|
||||
{
|
||||
struct ice_sw_rule_lkup_rx_tx *s_rule;
|
||||
struct ice_fltr_list_entry f_list_entry;
|
||||
struct ice_fltr_info f_info;
|
||||
enum ice_adminq_opc opcode;
|
||||
u16 s_rule_size;
|
||||
struct ice_hw *hw = pi->hw;
|
||||
u16 hw_vsi_id;
|
||||
int status;
|
||||
|
||||
if (!ice_is_vsi_valid(hw, vsi_handle))
|
||||
return -EINVAL;
|
||||
|
||||
hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
|
||||
|
||||
s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule) :
|
||||
ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule);
|
||||
|
||||
s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
|
||||
if (!s_rule)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(&f_info, 0, sizeof(f_info));
|
||||
|
||||
f_info.lkup_type = ICE_SW_LKUP_DFLT;
|
||||
f_info.flag = direction;
|
||||
f_info.fltr_act = ICE_FWD_TO_VSI;
|
||||
f_info.fwd_id.hw_vsi_id = hw_vsi_id;
|
||||
f_info.vsi_handle = vsi_handle;
|
||||
|
||||
if (f_info.flag & ICE_FLTR_RX) {
|
||||
f_info.src = hw->port_info->lport;
|
||||
f_info.src_id = ICE_SRC_ID_LPORT;
|
||||
if (!set)
|
||||
f_info.fltr_rule_id =
|
||||
hw->port_info->dflt_rx_vsi_rule_id;
|
||||
} else if (f_info.flag & ICE_FLTR_TX) {
|
||||
f_info.src_id = ICE_SRC_ID_VSI;
|
||||
f_info.src = hw_vsi_id;
|
||||
if (!set)
|
||||
f_info.fltr_rule_id =
|
||||
hw->port_info->dflt_tx_vsi_rule_id;
|
||||
}
|
||||
f_list_entry.fltr_info = f_info;
|
||||
|
||||
if (set)
|
||||
opcode = ice_aqc_opc_add_sw_rules;
|
||||
status = ice_add_rule_internal(hw, ICE_SW_LKUP_DFLT,
|
||||
&f_list_entry);
|
||||
else
|
||||
opcode = ice_aqc_opc_remove_sw_rules;
|
||||
status = ice_remove_rule_internal(hw, ICE_SW_LKUP_DFLT,
|
||||
&f_list_entry);
|
||||
|
||||
ice_fill_sw_rule(hw, &f_info, s_rule, opcode);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL);
|
||||
if (status || !(f_info.flag & ICE_FLTR_TX_RX))
|
||||
goto out;
|
||||
if (set) {
|
||||
u16 index = le16_to_cpu(s_rule->index);
|
||||
/**
|
||||
* ice_vsi_uses_fltr - Determine if given VSI uses specified filter
|
||||
* @fm_entry: filter entry to inspect
|
||||
* @vsi_handle: VSI handle to compare with filter info
|
||||
*/
|
||||
static bool
|
||||
ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
|
||||
{
|
||||
return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
|
||||
fm_entry->fltr_info.vsi_handle == vsi_handle) ||
|
||||
(fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
|
||||
fm_entry->vsi_list_info &&
|
||||
(test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
|
||||
}
|
||||
|
||||
if (f_info.flag & ICE_FLTR_TX) {
|
||||
hw->port_info->dflt_tx_vsi_num = hw_vsi_id;
|
||||
hw->port_info->dflt_tx_vsi_rule_id = index;
|
||||
} else if (f_info.flag & ICE_FLTR_RX) {
|
||||
hw->port_info->dflt_rx_vsi_num = hw_vsi_id;
|
||||
hw->port_info->dflt_rx_vsi_rule_id = index;
|
||||
}
|
||||
} else {
|
||||
if (f_info.flag & ICE_FLTR_TX) {
|
||||
hw->port_info->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
|
||||
hw->port_info->dflt_tx_vsi_rule_id = ICE_INVAL_ACT;
|
||||
} else if (f_info.flag & ICE_FLTR_RX) {
|
||||
hw->port_info->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
|
||||
hw->port_info->dflt_rx_vsi_rule_id = ICE_INVAL_ACT;
|
||||
/**
|
||||
* ice_check_if_dflt_vsi - check if VSI is default VSI
|
||||
* @pi: pointer to the port_info structure
|
||||
* @vsi_handle: vsi handle to check for in filter list
|
||||
* @rule_exists: indicates if there are any VSI's in the rule list
|
||||
*
|
||||
* checks if the VSI is in a default VSI list, and also indicates
|
||||
* if the default VSI list is empty
|
||||
*/
|
||||
bool
|
||||
ice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle,
|
||||
bool *rule_exists)
|
||||
{
|
||||
struct ice_fltr_mgmt_list_entry *fm_entry;
|
||||
struct ice_sw_recipe *recp_list;
|
||||
struct list_head *rule_head;
|
||||
struct mutex *rule_lock; /* Lock to protect filter rule list */
|
||||
bool ret = false;
|
||||
|
||||
recp_list = &pi->hw->switch_info->recp_list[ICE_SW_LKUP_DFLT];
|
||||
rule_lock = &recp_list->filt_rule_lock;
|
||||
rule_head = &recp_list->filt_rules;
|
||||
|
||||
mutex_lock(rule_lock);
|
||||
|
||||
if (rule_exists && !list_empty(rule_head))
|
||||
*rule_exists = true;
|
||||
|
||||
list_for_each_entry(fm_entry, rule_head, list_entry) {
|
||||
if (ice_vsi_uses_fltr(fm_entry, vsi_handle)) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
devm_kfree(ice_hw_to_dev(hw), s_rule);
|
||||
return status;
|
||||
mutex_unlock(rule_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4073,21 +4094,6 @@ int ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_vsi_uses_fltr - Determine if given VSI uses specified filter
|
||||
* @fm_entry: filter entry to inspect
|
||||
* @vsi_handle: VSI handle to compare with filter info
|
||||
*/
|
||||
static bool
|
||||
ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
|
||||
{
|
||||
return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
|
||||
fm_entry->fltr_info.vsi_handle == vsi_handle) ||
|
||||
(fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
|
||||
fm_entry->vsi_list_info &&
|
||||
(test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
|
||||
* @hw: pointer to the hardware structure
|
||||
|
@ -359,7 +359,13 @@ int ice_cfg_rdma_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable);
|
||||
void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle);
|
||||
|
||||
/* Promisc/defport setup for VSIs */
|
||||
int ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction);
|
||||
int
|
||||
ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
|
||||
u8 direction);
|
||||
bool
|
||||
ice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle,
|
||||
bool *rule_exists);
|
||||
|
||||
int
|
||||
ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
|
||||
u16 vid);
|
||||
|
@ -693,10 +693,6 @@ struct ice_port_info {
|
||||
#define ICE_SCHED_PORT_STATE_READY 0x1
|
||||
u8 lport;
|
||||
#define ICE_LPORT_MASK 0xff
|
||||
u16 dflt_tx_vsi_rule_id;
|
||||
u16 dflt_tx_vsi_num;
|
||||
u16 dflt_rx_vsi_rule_id;
|
||||
u16 dflt_rx_vsi_num;
|
||||
struct ice_fc_info fc;
|
||||
struct ice_mac_info mac;
|
||||
struct ice_phy_info phy;
|
||||
|
@ -271,13 +271,14 @@ static int ice_vf_rebuild_vsi(struct ice_vf *vf)
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_is_any_vf_in_promisc - check if any VF(s) are in promiscuous mode
|
||||
* ice_is_any_vf_in_unicast_promisc - check if any VF(s)
|
||||
* are in unicast promiscuous mode
|
||||
* @pf: PF structure for accessing VF(s)
|
||||
*
|
||||
* Return false if no VF(s) are in unicast and/or multicast promiscuous mode,
|
||||
* Return false if no VF(s) are in unicast promiscuous mode,
|
||||
* else return true
|
||||
*/
|
||||
bool ice_is_any_vf_in_promisc(struct ice_pf *pf)
|
||||
bool ice_is_any_vf_in_unicast_promisc(struct ice_pf *pf)
|
||||
{
|
||||
bool is_vf_promisc = false;
|
||||
struct ice_vf *vf;
|
||||
@ -286,8 +287,7 @@ bool ice_is_any_vf_in_promisc(struct ice_pf *pf)
|
||||
rcu_read_lock();
|
||||
ice_for_each_vf_rcu(pf, bkt, vf) {
|
||||
/* found a VF that has promiscuous mode configured */
|
||||
if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) ||
|
||||
test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) {
|
||||
if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) {
|
||||
is_vf_promisc = true;
|
||||
break;
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf);
|
||||
bool ice_is_vf_disabled(struct ice_vf *vf);
|
||||
int ice_check_vf_ready_for_cfg(struct ice_vf *vf);
|
||||
void ice_set_vf_state_qs_dis(struct ice_vf *vf);
|
||||
bool ice_is_any_vf_in_promisc(struct ice_pf *pf);
|
||||
bool ice_is_any_vf_in_unicast_promisc(struct ice_pf *pf);
|
||||
int
|
||||
ice_vf_set_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m);
|
||||
int
|
||||
@ -260,7 +260,7 @@ static inline void ice_set_vf_state_qs_dis(struct ice_vf *vf)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool ice_is_any_vf_in_promisc(struct ice_pf *pf)
|
||||
static inline bool ice_is_any_vf_in_unicast_promisc(struct ice_pf *pf)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -999,6 +999,7 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
|
||||
int mcast_err = 0, ucast_err = 0;
|
||||
struct ice_pf *pf = vf->pf;
|
||||
struct ice_vsi *vsi;
|
||||
u8 mcast_m, ucast_m;
|
||||
struct device *dev;
|
||||
int ret = 0;
|
||||
|
||||
@ -1045,39 +1046,40 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
|
||||
goto error_param;
|
||||
}
|
||||
|
||||
if (!test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags)) {
|
||||
bool set_dflt_vsi = alluni || allmulti;
|
||||
if (ice_vf_is_port_vlan_ena(vf) ||
|
||||
ice_vsi_has_non_zero_vlans(vsi)) {
|
||||
mcast_m = ICE_MCAST_VLAN_PROMISC_BITS;
|
||||
ucast_m = ICE_UCAST_VLAN_PROMISC_BITS;
|
||||
} else {
|
||||
mcast_m = ICE_MCAST_PROMISC_BITS;
|
||||
ucast_m = ICE_UCAST_PROMISC_BITS;
|
||||
}
|
||||
|
||||
if (set_dflt_vsi && !ice_is_dflt_vsi_in_use(pf->first_sw))
|
||||
/* only attempt to set the default forwarding VSI if
|
||||
* it's not currently set
|
||||
*/
|
||||
ret = ice_set_dflt_vsi(pf->first_sw, vsi);
|
||||
else if (!set_dflt_vsi &&
|
||||
ice_is_vsi_dflt_vsi(pf->first_sw, vsi))
|
||||
/* only attempt to free the default forwarding VSI if we
|
||||
* are the owner
|
||||
*/
|
||||
ret = ice_clear_dflt_vsi(pf->first_sw);
|
||||
if (!test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags)) {
|
||||
if (alluni) {
|
||||
/* in this case we're turning on promiscuous mode */
|
||||
ret = ice_set_dflt_vsi(vsi);
|
||||
} else {
|
||||
/* in this case we're turning off promiscuous mode */
|
||||
if (ice_is_dflt_vsi_in_use(vsi->port_info))
|
||||
ret = ice_clear_dflt_vsi(vsi);
|
||||
}
|
||||
|
||||
/* in this case we're turning on/off only
|
||||
* allmulticast
|
||||
*/
|
||||
if (allmulti)
|
||||
mcast_err = ice_vf_set_vsi_promisc(vf, vsi, mcast_m);
|
||||
else
|
||||
mcast_err = ice_vf_clear_vsi_promisc(vf, vsi, mcast_m);
|
||||
|
||||
if (ret) {
|
||||
dev_err(dev, "%sable VF %d as the default VSI failed, error %d\n",
|
||||
set_dflt_vsi ? "en" : "dis", vf->vf_id, ret);
|
||||
dev_err(dev, "Turning on/off promiscuous mode for VF %d failed, error: %d\n",
|
||||
vf->vf_id, ret);
|
||||
v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
|
||||
goto error_param;
|
||||
}
|
||||
} else {
|
||||
u8 mcast_m, ucast_m;
|
||||
|
||||
if (ice_vf_is_port_vlan_ena(vf) ||
|
||||
ice_vsi_has_non_zero_vlans(vsi)) {
|
||||
mcast_m = ICE_MCAST_VLAN_PROMISC_BITS;
|
||||
ucast_m = ICE_UCAST_VLAN_PROMISC_BITS;
|
||||
} else {
|
||||
mcast_m = ICE_MCAST_PROMISC_BITS;
|
||||
ucast_m = ICE_UCAST_PROMISC_BITS;
|
||||
}
|
||||
|
||||
if (alluni)
|
||||
ucast_err = ice_vf_set_vsi_promisc(vf, vsi, ucast_m);
|
||||
else
|
||||
@ -1102,6 +1104,9 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
|
||||
vf->vf_states))
|
||||
dev_info(dev, "VF %u successfully unset multicast promiscuous mode\n",
|
||||
vf->vf_id);
|
||||
} else {
|
||||
dev_err(dev, "Error while modifying multicast promiscuous mode for VF %u, error: %d\n",
|
||||
vf->vf_id, mcast_err);
|
||||
}
|
||||
|
||||
if (!ucast_err) {
|
||||
@ -1114,6 +1119,9 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
|
||||
vf->vf_states))
|
||||
dev_info(dev, "VF %u successfully unset unicast promiscuous mode\n",
|
||||
vf->vf_id);
|
||||
} else {
|
||||
dev_err(dev, "Error while modifying unicast promiscuous mode for VF %u, error: %d\n",
|
||||
vf->vf_id, ucast_err);
|
||||
}
|
||||
|
||||
error_param:
|
||||
|
Loading…
Reference in New Issue
Block a user