lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 8 Jul 2020 22:55:21 +0000
From:   "Nguyen, Anthony L" <anthony.l.nguyen@...el.com>
To:     "Wang, Haiyue" <haiyue.wang@...el.com>,
        "davem@...emloft.net" <davem@...emloft.net>,
        "intel-wired-lan@...ts.osuosl.org" <intel-wired-lan@...ts.osuosl.org>,
        "kuba@...nel.org" <kuba@...nel.org>
CC:     "Zhang, Xiao" <xiao.zhang@...el.com>,
        "netdev@...r.kernel.org" <netdev@...r.kernel.org>,
        "Xing, Beilei" <beilei.xing@...el.com>,
        "Venkataramanan, Anirudh" <anirudh.venkataramanan@...el.com>
Subject: Re: [Intel-wired-lan] [net-next, v7 5/5] ice: add switch rule
 management for DCF

On Wed, 2020-07-01 at 09:25 +0800, Haiyue Wang wrote:
> The PF shall track all the outstanding switch filters (filter IDs to
> be
> precise) added by the DCF.
> 
> Upon a VF reset event, the PF shall clear all outstanding switch
> filters
> for the given VF. Upon completion of either VF or PF reset, the PF
> shall
> skip replay of filters that were added by the DCF. The PF shall
> however
> continue to replay the filters that were not added by DCF for the
> VF(s).
> 
> If the trust mode of the DCF is taken away without the DCF gracefully
> relinquishing the DCF functionality (by way appropriate virtchnl
> message
> exchanges), then the PF shall remove all switch filters that were
> added
> by the DCF. The PF shall transition back from DCF mode to regular
> mode,
> the VF shall be treated as any other untrusted VF, and the PF will
> reset
> the VF.
> 
> If a designated DCF requests AVF functionality from the same VF (VF-
> ID)
> without the DCF gracefully relinquishing the DCF functionality first
> (by
> way appropriate virtchnl message exchanges), the PF shall remove all
> the
> switch filters that were added by the DCF.
> 
> Signed-off-by: Xiao Zhang <xiao.zhang@...el.com>
> Signed-off-by: Beilei Xing <beilei.xing@...el.com>
> Signed-off-by: Haiyue Wang <haiyue.wang@...el.com>
> ---
>  drivers/net/ethernet/intel/ice/ice_dcf.c      | 713
> ++++++++++++++++++
>  drivers/net/ethernet/intel/ice/ice_dcf.h      |  41 +
>  drivers/net/ethernet/intel/ice/ice_switch.c   |  16 +-
>  drivers/net/ethernet/intel/ice/ice_switch.h   |  27 +-
>  drivers/net/ethernet/intel/ice/ice_type.h     |   9 +
>  .../net/ethernet/intel/ice/ice_virtchnl_pf.c  |  40 +
>  6 files changed, 821 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/ice/ice_dcf.c
> b/drivers/net/ethernet/intel/ice/ice_dcf.c
> index e7d37735aaa5..154005f1b634 100644
> --- a/drivers/net/ethernet/intel/ice/ice_dcf.c
> +++ b/drivers/net/ethernet/intel/ice/ice_dcf.c
> @@ -124,3 +124,716 @@ void ice_dcf_set_state(struct ice_pf *pf, enum
> ice_dcf_state state)
>  
>  	pf->dcf.state = state;
>  }
> +
> +/**
> + * ice_dcf_rm_sw_rule_to_vsi - remove switch rule of "forward to
> VSI"
> + * @pf: pointer to the PF struct
> + * @s_entry: pointer to switch rule entry to remove
> + */
> +static int
> +ice_dcf_rm_sw_rule_to_vsi(struct ice_pf *pf,
> +			  struct ice_dcf_sw_rule_entry *s_entry)
> +{
> +	struct ice_aqc_sw_rules_elem *s_rule;
> +	enum ice_status status;
> +
> +	s_rule = kzalloc(ICE_SW_RULE_RX_TX_NO_HDR_SIZE, GFP_KERNEL);
> +	if (!s_rule)
> +		return -ENOMEM;
> +
> +	s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
> +	s_rule->pdata.lkup_tx_rx.act = 0;
> +	s_rule->pdata.lkup_tx_rx.hdr_len = 0;
> +	s_rule->pdata.lkup_tx_rx.index = cpu_to_le16(s_entry->rule_id);
> +	status = ice_aq_sw_rules(&pf->hw, s_rule,
> ICE_SW_RULE_RX_TX_NO_HDR_SIZE,
> +				 1, ice_aqc_opc_remove_sw_rules, NULL);
> +	kfree(s_rule);
> +	if (status)
> +		return -EIO;
> +
> +	list_del(&s_entry->list_entry);
> +	kfree(s_entry);
> +	return 0;
> +}
> +
> +/**
> + * ice_dcf_rm_sw_rule_to_vsi_list - remove switch rule of "forward
> to VSI list"
> + * @pf: pointer to the PF struct
> + * @s_entry: pointer to switch rule entry to remove
> + */
> +static int
> +ice_dcf_rm_sw_rule_to_vsi_list(struct ice_pf *pf,
> +			       struct ice_dcf_sw_rule_entry *s_entry)
> +{
> +	struct ice_dcf_vsi_list_info *vsi_list_info = s_entry-
> >vsi_list_info;
> +	struct ice_aqc_alloc_free_res_elem *res_buf;
> +	struct ice_aqc_sw_rules_elem *s_rule;
> +	enum ice_status status;
> +	u16 rule_sz;
> +	u16 vsi_id;
> +	int i = 0;
> +
> +	if (!vsi_list_info)
> +		return -EINVAL;
> +
> +	/* The VSI list is empty, it can be freed immediately */
> +	if (!vsi_list_info->vsi_count)
> +		goto free_vsi_list;
> +
> +	rule_sz = ICE_SW_RULE_VSI_LIST_SIZE(vsi_list_info->vsi_count);
> +	s_rule = kzalloc(rule_sz, GFP_KERNEL);
> +	if (!s_rule)
> +		return -ENOMEM;
> +
> +	s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
> +	s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_info-
> >list_id);
> +	s_rule->pdata.vsi_list.number_vsi =
> +					cpu_to_le16(vsi_list_info-
> >vsi_count);
> +	for_each_set_bit(vsi_id, vsi_list_info->hw_vsi_map,
> ICE_HW_VSI_ID_MAX)
> +		s_rule->pdata.vsi_list.vsi[i++] = cpu_to_le16(vsi_id);
> +
> +	bitmap_zero(vsi_list_info->hw_vsi_map, ICE_HW_VSI_ID_MAX);
> +	vsi_list_info->vsi_count = 0;
> +
> +	status = ice_aq_sw_rules(&pf->hw, s_rule, rule_sz, 1,
> +				 ice_aqc_opc_update_sw_rules, NULL);
> +	kfree(s_rule);
> +	if (status)
> +		return -EIO;
> +
> +free_vsi_list:
> +	res_buf = kzalloc(sizeof(*res_buf), GFP_KERNEL);
> +	if (!res_buf)
> +		return -ENOMEM;
> +
> +	res_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
> +	res_buf->num_elems = cpu_to_le16(1);
> +	res_buf->elem[0].e.sw_resp = cpu_to_le16(vsi_list_info-
> >list_id);
> +	status = ice_aq_alloc_free_res(&pf->hw, 1, res_buf,
> sizeof(*res_buf),
> +				       ice_aqc_opc_free_res, NULL);
> +	kfree(res_buf);
> +	if (status)
> +		return -EIO;
> +
> +	list_del(&vsi_list_info->list_entry);
> +	kfree(vsi_list_info);
> +	s_entry->vsi_list_info = NULL;
> +
> +	return ice_dcf_rm_sw_rule_to_vsi(pf, s_entry);
> +}
> +
> +/**
> + * ice_dcf_rm_vsi_from_list - remove VSI from switch rule forward
> VSI list
> + * @pf: pointer to the PF struct
> + * @vsi_list_info: pointer to the VSI list info
> + * @hw_vsi_id: the Hardware VSI number
> + */
> +static int
> +ice_dcf_rm_vsi_from_list(struct ice_pf *pf,
> +			 struct ice_dcf_vsi_list_info *vsi_list_info,
> +			 u16 hw_vsi_id)
> +{
> +	struct ice_aqc_sw_rules_elem *s_rule;
> +	enum ice_status status;
> +
> +	if (!vsi_list_info || !vsi_list_info->vsi_count ||
> +	    !test_bit(hw_vsi_id, vsi_list_info->hw_vsi_map))
> +		return -ENOENT;
> +
> +	s_rule = kzalloc(ICE_SW_RULE_VSI_LIST_SIZE(1), GFP_KERNEL);
> +	if (!s_rule)
> +		return -ENOMEM;
> +
> +	s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
> +	s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_info-
> >list_id);
> +	s_rule->pdata.vsi_list.number_vsi = cpu_to_le16(1);
> +	s_rule->pdata.vsi_list.vsi[0] = cpu_to_le16(hw_vsi_id);
> +	status = ice_aq_sw_rules(&pf->hw, s_rule,
> +				 ICE_SW_RULE_VSI_LIST_SIZE(1), 1,
> +				 ice_aqc_opc_update_sw_rules, NULL);
> +	kfree(s_rule);
> +	if (status)
> +		return -EIO;
> +
> +	/* When the VF resets gracefully, it should keep the VSI list
> and its
> +	 * rule, just clears the VSI from list, so that the DCF can
> replay the
> +	 * rule by updating this VF to list successfully.
> +	 */
> +	vsi_list_info->vsi_count--;
> +	clear_bit(hw_vsi_id, vsi_list_info->hw_vsi_map);
> +
> +	return 0;
> +}
> +
> +/**
> + * ice_rm_dcf_sw_vsi_rule - remove switch rules added by DCF to VSI
> + * @pf: pointer to the PF struct
> + * @hw_vsi_id: hardware VSI ID of the VF
> + */
> +void ice_rm_dcf_sw_vsi_rule(struct ice_pf *pf, u16 hw_vsi_id)
> +{
> +	struct ice_dcf_sw_rule_entry *s_entry, *tmp;
> +	int ret;
> +
> +	list_for_each_entry_safe(s_entry, tmp, &pf->dcf.sw_rule_head,
> +				 list_entry)
> +		if (s_entry->fltr_act == ICE_FWD_TO_VSI_LIST) {
> +			ret = ice_dcf_rm_vsi_from_list(pf,
> +						       s_entry-
> >vsi_list_info,
> +						       hw_vsi_id);
> +			if (ret && ret != -ENOENT)
> +				dev_err(ice_pf_to_dev(pf),
> +					"Failed to remove VSI %u from
> VSI list : %d\n",
> +					hw_vsi_id, ret);
> +		} else if (s_entry->fwd_id.hw_vsi_id == hw_vsi_id) {
> +			ret = ice_dcf_rm_sw_rule_to_vsi(pf, s_entry);
> +			if (ret)
> +				dev_err(ice_pf_to_dev(pf),
> +					"Failed to remove VSI %u switch
> rule : %d\n",
> +					hw_vsi_id, ret);
> +		}
> +}
> +
> +/**
> + * ice_dcf_init_sw_rule_mgmt - initializes DCF rule filter mngt
> struct
> + * @pf: pointer to the PF struct
> + */
> +void ice_dcf_init_sw_rule_mgmt(struct ice_pf *pf)
> +{
> +	INIT_LIST_HEAD(&pf->dcf.sw_rule_head);
> +	INIT_LIST_HEAD(&pf->dcf.vsi_list_info_head);
> +}
> +
> +/**
> + * ice_rm_all_dcf_sw_rules - remove switch rules configured by DCF
> + * @pf: pointer to the PF struct
> + */
> +void ice_rm_all_dcf_sw_rules(struct ice_pf *pf)
> +{
> +	struct ice_dcf_vsi_list_info *vsi_list_info, *list_info_tmp;
> +	struct ice_dcf_sw_rule_entry *sw_rule, *rule_tmp;
> +	u16 rule_id, list_id;
> +	int ret;
> +
> +	list_for_each_entry_safe(sw_rule, rule_tmp, &pf-
> >dcf.sw_rule_head,
> +				 list_entry)
> +		if (sw_rule->fltr_act == ICE_FWD_TO_VSI_LIST) {
> +			list_id = sw_rule->fwd_id.vsi_list_id;
> +			rule_id = sw_rule->rule_id;
> +			ret = ice_dcf_rm_sw_rule_to_vsi_list(pf,
> sw_rule);
> +			if (ret)
> +				dev_err(ice_pf_to_dev(pf),
> +					"Failed to remove switch rule
> 0x%04x with list id %u : %d\n",
> +					rule_id, list_id, ret);
> +		} else {
> +			rule_id = sw_rule->rule_id;
> +			ret = ice_dcf_rm_sw_rule_to_vsi(pf, sw_rule);
> +			if (ret)
> +				dev_err(ice_pf_to_dev(pf),
> +					"Failed to remove switch rule
> 0x%04x : %d\n",
> +					rule_id, ret);
> +		}
> +
> +	/* clears rule filter management data if AdminQ command has
> error */
> +	list_for_each_entry_safe(vsi_list_info, list_info_tmp,
> +				 &pf->dcf.vsi_list_info_head,
> +				 list_entry) {
> +		list_del(&vsi_list_info->list_entry);
> +		kfree(vsi_list_info);
> +	}
> +
> +	list_for_each_entry_safe(sw_rule, rule_tmp, &pf-
> >dcf.sw_rule_head,
> +				 list_entry) {
> +		list_del(&sw_rule->list_entry);
> +		kfree(sw_rule);
> +	}
> +}
> +
> +/**
> + * ice_dcf_find_vsi_list_info - find the VSI list by ID.
> + * @pf: pointer to the PF info
> + * @vsi_list_id: VSI list ID
> + */
> +static struct ice_dcf_vsi_list_info *
> +ice_dcf_find_vsi_list_info(struct ice_pf *pf, u16 vsi_list_id)
> +{
> +	struct ice_dcf_vsi_list_info *list_info;
> +
> +	list_for_each_entry(list_info, &pf->dcf.vsi_list_info_head,
> list_entry)
> +		if (list_info->list_id == vsi_list_id)
> +			return list_info;
> +
> +	return NULL;
> +}
> +
> +/**
> + * ice_dcf_add_vsi_id - add new VSI ID into list.
> + * @vsi_list_info: pointer to the VSI list info
> + * @hw_vsi_id: the VSI ID
> + */
> +static void
> +ice_dcf_add_vsi_id(struct ice_dcf_vsi_list_info *vsi_list_info, u16
> hw_vsi_id)
> +{
> +	if (!test_and_set_bit(hw_vsi_id, vsi_list_info->hw_vsi_map))
> +		vsi_list_info->vsi_count++;
> +}
> +
> +/**
> + * ice_dcf_del_vsi_id - delete the VSI ID from list.
> + * @vsi_list_info: pointer to the VSI list info
> + * @hw_vsi_id: the VSI ID
> + */
> +static void
> +ice_dcf_del_vsi_id(struct ice_dcf_vsi_list_info *vsi_list_info, u16
> hw_vsi_id)
> +{
> +	if (test_and_clear_bit(hw_vsi_id, vsi_list_info->hw_vsi_map))
> +		vsi_list_info->vsi_count--;
> +}
> +
> +/**
> + * ice_dcf_parse_alloc_vsi_list_res - parse the allocate VSI list
> resource
> + * @pf: pointer to the PF info
> + * @res: pointer to the VSI list resource
> + */
> +static enum virtchnl_status_code
> +ice_dcf_parse_alloc_vsi_list_res(struct ice_pf *pf,
> +				 struct ice_aqc_res_elem *res)
> +{
> +	struct ice_dcf_vsi_list_info *vsi_list_info;
> +	u16 list_id = le16_to_cpu(res->e.sw_resp);
> +
> +	vsi_list_info = ice_dcf_find_vsi_list_info(pf, list_id);
> +	if (vsi_list_info)
> +		return VIRTCHNL_STATUS_SUCCESS;
> +
> +	vsi_list_info = kzalloc(sizeof(*vsi_list_info), GFP_KERNEL);
> +	if (!vsi_list_info)
> +		return VIRTCHNL_STATUS_ERR_NO_MEMORY;
> +
> +	vsi_list_info->list_id = list_id;
> +	list_add(&vsi_list_info->list_entry, &pf-
> >dcf.vsi_list_info_head);
> +
> +	return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_parse_free_vsi_list_res - parse the free VSI list
> resource
> + * @pf: pointer to the PF info
> + * @res: pointer to the VSI list resource
> + */
> +static enum virtchnl_status_code
> +ice_dcf_parse_free_vsi_list_res(struct ice_pf *pf,
> +				struct ice_aqc_res_elem *res)
> +{
> +	struct ice_dcf_vsi_list_info *vsi_list_info;
> +	u16 list_id = le16_to_cpu(res->e.sw_resp);
> +
> +	vsi_list_info = ice_dcf_find_vsi_list_info(pf, list_id);
> +	if (!vsi_list_info)
> +		return VIRTCHNL_STATUS_ERR_PARAM;
> +
> +	if (vsi_list_info->vsi_count)
> +		dev_warn(ice_pf_to_dev(pf),
> +			 "VSI list %u still has %u VSIs to be
> removed!\n",
> +			 list_id, vsi_list_info->vsi_count);
> +
> +	if (vsi_list_info->sw_rule)
> +		vsi_list_info->sw_rule->vsi_list_info = NULL;
> +
> +	list_del(&vsi_list_info->list_entry);
> +	kfree(vsi_list_info);
> +
> +	return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_set_vsi_list - set the VSI to VSI list
> + * @pf: pointer to the PF info
> + * @vsi_list: pointer to the VSI ID list to be set
> + */
> +static enum virtchnl_status_code
> +ice_dcf_set_vsi_list(struct ice_pf *pf, struct ice_sw_rule_vsi_list
> *vsi_list)
> +{
> +	struct ice_dcf_vsi_list_info *vsi_list_info;
> +	int i;
> +
> +	vsi_list_info =
> +		ice_dcf_find_vsi_list_info(pf, le16_to_cpu(vsi_list-
> >index));
> +	if (!vsi_list_info)
> +		return VIRTCHNL_STATUS_ERR_PARAM;
> +
> +	for (i = 0; i < le16_to_cpu(vsi_list->number_vsi); i++)
> +		ice_dcf_add_vsi_id(vsi_list_info,
> +				   le16_to_cpu(vsi_list->vsi[i]));
> +
> +	return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_clear_vsi_list - clear the VSI from VSI list
> + * @pf: pointer to the PF info
> + * @vsi_list: pointer to the VSI ID list to be cleared
> + */
> +static enum virtchnl_status_code
> +ice_dcf_clear_vsi_list(struct ice_pf *pf, struct
> ice_sw_rule_vsi_list *vsi_list)
> +{
> +	struct ice_dcf_vsi_list_info *vsi_list_info;
> +	int i;
> +
> +	vsi_list_info =
> +		ice_dcf_find_vsi_list_info(pf, le16_to_cpu(vsi_list-
> >index));
> +	if (!vsi_list_info)
> +		return VIRTCHNL_STATUS_ERR_PARAM;
> +
> +	for (i = 0; i < le16_to_cpu(vsi_list->number_vsi); i++)
> +		ice_dcf_del_vsi_id(vsi_list_info,
> +				   le16_to_cpu(vsi_list->vsi[i]));
> +
> +	return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_find_sw_rule - find the switch rule by ID.
> + * @pf: pointer to the PF info
> + * @rule_id: switch rule ID
> + */
> +static struct ice_dcf_sw_rule_entry *
> +ice_dcf_find_sw_rule(struct ice_pf *pf, u16 rule_id)
> +{
> +	struct ice_dcf_sw_rule_entry *sw_rule;
> +
> +	list_for_each_entry(sw_rule, &pf->dcf.sw_rule_head, list_entry)
> +		if (sw_rule->rule_id == rule_id)
> +			return sw_rule;
> +
> +	return NULL;
> +}
> +
> +/**
> + * ice_dcf_parse_add_sw_rule_data - parse the add switch rule data
> + * @pf: pointer to the PF info
> + * @lkup: pointer to the add switch rule data
> + */
> +static enum virtchnl_status_code
> +ice_dcf_parse_add_sw_rule_data(struct ice_pf *pf,
> +			       struct ice_sw_rule_lkup_rx_tx *lkup)
> +{
> +	struct ice_dcf_sw_rule_entry *sw_rule;
> +	u32 act;
> +
> +	sw_rule = kzalloc(sizeof(*sw_rule), GFP_KERNEL);
> +	if (!sw_rule)
> +		return VIRTCHNL_STATUS_ERR_NO_MEMORY;
> +
> +	act = le32_to_cpu(lkup->act);
> +	sw_rule->fltr_act = ICE_FWD_TO_VSI;
> +	sw_rule->fwd_id.hw_vsi_id = (act & ICE_SINGLE_ACT_VSI_ID_M) >>
> +					ICE_SINGLE_ACT_VSI_ID_S;
> +	sw_rule->rule_id = le16_to_cpu(lkup->index);
> +
> +	list_add(&sw_rule->list_entry, &pf->dcf.sw_rule_head);
> +
> +	return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_parse_updt_sw_rule_data - parse the update switch rule
> data
> + * @pf: pointer to the PF info
> + * @lkup: pointer to the update switch rule data
> + */
> +static enum virtchnl_status_code
> +ice_dcf_parse_updt_sw_rule_data(struct ice_pf *pf,
> +				struct ice_sw_rule_lkup_rx_tx *lkup)
> +{
> +	struct ice_dcf_vsi_list_info *vsi_list_info;
> +	struct ice_dcf_sw_rule_entry *sw_rule;
> +	u16 vsi_list_id, rule_id;
> +	u32 act;
> +
> +	rule_id = le16_to_cpu(lkup->index);
> +	sw_rule = ice_dcf_find_sw_rule(pf, rule_id);
> +	if (!sw_rule)
> +		return VIRTCHNL_STATUS_ERR_PARAM;
> +
> +	act = le32_to_cpu(lkup->act);
> +	if (!(act & ICE_SINGLE_ACT_VSI_LIST)) {
> +		u16 vsi_hw_id = (act & ICE_SINGLE_ACT_VSI_ID_M) >>
> +				ICE_SINGLE_ACT_VSI_ID_S;
> +
> +		sw_rule->fltr_act = ICE_FWD_TO_VSI;
> +		sw_rule->fwd_id.hw_vsi_id = vsi_hw_id;
> +
> +		return VIRTCHNL_STATUS_SUCCESS;
> +	}
> +
> +	vsi_list_id = (act & ICE_SINGLE_ACT_VSI_LIST_ID_M) >>
> +				ICE_SINGLE_ACT_VSI_LIST_ID_S;
> +	if (sw_rule->vsi_list_info) {
> +		if (sw_rule->vsi_list_info->list_id == vsi_list_id)
> +			return VIRTCHNL_STATUS_SUCCESS;
> +
> +		dev_err(ice_pf_to_dev(pf),
> +			"The switch rule 0x%04x is running on VSI list
> %u\n",
> +			rule_id, sw_rule->vsi_list_info->list_id);
> +		return VIRTCHNL_STATUS_ERR_PARAM;
> +	}
> +
> +	vsi_list_info = ice_dcf_find_vsi_list_info(pf, vsi_list_id);
> +	if (!vsi_list_info) {
> +		dev_err(ice_pf_to_dev(pf),
> +			"No VSI list %u found to bind the switch rule
> 0x%04x\n",
> +			vsi_list_id, rule_id);
> +		return VIRTCHNL_STATUS_ERR_PARAM;
> +	}
> +
> +	if (vsi_list_info->sw_rule) {
> +		if (vsi_list_info->sw_rule->rule_id == rule_id)
> +			return VIRTCHNL_STATUS_SUCCESS;
> +
> +		dev_err(ice_pf_to_dev(pf),
> +			"The VSI list %u is running on switch rule
> 0x%04x\n",
> +			vsi_list_id, vsi_list_info->sw_rule->rule_id);
> +		return VIRTCHNL_STATUS_ERR_PARAM;
> +	}
> +
> +	vsi_list_info->sw_rule = sw_rule;
> +
> +	sw_rule->fltr_act = ICE_FWD_TO_VSI_LIST;
> +	sw_rule->fwd_id.vsi_list_id = vsi_list_id;
> +	sw_rule->vsi_list_info = vsi_list_info;
> +
> +	return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_parse_rm_sw_rule_data - parse the remove switch rule data
> + * @pf: pointer to the PF info
> + * @lkup: pointer to the remove switch rule data
> + */
> +static enum virtchnl_status_code
> +ice_dcf_parse_rm_sw_rule_data(struct ice_pf *pf,
> +			      struct ice_sw_rule_lkup_rx_tx *lkup)
> +{
> +	struct ice_dcf_sw_rule_entry *sw_rule, *tmp;
> +	u16 rule_id = le16_to_cpu(lkup->index);
> +
> +	list_for_each_entry_safe(sw_rule, tmp, &pf->dcf.sw_rule_head,
> +				 list_entry)
> +		if (sw_rule->rule_id == rule_id) {
> +			list_del(&sw_rule->list_entry);
> +			kfree(sw_rule);
> +		}
> +
> +	return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_handle_add_sw_rule_rsp - handle the add switch rule
> response
> + * @pf: pointer to the PF info
> + * @aq_buf: pointer to the add switch rule command buffer
> + */
> +static enum virtchnl_status_code
> +ice_dcf_handle_add_sw_rule_rsp(struct ice_pf *pf, u8 *aq_buf)
> +{
> +	enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;
> +	struct ice_aqc_sw_rules_elem *em =
> +			(struct ice_aqc_sw_rules_elem *)aq_buf;
> +	u16 type = le16_to_cpu(em->type);
> +
> +	if (type == ICE_AQC_SW_RULES_T_VSI_LIST_SET)
> +		status = ice_dcf_set_vsi_list(pf, &em->pdata.vsi_list);
> +	else if (type == ICE_AQC_SW_RULES_T_LKUP_RX)
> +		status = ice_dcf_parse_add_sw_rule_data(pf,
> +							&em-
> >pdata.lkup_tx_rx);
> +
> +	return status;
> +}
> +
> +/**
> + * ice_dcf_handle_updt_sw_rule_rsp - handle the update switch rule
> response
> + * @pf: pointer to the PF info
> + * @aq_buf: pointer to the update switch rule command buffer
> + */
> +static enum virtchnl_status_code
> +ice_dcf_handle_updt_sw_rule_rsp(struct ice_pf *pf, u8 *aq_buf)
> +{
> +	enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;
> +	struct ice_aqc_sw_rules_elem *em =
> +			(struct ice_aqc_sw_rules_elem *)aq_buf;
> +	u16 type = le16_to_cpu(em->type);
> +
> +	if (type == ICE_AQC_SW_RULES_T_VSI_LIST_SET)
> +		status = ice_dcf_set_vsi_list(pf, &em->pdata.vsi_list);
> +	else if (type == ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR)
> +		status = ice_dcf_clear_vsi_list(pf, &em-
> >pdata.vsi_list);
> +	else if (type == ICE_AQC_SW_RULES_T_LKUP_RX)
> +		status = ice_dcf_parse_updt_sw_rule_data(pf,
> +							 &em-
> >pdata.lkup_tx_rx);
> +
> +	return status;
> +}
> +
> +/**
> + * ice_dcf_handle_rm_sw_rule_rsp - handle the remove switch rule
> response
> + * @pf: pointer to the PF info
> + * @aq_buf: pointer to the remove switch rule command buffer
> + */
> +static enum virtchnl_status_code
> +ice_dcf_handle_rm_sw_rule_rsp(struct ice_pf *pf, u8 *aq_buf)
> +{
> +	enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;
> +	struct ice_aqc_sw_rules_elem *em =
> +			(struct ice_aqc_sw_rules_elem *)aq_buf;
> +	u16 type = le16_to_cpu(em->type);
> +
> +	if (type == ICE_AQC_SW_RULES_T_LKUP_RX)
> +		status = ice_dcf_parse_rm_sw_rule_data(pf,
> +						       &em-
> >pdata.lkup_tx_rx);
> +
> +	return status;
> +}
> +
> +/**
> + * ice_dcf_handle_alloc_res_rsp - handle the allocate resource
> response
> + * @pf: pointer to the PF info
> + * @aq_buf: pointer to the allocate resource command buffer
> + */
> +static enum virtchnl_status_code
> +ice_dcf_handle_alloc_res_rsp(struct ice_pf *pf, u8 *aq_buf)
> +{
> +	enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;
> +	struct ice_aqc_alloc_free_res_elem *res_buf =
> +		 (struct ice_aqc_alloc_free_res_elem *)aq_buf;
> +	u16 type = (le16_to_cpu(res_buf->res_type) &
> +		    ICE_AQC_RES_TYPE_M) >> ICE_AQC_RES_TYPE_S;
> +
> +	if (type == ICE_AQC_RES_TYPE_VSI_LIST_REP)
> +		status = ice_dcf_parse_alloc_vsi_list_res(pf,
> +							  &res_buf-
> >elem[0]);
> +
> +	return status;
> +}
> +
> +/**
> + * ice_dcf_handle_free_res_rsp - handle the free resource response
> + * @pf: pointer to the PF info
> + * @aq_buf: pointer to the free resource command buffer
> + */
> +static enum virtchnl_status_code
> +ice_dcf_handle_free_res_rsp(struct ice_pf *pf, u8 *aq_buf)
> +{
> +	enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;
> +	struct ice_aqc_alloc_free_res_elem *res_buf =
> +		 (struct ice_aqc_alloc_free_res_elem *)aq_buf;
> +	u16 type = (le16_to_cpu(res_buf->res_type) &
> +		    ICE_AQC_RES_TYPE_M) >> ICE_AQC_RES_TYPE_S;
> +
> +	if (type == ICE_AQC_RES_TYPE_VSI_LIST_REP)
> +		status = ice_dcf_parse_free_vsi_list_res(pf,
> +							 &res_buf-
> >elem[0]);
> +
> +	return status;
> +}
> +
> +/**
> + * ice_dcf_post_aq_send_cmd - get the data from firmware successful
> response
> + * @pf: pointer to the PF info
> + * @aq_desc: descriptor describing the command
> + * @aq_buf: the AdminQ command buffer
> + */
> +enum virtchnl_status_code
> +ice_dcf_post_aq_send_cmd(struct ice_pf *pf, struct ice_aq_desc
> *aq_desc,
> +			 u8 *aq_buf)
> +{
> +	enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;
> +	u16 opc = le16_to_cpu(aq_desc->opcode);
> +
> +	if (!aq_buf)
> +		return VIRTCHNL_STATUS_SUCCESS;
> +
> +	if (opc == ice_aqc_opc_add_sw_rules)
> +		status = ice_dcf_handle_add_sw_rule_rsp(pf, aq_buf);
> +	else if (opc == ice_aqc_opc_update_sw_rules)
> +		status = ice_dcf_handle_updt_sw_rule_rsp(pf, aq_buf);
> +	else if (opc == ice_aqc_opc_remove_sw_rules)
> +		status = ice_dcf_handle_rm_sw_rule_rsp(pf, aq_buf);
> +	else if (opc == ice_aqc_opc_alloc_res)
> +		status = ice_dcf_handle_alloc_res_rsp(pf, aq_buf);
> +	else if (opc == ice_aqc_opc_free_res)
> +		status = ice_dcf_handle_free_res_rsp(pf, aq_buf);
> +
> +	return status;
> +}
> +
> +/**
> + * ice_dcf_pre_aq_send_cmd - check if it needs to send the command
> to firmware
> + * @vf: pointer to the VF info
> + * @aq_desc: descriptor describing the command
> + * @aq_buf: the AdminQ command buffer
> + * @aq_buf_size: the AdminQ command buffer size
> + */
> +bool
> +ice_dcf_pre_aq_send_cmd(struct ice_vf *vf, struct ice_aq_desc
> *aq_desc,
> +			u8 *aq_buf, u16 aq_buf_size)
> +{
> +	struct ice_pf *pf = vf->pf;
> +
> +	switch (le16_to_cpu(aq_desc->opcode)) {
> +	case ice_aqc_opc_update_sw_rules:
> +	{
> +		struct ice_dcf_vsi_list_info *vsi_list_info;
> +		struct ice_aqc_sw_rules_elem *s_rule;
> +		u16 list_id, vsi_id;
> +
> +		if (aq_buf_size < ICE_SW_RULE_VSI_LIST_SIZE(1))
> +			break;
> +
> +		s_rule = (struct ice_aqc_sw_rules_elem *)aq_buf;
> +		if (le16_to_cpu(s_rule->type) !=
> +					ICE_AQC_SW_RULES_T_VSI_LIST_CLE
> AR ||
> +		    le16_to_cpu(s_rule->pdata.vsi_list.number_vsi) !=
> 1)
> +			break;
> +
> +		list_id = le16_to_cpu(s_rule->pdata.vsi_list.index);
> +		vsi_list_info = ice_dcf_find_vsi_list_info(pf,
> list_id);
> +		if (!vsi_list_info)
> +			break;
> +
> +		vsi_id = le16_to_cpu(s_rule->pdata.vsi_list.vsi[0]);
> +		if (vsi_id >= ICE_HW_VSI_ID_MAX ||
> +		    test_bit(vsi_id, vsi_list_info->hw_vsi_map))
> +			break;
> +
> +		/* The VSI is removed from list already, no need to
> send the
> +		 * command to firmware.
> +		 */
> +		return true;
> +	}
> +	case ice_aqc_opc_remove_sw_rules:
> +	{
> +		struct ice_aqc_sw_rules_elem *s_rule;
> +		u16 rule_id;
> +
> +		if (aq_buf_size < ICE_SW_RULE_RX_TX_NO_HDR_SIZE)
> +			break;
> +
> +		s_rule = (struct ice_aqc_sw_rules_elem *)aq_buf;
> +		if (le16_to_cpu(s_rule->type) !=
> ICE_AQC_SW_RULES_T_LKUP_RX)
> +			break;
> +
> +		rule_id = le16_to_cpu(s_rule->pdata.lkup_tx_rx.index);
> +		if (ice_dcf_find_sw_rule(pf, rule_id))
> +			break;
> +
> +		/* The switch rule is removed already, no need to send
> the
> +		 * command to firmware.
> +		 */
> +		return true;
> +	}
> +
> +	default:
> +		break;
> +	}
> +
> +	return false;
> +}
> diff --git a/drivers/net/ethernet/intel/ice/ice_dcf.h
> b/drivers/net/ethernet/intel/ice/ice_dcf.h
> index 1ca228f89a19..23842db0a884 100644
> --- a/drivers/net/ethernet/intel/ice/ice_dcf.h
> +++ b/drivers/net/ethernet/intel/ice/ice_dcf.h
> @@ -21,10 +21,42 @@ enum ice_dcf_state {
>  	ICE_DCF_STATE_PAUSE,
>  };
>  
> +struct ice_dcf_sw_rule_entry;
> +
> +#define ICE_HW_VSI_ID_MAX	BIT(10) /* The AQ VSI number uses 10
> bits */
> +
> +struct ice_dcf_vsi_list_info {
> +	struct list_head list_entry;
> +	struct ice_dcf_sw_rule_entry *sw_rule;
> +	u16 list_id;
> +
> +	u16 vsi_count;
> +	DECLARE_BITMAP(hw_vsi_map, ICE_HW_VSI_ID_MAX);
> +};
> +
> +struct ice_dcf_sw_rule_entry {
> +	struct list_head list_entry;
> +	u16 rule_id;
> +
> +	/* Only support ICE_FWD_TO_VSI and ICE_FWD_TO_VSI_LIST */
> +	enum ice_sw_fwd_act_type fltr_act;
> +	/* Depending on filter action */
> +	union {
> +		u16 hw_vsi_id:10;
> +		u16 vsi_list_id:10;
> +	} fwd_id;
> +
> +	struct ice_dcf_vsi_list_info *vsi_list_info;
> +};
> +
>  struct ice_dcf {
>  	struct ice_vf *vf;
>  	enum ice_dcf_state state;
>  
> +	/* Trace the switch rules added/removed by DCF */
> +	struct list_head sw_rule_head;
> +	struct list_head vsi_list_info_head;
> +
>  	/* Handle the AdminQ command between the DCF (Device Config
> Function)
>  	 * and the firmware.
>  	 */
> @@ -46,5 +78,14 @@ bool ice_check_dcf_allowed(struct ice_vf *vf);
>  bool ice_is_vf_dcf(struct ice_vf *vf);
>  enum ice_dcf_state ice_dcf_get_state(struct ice_pf *pf);
>  void ice_dcf_set_state(struct ice_pf *pf, enum ice_dcf_state state);
> +void ice_dcf_init_sw_rule_mgmt(struct ice_pf *pf);
> +void ice_rm_all_dcf_sw_rules(struct ice_pf *pf);
> +void ice_rm_dcf_sw_vsi_rule(struct ice_pf *pf, u16 hw_vsi_id);
> +bool
> +ice_dcf_pre_aq_send_cmd(struct ice_vf *vf, struct ice_aq_desc
> *aq_desc,
> +			u8 *aq_buf, u16 aq_buf_size);
> +enum virtchnl_status_code
> +ice_dcf_post_aq_send_cmd(struct ice_pf *pf, struct ice_aq_desc
> *aq_desc,
> +			 u8 *aq_buf);
>  #endif /* CONFIG_PCI_IOV */
>  #endif /* _ICE_DCF_H_ */
> diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c
> b/drivers/net/ethernet/intel/ice/ice_switch.c
> index ccbe1cc64295..ee434b8d794d 100644
> --- a/drivers/net/ethernet/intel/ice/ice_switch.c
> +++ b/drivers/net/ethernet/intel/ice/ice_switch.c
> @@ -23,24 +23,10 @@
>   *	In case of Ether type filter it is treated as header without
> VLAN tag
>   *	and byte 12 and 13 is used to program a given Ether type
> instead
>   */
> -#define DUMMY_ETH_HDR_LEN		16
>  static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0,
> 0, 0, 0,
>  							0x2, 0, 0, 0,
> 0, 0,
>  							0x81, 0, 0, 0};
>  
> -#define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \
> -	(offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr) +
> \
> -	 (DUMMY_ETH_HDR_LEN * \
> -	  sizeof(((struct ice_sw_rule_lkup_rx_tx *)0)->hdr[0])))
> -#define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \
> -	(offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr))
> -#define ICE_SW_RULE_LG_ACT_SIZE(n) \
> -	(offsetof(struct ice_aqc_sw_rules_elem, pdata.lg_act.act) + \
> -	 ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act[0])))
> -#define ICE_SW_RULE_VSI_LIST_SIZE(n) \
> -	(offsetof(struct ice_aqc_sw_rules_elem, pdata.vsi_list.vsi) + \
> -	 ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi[0])))
> -
>  /**
>   * ice_init_def_sw_recp - initialize the recipe book keeping tables
>   * @hw: pointer to the HW struct
> @@ -490,7 +476,7 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16
> *vsi_list_id,
>   *
>   * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands
> to firmware
>   */
> -static enum ice_status
> +enum ice_status
>  ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16
> rule_list_sz,
>  		u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd
> *cd)
>  {

Hi Dave, Jakub,

This feature is only built when CONFIG_PCI_IOV is set. We end up with
this namespace issue using defconfig when checked against namespace.pl
since CONFIG_PCI_IOV is not enabled.
	Externally defined symbols with no external references
          ice_switch.o
            ice_aq_sw_rules

From a previous patch, neither of you liked the use of CONFIG_ to
control static-ness. I wanted to check that you are ok with the
namespace issue or if you have a preferred method to resolve this
issue. I appreciate your feedback.

Thanks,
Tony

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ