提交 d7393425 编写于 作者: M Michal Wilczynski 提交者: Tony Nguyen

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: NMichal Wilczynski <michal.wilczynski@intel.com>
Tested-by: NMarek Szlosek <marek.szlosek@intel.com>
Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
上级 623cd870
...@@ -248,8 +248,6 @@ struct ice_sw { ...@@ -248,8 +248,6 @@ struct ice_sw {
struct ice_pf *pf; struct ice_pf *pf;
u16 sw_id; /* switch ID for this switch */ u16 sw_id; /* switch ID for this switch */
u16 bridge_mode; /* VEB/VEPA/Port Virtualizer */ 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 { enum ice_pf_state {
......
...@@ -133,8 +133,8 @@ static int ice_eswitch_setup_env(struct ice_pf *pf) ...@@ -133,8 +133,8 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
if (ice_vsi_add_vlan_zero(uplink_vsi)) if (ice_vsi_add_vlan_zero(uplink_vsi))
goto err_def_rx; goto err_def_rx;
if (!ice_is_dflt_vsi_in_use(uplink_vsi->vsw)) { if (!ice_is_dflt_vsi_in_use(uplink_vsi->port_info)) {
if (ice_set_dflt_vsi(uplink_vsi->vsw, uplink_vsi)) if (ice_set_dflt_vsi(uplink_vsi))
goto err_def_rx; goto err_def_rx;
rule_added = true; rule_added = true;
} }
...@@ -151,7 +151,7 @@ static int ice_eswitch_setup_env(struct ice_pf *pf) ...@@ -151,7 +151,7 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override); ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override);
err_override_uplink: err_override_uplink:
if (rule_added) if (rule_added)
ice_clear_dflt_vsi(uplink_vsi->vsw); ice_clear_dflt_vsi(uplink_vsi);
err_def_rx: err_def_rx:
ice_fltr_add_mac_and_broadcast(uplink_vsi, ice_fltr_add_mac_and_broadcast(uplink_vsi,
uplink_vsi->port_info->mac.perm_addr, uplink_vsi->port_info->mac.perm_addr,
...@@ -411,7 +411,7 @@ static void ice_eswitch_release_env(struct ice_pf *pf) ...@@ -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(ctrl_vsi, ice_vsi_ctx_clear_allow_override);
ice_vsi_update_security(uplink_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, ice_fltr_add_mac_and_broadcast(uplink_vsi,
uplink_vsi->port_info->mac.perm_addr, uplink_vsi->port_info->mac.perm_addr,
ICE_FWD_TO_VSI); ICE_FWD_TO_VSI);
......
...@@ -1292,7 +1292,7 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags) ...@@ -1292,7 +1292,7 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
* promiscuous mode because it's not supported * promiscuous mode because it's not supported
*/ */
if (test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, change_flags) && 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"); 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 */ /* toggle bit back to previous state */
change_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags); change_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags);
......
...@@ -3006,8 +3006,8 @@ int ice_vsi_release(struct ice_vsi *vsi) ...@@ -3006,8 +3006,8 @@ int ice_vsi_release(struct ice_vsi *vsi)
} }
} }
if (ice_is_vsi_dflt_vsi(pf->first_sw, vsi)) if (ice_is_vsi_dflt_vsi(vsi))
ice_clear_dflt_vsi(pf->first_sw); ice_clear_dflt_vsi(vsi);
ice_fltr_remove_all(vsi); ice_fltr_remove_all(vsi);
ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
err = ice_rm_vsi_rdma_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) ...@@ -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 * 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 * Return true if the there is a single VSI in default forwarding VSI list
* false signalling that it's available to use.
*/ */
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 * 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 * @vsi: VSI to compare against default forwarding VSI
* *
* If this VSI passed in is the default forwarding VSI then return true, else * If this VSI passed in is the default forwarding VSI then return true, else
* return false * 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 * 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 * @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 * If the VSI passed in is already the default VSI and it's enabled just return
* success. * 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 * Otherwise try to set the VSI passed in as the switch's default VSI and
* return the result. * 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; struct device *dev;
int status; int status;
if (!sw || !vsi) if (!vsi)
return -EINVAL; return -EINVAL;
dev = ice_pf_to_dev(vsi->back); dev = ice_pf_to_dev(vsi->back);
/* the VSI passed in is already the default VSI */ /* 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", dev_dbg(dev, "VSI %d passed in is already the default forwarding VSI, nothing to do\n",
vsi->vsi_num); vsi->vsi_num);
return 0; return 0;
} }
/* another VSI is already the default VSI for this switch */ status = ice_cfg_dflt_vsi(vsi->port_info, vsi->idx, true, ICE_FLTR_RX);
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);
if (status) { if (status) {
dev_err(dev, "Failed to set VSI %d as the default forwarding VSI, error %d\n", dev_err(dev, "Failed to set VSI %d as the default forwarding VSI, error %d\n",
vsi->vsi_num, status); vsi->vsi_num, status);
return status; return status;
} }
sw->dflt_vsi = vsi;
sw->dflt_vsi_ena = true;
return 0; return 0;
} }
/** /**
* ice_clear_dflt_vsi - clear the default forwarding VSI * 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. * 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. * 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; struct device *dev;
int status; int status;
if (!sw) if (!vsi)
return -EINVAL; return -EINVAL;
dev = ice_pf_to_dev(sw->pf); dev = ice_pf_to_dev(vsi->back);
dflt_vsi = sw->dflt_vsi;
/* there is no default VSI configured */ /* 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; 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); ICE_FLTR_RX);
if (status) { if (status) {
dev_err(dev, "Failed to clear the default forwarding VSI %d, error %d\n", 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; return -EIO;
} }
sw->dflt_vsi = NULL;
sw->dflt_vsi_ena = false;
return 0; return 0;
} }
......
...@@ -102,13 +102,10 @@ int ice_vsi_cfg_mac_fltr(struct ice_vsi *vsi, const u8 *macaddr, bool set); ...@@ -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_safe_mode(struct ice_pf *pf);
bool ice_is_rdma_ena(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_dflt_vsi_in_use(struct ice_port_info *pi);
bool ice_is_vsi_dflt_vsi(struct ice_vsi *vsi);
bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, 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_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi);
int ice_clear_dflt_vsi(struct ice_sw *sw);
int ice_set_min_bw_limit(struct ice_vsi *vsi, u64 min_tx_rate); 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_set_max_bw_limit(struct ice_vsi *vsi, u64 max_tx_rate);
int ice_get_link_speed_kbps(struct ice_vsi *vsi); int ice_get_link_speed_kbps(struct ice_vsi *vsi);
......
...@@ -410,8 +410,8 @@ static int ice_vsi_sync_fltr(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); clear_bit(ICE_VSI_PROMISC_CHANGED, vsi->state);
if (vsi->current_netdev_flags & IFF_PROMISC) { if (vsi->current_netdev_flags & IFF_PROMISC) {
/* Apply Rx filter rule to get traffic from wire */ /* Apply Rx filter rule to get traffic from wire */
if (!ice_is_dflt_vsi_in_use(pf->first_sw)) { if (!ice_is_dflt_vsi_in_use(vsi->port_info)) {
err = ice_set_dflt_vsi(pf->first_sw, vsi); err = ice_set_dflt_vsi(vsi);
if (err && err != -EEXIST) { if (err && err != -EEXIST) {
netdev_err(netdev, "Error %d setting default VSI %i Rx rule\n", netdev_err(netdev, "Error %d setting default VSI %i Rx rule\n",
err, vsi->vsi_num); err, vsi->vsi_num);
...@@ -424,8 +424,8 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi) ...@@ -424,8 +424,8 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
} }
} else { } else {
/* Clear Rx filter to remove traffic from wire */ /* Clear Rx filter to remove traffic from wire */
if (ice_is_vsi_dflt_vsi(pf->first_sw, vsi)) { if (ice_is_vsi_dflt_vsi(vsi)) {
err = ice_clear_dflt_vsi(pf->first_sw); err = ice_clear_dflt_vsi(vsi);
if (err) { if (err) {
netdev_err(netdev, "Error %d clearing default VSI %i Rx rule\n", netdev_err(netdev, "Error %d clearing default VSI %i Rx rule\n",
err, vsi->vsi_num); err, vsi->vsi_num);
...@@ -6990,12 +6990,6 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) ...@@ -6990,12 +6990,6 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
goto err_init_ctrlq; 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); ice_clear_pxe_mode(hw);
err = ice_init_nvm(hw); err = ice_init_nvm(hw);
......
...@@ -1762,7 +1762,8 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id, ...@@ -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 ||
lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
lkup_type == ICE_SW_LKUP_PROMISC || 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); sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
} else if (lkup_type == ICE_SW_LKUP_VLAN) { } else if (lkup_type == ICE_SW_LKUP_VLAN) {
sw_buf->res_type = sw_buf->res_type =
...@@ -2255,8 +2256,6 @@ ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 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->sw_id = swid;
pi->pf_vf_num = pf_vf_num; pi->pf_vf_num = pf_vf_num;
pi->is_vf = is_vf; pi->is_vf = is_vf;
pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
break; break;
default: default:
ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n"); 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, ...@@ -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 ||
lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
lkup_type == ICE_SW_LKUP_PROMISC || 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 : rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
ICE_AQC_SW_RULES_T_VSI_LIST_SET; ICE_AQC_SW_RULES_T_VSI_LIST_SET;
else if (lkup_type == ICE_SW_LKUP_VLAN) 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) ...@@ -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 * 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 * @vsi_handle: VSI handle to set as default
* @set: true to add the above mentioned switch rule, false to remove it * @set: true to add the above mentioned switch rule, false to remove it
* @direction: ICE_FLTR_RX or ICE_FLTR_TX * @direction: ICE_FLTR_RX or ICE_FLTR_TX
...@@ -3881,25 +3881,20 @@ ice_rem_adv_rule_info(struct ice_hw *hw, struct list_head *rule_head) ...@@ -3881,25 +3881,20 @@ 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 * add filter rule to set/unset given VSI as default VSI for the switch
* (represented by swid) * (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; struct ice_fltr_info f_info;
enum ice_adminq_opc opcode; struct ice_hw *hw = pi->hw;
u16 s_rule_size;
u16 hw_vsi_id; u16 hw_vsi_id;
int status; int status;
if (!ice_is_vsi_valid(hw, vsi_handle)) if (!ice_is_vsi_valid(hw, vsi_handle))
return -EINVAL; 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); hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
if (!s_rule)
return -ENOMEM;
memset(&f_info, 0, sizeof(f_info)); memset(&f_info, 0, sizeof(f_info));
...@@ -3907,54 +3902,80 @@ int ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction) ...@@ -3907,54 +3902,80 @@ int ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction)
f_info.flag = direction; f_info.flag = direction;
f_info.fltr_act = ICE_FWD_TO_VSI; f_info.fltr_act = ICE_FWD_TO_VSI;
f_info.fwd_id.hw_vsi_id = hw_vsi_id; f_info.fwd_id.hw_vsi_id = hw_vsi_id;
f_info.vsi_handle = vsi_handle;
if (f_info.flag & ICE_FLTR_RX) { if (f_info.flag & ICE_FLTR_RX) {
f_info.src = hw->port_info->lport; f_info.src = hw->port_info->lport;
f_info.src_id = ICE_SRC_ID_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) { } else if (f_info.flag & ICE_FLTR_TX) {
f_info.src_id = ICE_SRC_ID_VSI; f_info.src_id = ICE_SRC_ID_VSI;
f_info.src = hw_vsi_id; 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) if (set)
opcode = ice_aqc_opc_add_sw_rules; status = ice_add_rule_internal(hw, ICE_SW_LKUP_DFLT,
&f_list_entry);
else 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)) * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
goto out; * @fm_entry: filter entry to inspect
if (set) { * @vsi_handle: VSI handle to compare with filter info
u16 index = le16_to_cpu(s_rule->index); */
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; * ice_check_if_dflt_vsi - check if VSI is default VSI
hw->port_info->dflt_tx_vsi_rule_id = index; * @pi: pointer to the port_info structure
} else if (f_info.flag & ICE_FLTR_RX) { * @vsi_handle: vsi handle to check for in filter list
hw->port_info->dflt_rx_vsi_num = hw_vsi_id; * @rule_exists: indicates if there are any VSI's in the rule list
hw->port_info->dflt_rx_vsi_rule_id = index; *
} * checks if the VSI is in a default VSI list, and also indicates
} else { * if the default VSI list is empty
if (f_info.flag & ICE_FLTR_TX) { */
hw->port_info->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL; bool
hw->port_info->dflt_tx_vsi_rule_id = ICE_INVAL_ACT; ice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle,
} else if (f_info.flag & ICE_FLTR_RX) { bool *rule_exists)
hw->port_info->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL; {
hw->port_info->dflt_rx_vsi_rule_id = ICE_INVAL_ACT; 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: mutex_unlock(rule_lock);
devm_kfree(ice_hw_to_dev(hw), s_rule);
return status; return ret;
} }
/** /**
...@@ -4073,21 +4094,6 @@ int ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list) ...@@ -4073,21 +4094,6 @@ int ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list)
return 0; 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 * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
* @hw: pointer to the hardware structure * @hw: pointer to the hardware structure
......
...@@ -359,7 +359,13 @@ int ice_cfg_rdma_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable); ...@@ -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); void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle);
/* Promisc/defport setup for VSIs */ /* 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 int
ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
u16 vid); u16 vid);
......
...@@ -693,10 +693,6 @@ struct ice_port_info { ...@@ -693,10 +693,6 @@ struct ice_port_info {
#define ICE_SCHED_PORT_STATE_READY 0x1 #define ICE_SCHED_PORT_STATE_READY 0x1
u8 lport; u8 lport;
#define ICE_LPORT_MASK 0xff #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_fc_info fc;
struct ice_mac_info mac; struct ice_mac_info mac;
struct ice_phy_info phy; struct ice_phy_info phy;
......
...@@ -271,13 +271,14 @@ static int ice_vf_rebuild_vsi(struct ice_vf *vf) ...@@ -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) * @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 * 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; bool is_vf_promisc = false;
struct ice_vf *vf; struct ice_vf *vf;
...@@ -286,8 +287,7 @@ bool ice_is_any_vf_in_promisc(struct ice_pf *pf) ...@@ -286,8 +287,7 @@ bool ice_is_any_vf_in_promisc(struct ice_pf *pf)
rcu_read_lock(); rcu_read_lock();
ice_for_each_vf_rcu(pf, bkt, vf) { ice_for_each_vf_rcu(pf, bkt, vf) {
/* found a VF that has promiscuous mode configured */ /* found a VF that has promiscuous mode configured */
if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) || if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) {
test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) {
is_vf_promisc = true; is_vf_promisc = true;
break; break;
} }
......
...@@ -214,7 +214,7 @@ struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf); ...@@ -214,7 +214,7 @@ struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf);
bool ice_is_vf_disabled(struct ice_vf *vf); bool ice_is_vf_disabled(struct ice_vf *vf);
int ice_check_vf_ready_for_cfg(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); 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 int
ice_vf_set_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m); ice_vf_set_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m);
int int
...@@ -260,7 +260,7 @@ static inline void ice_set_vf_state_qs_dis(struct ice_vf *vf) ...@@ -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; return false;
} }
......
...@@ -999,6 +999,7 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg) ...@@ -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; int mcast_err = 0, ucast_err = 0;
struct ice_pf *pf = vf->pf; struct ice_pf *pf = vf->pf;
struct ice_vsi *vsi; struct ice_vsi *vsi;
u8 mcast_m, ucast_m;
struct device *dev; struct device *dev;
int ret = 0; int ret = 0;
...@@ -1045,30 +1046,6 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg) ...@@ -1045,30 +1046,6 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
goto error_param; goto error_param;
} }
if (!test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags)) {
bool set_dflt_vsi = alluni || allmulti;
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 (ret) {
dev_err(dev, "%sable VF %d as the default VSI failed, error %d\n",
set_dflt_vsi ? "en" : "dis", 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) || if (ice_vf_is_port_vlan_ena(vf) ||
ice_vsi_has_non_zero_vlans(vsi)) { ice_vsi_has_non_zero_vlans(vsi)) {
mcast_m = ICE_MCAST_VLAN_PROMISC_BITS; mcast_m = ICE_MCAST_VLAN_PROMISC_BITS;
...@@ -1078,6 +1055,31 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg) ...@@ -1078,6 +1055,31 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
ucast_m = ICE_UCAST_PROMISC_BITS; ucast_m = ICE_UCAST_PROMISC_BITS;
} }
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, "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 {
if (alluni) if (alluni)
ucast_err = ice_vf_set_vsi_promisc(vf, vsi, ucast_m); ucast_err = ice_vf_set_vsi_promisc(vf, vsi, ucast_m);
else else
...@@ -1102,6 +1104,9 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg) ...@@ -1102,6 +1104,9 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
vf->vf_states)) vf->vf_states))
dev_info(dev, "VF %u successfully unset multicast promiscuous mode\n", dev_info(dev, "VF %u successfully unset multicast promiscuous mode\n",
vf->vf_id); 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) { if (!ucast_err) {
...@@ -1114,6 +1119,9 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg) ...@@ -1114,6 +1119,9 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
vf->vf_states)) vf->vf_states))
dev_info(dev, "VF %u successfully unset unicast promiscuous mode\n", dev_info(dev, "VF %u successfully unset unicast promiscuous mode\n",
vf->vf_id); 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: error_param:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册