> -----Original Message-----
> From: Liu, KevinX <kevinx....@intel.com>
> Sent: Thursday, April 28, 2022 2:13 AM
> To: dev@dpdk.org
> Cc: Yang, Qiming <qiming.y...@intel.com>; Zhang, Qi Z
> <qi.z.zh...@intel.com>; Yang, SteveX <stevex.y...@intel.com>; Alvin Zhang
> <alvinx.zh...@intel.com>; Liu, KevinX <kevinx....@intel.com>
> Subject: [PATCH v6 12/12] net/ice: support DCF new VLAN capabilities
>
> From: Alvin Zhang <alvinx.zh...@intel.com>
>
> The new VLAN virtchnl opcodes introduce new capabilities like VLAN filtering,
> stripping and insertion.
>
> The DCF needs to query the VLAN capabilities based on current device
> configuration firstly.
>
> DCF is able to configure inner VLAN filter when port VLAN is enabled base on
> negotiation; and DCF is able to configure outer VLAN (0x8100) if port VLAN is
> disabled to be compatible with legacy mode.
>
> When port VLAN is updated by DCF, the DCF needs to reset to query the new
> VLAN capabilities.
>
> Signed-off-by: Alvin Zhang <alvinx.zh...@intel.com>
> Signed-off-by: Kevin Liu <kevinx....@intel.com>
> ---
> doc/guides/rel_notes/release_22_07.rst | 1 +
> drivers/net/ice/ice_dcf.c | 27 ++++
> drivers/net/ice/ice_dcf.h | 1 +
> drivers/net/ice/ice_dcf_ethdev.c | 171 ++++++++++++++++++++++---
> 4 files changed, 183 insertions(+), 17 deletions(-)
>
> diff --git a/doc/guides/rel_notes/release_22_07.rst
> b/doc/guides/rel_notes/release_22_07.rst
> index 004a6d3343..7c932a7c8a 100644
> --- a/doc/guides/rel_notes/release_22_07.rst
> +++ b/doc/guides/rel_notes/release_22_07.rst
> @@ -73,6 +73,7 @@ New Features
> * Added add extended stats.
> * Added support queue information getting.
> * Added implement power management.
> + * Added support DCF new VLAN capabilities.
This feature is not exposed to user, no need release note update.
>
> Removed Items
> -------------
> diff --git a/drivers/net/ice/ice_dcf.c b/drivers/net/ice/ice_dcf.c index
> 55ae68c456..885d58c0f4 100644
> --- a/drivers/net/ice/ice_dcf.c
> +++ b/drivers/net/ice/ice_dcf.c
> @@ -587,6 +587,29 @@ ice_dcf_get_supported_rxdid(struct ice_dcf_hw *hw)
> return 0;
> }
>
> +static int
> +dcf_get_vlan_offload_caps_v2(struct ice_dcf_hw *hw) {
> + struct virtchnl_vlan_caps vlan_v2_caps;
> + struct dcf_virtchnl_cmd args;
> + int ret;
> +
> + memset(&args, 0, sizeof(args));
> + args.v_op = VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS;
> + args.rsp_msgbuf = (uint8_t *)&vlan_v2_caps;
> + args.rsp_buflen = sizeof(vlan_v2_caps);
> +
> + ret = ice_dcf_execute_virtchnl_cmd(hw, &args);
> + if (ret) {
> + PMD_DRV_LOG(ERR,
> + "Failed to execute command of
> VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS");
> + return ret;
> + }
> +
> + rte_memcpy(&hw->vlan_v2_caps, &vlan_v2_caps,
> sizeof(vlan_v2_caps));
> + return 0;
> +}
> +
> int
> ice_dcf_init_hw(struct rte_eth_dev *eth_dev, struct ice_dcf_hw *hw) { @@ -
> 701,6 +724,10 @@ ice_dcf_init_hw(struct rte_eth_dev *eth_dev, struct
> ice_dcf_hw *hw)
> rte_intr_enable(pci_dev->intr_handle);
> ice_dcf_enable_irq0(hw);
>
> + if ((hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2)
> &&
> + dcf_get_vlan_offload_caps_v2(hw))
> + goto err_rss;
> +
> return 0;
>
> err_rss:
> diff --git a/drivers/net/ice/ice_dcf.h b/drivers/net/ice/ice_dcf.h index
> 44a61404c3..7f42ebabe9 100644
> --- a/drivers/net/ice/ice_dcf.h
> +++ b/drivers/net/ice/ice_dcf.h
> @@ -129,6 +129,7 @@ struct ice_dcf_hw {
> uint16_t nb_msix;
> uint16_t rxq_map[16];
> struct virtchnl_eth_stats eth_stats_offset;
> + struct virtchnl_vlan_caps vlan_v2_caps;
>
> /* Link status */
> bool link_up;
> diff --git a/drivers/net/ice/ice_dcf_ethdev.c
> b/drivers/net/ice/ice_dcf_ethdev.c
> index 236c0395e0..8005eb2ab8 100644
> --- a/drivers/net/ice/ice_dcf_ethdev.c
> +++ b/drivers/net/ice/ice_dcf_ethdev.c
> @@ -1050,6 +1050,46 @@ dcf_dev_set_default_mac_addr(struct
> rte_eth_dev *dev,
> return 0;
> }
>
> +static int
> +dcf_add_del_vlan_v2(struct ice_dcf_hw *hw, uint16_t vlanid, bool add) {
> + struct virtchnl_vlan_supported_caps *supported_caps =
> + &hw->vlan_v2_caps.filtering.filtering_support;
> + struct virtchnl_vlan *vlan_setting;
> + struct virtchnl_vlan_filter_list_v2 vlan_filter;
> + struct dcf_virtchnl_cmd args;
> + uint32_t filtering_caps;
> + int err;
> +
> + if (supported_caps->outer) {
> + filtering_caps = supported_caps->outer;
> + vlan_setting = &vlan_filter.filters[0].outer;
> + } else {
> + filtering_caps = supported_caps->inner;
> + vlan_setting = &vlan_filter.filters[0].inner;
> + }
> +
> + if (!(filtering_caps & VIRTCHNL_VLAN_ETHERTYPE_8100))
> + return -ENOTSUP;
> +
> + memset(&vlan_filter, 0, sizeof(vlan_filter));
> + vlan_filter.vport_id = hw->vsi_res->vsi_id;
> + vlan_filter.num_elements = 1;
> + vlan_setting->tpid = RTE_ETHER_TYPE_VLAN;
> + vlan_setting->tci = vlanid;
> +
> + memset(&args, 0, sizeof(args));
> + args.v_op = add ? VIRTCHNL_OP_ADD_VLAN_V2 :
> VIRTCHNL_OP_DEL_VLAN_V2;
> + args.req_msg = (uint8_t *)&vlan_filter;
> + args.req_msglen = sizeof(vlan_filter);
> + err = ice_dcf_execute_virtchnl_cmd(hw, &args);
> + if (err)
> + PMD_DRV_LOG(ERR, "fail to execute command %s",
> + add ? "OP_ADD_VLAN_V2" : "OP_DEL_VLAN_V2");
> +
> + return err;
> +}
> +
> static int
> dcf_add_del_vlan(struct ice_dcf_hw *hw, uint16_t vlanid, bool add) { @@ -
> 1076,6 +1116,116 @@ dcf_add_del_vlan(struct ice_dcf_hw *hw, uint16_t
> vlanid, bool add)
> return err;
> }
>
> +static int
> +dcf_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int
> +on) {
> + struct ice_dcf_adapter *adapter = dev->data->dev_private;
> + struct ice_dcf_hw *hw = &adapter->real_hw;
> + int err;
> +
> + if (hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) {
> + err = dcf_add_del_vlan_v2(hw, vlan_id, on);
> + if (err)
> + return -EIO;
> + return 0;
> + }
> +
> + if (!(hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
> + return -ENOTSUP;
> +
> + err = dcf_add_del_vlan(hw, vlan_id, on);
> + if (err)
> + return -EIO;
> + return 0;
> +}
> +
> +static void
> +dcf_iterate_vlan_filters_v2(struct rte_eth_dev *dev, bool enable) {
> + struct rte_vlan_filter_conf *vfc = &dev->data->vlan_filter_conf;
> + struct ice_dcf_adapter *adapter = dev->data->dev_private;
> + struct ice_dcf_hw *hw = &adapter->real_hw;
> + uint32_t i, j;
> + uint64_t ids;
> +
> + for (i = 0; i < RTE_DIM(vfc->ids); i++) {
> + if (vfc->ids[i] == 0)
> + continue;
> +
> + ids = vfc->ids[i];
> + for (j = 0; ids != 0 && j < 64; j++, ids >>= 1) {
> + if (ids & 1)
> + dcf_add_del_vlan_v2(hw, 64 * i + j, enable);
> + }
> + }
> +}
> +
> +static int
> +dcf_config_vlan_strip_v2(struct ice_dcf_hw *hw, bool enable) {
> + struct virtchnl_vlan_supported_caps *stripping_caps =
> + &hw->vlan_v2_caps.offloads.stripping_support;
> + struct virtchnl_vlan_setting vlan_strip;
> + struct dcf_virtchnl_cmd args;
> + uint32_t *ethertype;
> + int ret;
> +
> + if ((stripping_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_8100) &&
> + (stripping_caps->outer & VIRTCHNL_VLAN_TOGGLE))
> + ethertype = &vlan_strip.outer_ethertype_setting;
> + else if ((stripping_caps->inner & VIRTCHNL_VLAN_ETHERTYPE_8100)
> &&
> + (stripping_caps->inner & VIRTCHNL_VLAN_TOGGLE))
> + ethertype = &vlan_strip.inner_ethertype_setting;
> + else
> + return -ENOTSUP;
> +
> + memset(&vlan_strip, 0, sizeof(vlan_strip));
> + vlan_strip.vport_id = hw->vsi_res->vsi_id;
> + *ethertype = VIRTCHNL_VLAN_ETHERTYPE_8100;
> +
> + memset(&args, 0, sizeof(args));
> + args.v_op = enable ? VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2 :
> + VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2;
> + args.req_msg = (uint8_t *)&vlan_strip;
> + args.req_msglen = sizeof(vlan_strip);
> + ret = ice_dcf_execute_virtchnl_cmd(hw, &args);
> + if (ret)
> + PMD_DRV_LOG(ERR, "fail to execute command %s",
> + enable ?
> "VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2" :
> +
> "VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2");
> +
> + return ret;
> +}
> +
> +static int
> +dcf_dev_vlan_offload_set_v2(struct rte_eth_dev *dev, int mask) {
> + struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
> + struct ice_dcf_adapter *adapter = dev->data->dev_private;
> + struct ice_dcf_hw *hw = &adapter->real_hw;
> + bool enable;
> + int err;
> +
> + if (mask & RTE_ETH_VLAN_FILTER_MASK) {
> + enable = !!(rxmode->offloads &
> RTE_ETH_RX_OFFLOAD_VLAN_FILTER);
> +
> + dcf_iterate_vlan_filters_v2(dev, enable);
> + }
> +
> + if (mask & RTE_ETH_VLAN_STRIP_MASK) {
> + enable = !!(rxmode->offloads &
> RTE_ETH_RX_OFFLOAD_VLAN_STRIP);
> +
> + err = dcf_config_vlan_strip_v2(hw, enable);
> + /* If not support, the stripping is already disabled by PF */
> + if (err == -ENOTSUP && !enable)
> + err = 0;
> + if (err)
> + return -EIO;
> + }
> +
> + return 0;
> +}
> +
> static int
> dcf_enable_vlan_strip(struct ice_dcf_hw *hw) { @@ -1108,30 +1258,17 @@
> dcf_disable_vlan_strip(struct ice_dcf_hw *hw)
> return ret;
> }
>
> -static int
> -dcf_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) -{
> - struct ice_dcf_adapter *adapter = dev->data->dev_private;
> - struct ice_dcf_hw *hw = &adapter->real_hw;
> - int err;
> -
> - if (!(hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
> - return -ENOTSUP;
> -
> - err = dcf_add_del_vlan(hw, vlan_id, on);
> - if (err)
> - return -EIO;
> - return 0;
> -}
> -
> static int
> dcf_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask) {
> + struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
> struct ice_dcf_adapter *adapter = dev->data->dev_private;
> struct ice_dcf_hw *hw = &adapter->real_hw;
> - struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
> int err;
>
> + if (hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2)
> + return dcf_dev_vlan_offload_set_v2(dev, mask);
> +
> if (!(hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
> return -ENOTSUP;
>
> --
> 2.33.1