From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 4958CA09FF; Mon, 28 Dec 2020 06:23:53 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 19C6AC9FE; Mon, 28 Dec 2020 06:22:44 +0100 (CET) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 559362C2D for ; Mon, 28 Dec 2020 06:22:37 +0100 (CET) IronPort-SDR: v+puav7mFrgHSlY8bUOGFBcDblcM682m++7wSRJOJOo+emMxgG4ofZt3M1Jnf5tnsA0nVEQrWp TiqDOrr26iiw== X-IronPort-AV: E=McAfee;i="6000,8403,9847"; a="175570592" X-IronPort-AV: E=Sophos;i="5.78,454,1599548400"; d="scan'208";a="175570592" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Dec 2020 21:22:35 -0800 IronPort-SDR: GvgIQIVXFK0fkf5C5GD8599uQE47TlaAZqerbEaXKPnYV0pdo2/pIYGjTvqqZmCKSf4XHd1uPF cKOE/XMb5vVQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.78,454,1599548400"; d="scan'208";a="375487282" Received: from npg-dpdk-haiyue-3.sh.intel.com ([10.67.118.172]) by orsmga008.jf.intel.com with ESMTP; 27 Dec 2020 21:22:33 -0800 From: Haiyue Wang To: dev@dpdk.org Cc: qiming.yang@intel.com, jingjing.wu@intel.com, qi.z.zhang@intel.com, qi.fu@intel.com, Haiyue Wang , Beilei Xing Date: Mon, 28 Dec 2020 13:07:23 +0800 Message-Id: <20201228050723.27265-6-haiyue.wang@intel.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201228050723.27265-1-haiyue.wang@intel.com> References: <20201214071155.98764-1-haiyue.wang@intel.com> <20201228050723.27265-1-haiyue.wang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-dev] [PATCH v3 5/5] net/iavf: implement new VLAN capability handling X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The new VLAN virtchnl opcodes introduce new settings like different TPID filtering, stripping. Signed-off-by: Qiming Yang Signed-off-by: Haiyue Wang --- drivers/net/iavf/iavf.h | 10 +++ drivers/net/iavf/iavf_ethdev.c | 107 +++++++++++++++++++++++++ drivers/net/iavf/iavf_vchnl.c | 141 +++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+) diff --git a/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h index 9754273b2..c5d53bd9c 100644 --- a/drivers/net/iavf/iavf.h +++ b/drivers/net/iavf/iavf.h @@ -139,6 +139,7 @@ struct iavf_info { struct virtchnl_version_info virtchnl_version; struct virtchnl_vf_resource *vf_res; /* VF resource */ struct virtchnl_vsi_resource *vsi_res; /* LAN VSI */ + struct virtchnl_vlan_caps vlan_v2_caps; uint64_t supported_rxdid; uint8_t *proto_xtr; /* proto xtr type for all queues */ volatile enum virtchnl_ops pend_cmd; /* pending command not finished */ @@ -173,6 +174,10 @@ struct iavf_info { struct iavf_fdir_info fdir; /* flow director info */ /* indicate large VF support enabled or not */ bool lv_enabled; + + /* used to set the VLAN Ethernet type for virtchnl VLAN V2 */ + uint16_t outer_vlan_tpid; + uint16_t inner_vlan_tpid; }; #define IAVF_MAX_PKT_TYPE 1024 @@ -297,6 +302,8 @@ int iavf_get_vf_resource(struct iavf_adapter *adapter); void iavf_handle_virtchnl_msg(struct rte_eth_dev *dev); int iavf_enable_vlan_strip(struct iavf_adapter *adapter); int iavf_disable_vlan_strip(struct iavf_adapter *adapter); +int iavf_config_vlan_strip_v2(struct iavf_adapter *adapter, uint16_t tpid, + bool enable); int iavf_switch_queue(struct iavf_adapter *adapter, uint16_t qid, bool rx, bool on); int iavf_switch_queue_lv(struct iavf_adapter *adapter, uint16_t qid, @@ -310,6 +317,7 @@ int iavf_configure_rss_key(struct iavf_adapter *adapter); int iavf_configure_queues(struct iavf_adapter *adapter, uint16_t num_queue_pairs, uint16_t index); int iavf_get_supported_rxdid(struct iavf_adapter *adapter); +int iavf_get_vlan_offload_caps_v2(struct iavf_adapter *adapter); int iavf_config_irq_map(struct iavf_adapter *adapter); int iavf_config_irq_map_lv(struct iavf_adapter *adapter, uint16_t num, uint16_t index); @@ -323,6 +331,8 @@ int iavf_config_promisc(struct iavf_adapter *adapter, bool enable_unicast, int iavf_add_del_eth_addr(struct iavf_adapter *adapter, struct rte_ether_addr *addr, bool add); int iavf_add_del_vlan(struct iavf_adapter *adapter, uint16_t vlanid, bool add); +int iavf_add_del_vlan_v2(struct iavf_adapter *adapter, uint16_t tpid, + uint16_t vlanid, bool add); int iavf_fdir_add(struct iavf_adapter *adapter, struct iavf_fdir_conf *filter); int iavf_fdir_del(struct iavf_adapter *adapter, struct iavf_fdir_conf *filter); int iavf_fdir_check(struct iavf_adapter *adapter, diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c index 75361b73b..d6771c0d9 100644 --- a/drivers/net/iavf/iavf_ethdev.c +++ b/drivers/net/iavf/iavf_ethdev.c @@ -100,6 +100,8 @@ static void iavf_dev_del_mac_addr(struct rte_eth_dev *dev, uint32_t index); static int iavf_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); static int iavf_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask); +static int iavf_dev_vlan_tpid_set(struct rte_eth_dev *dev, + enum rte_vlan_type vlan_type, uint16_t tpid); static int iavf_dev_rss_reta_update(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); @@ -176,6 +178,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = { .mac_addr_remove = iavf_dev_del_mac_addr, .set_mc_addr_list = iavf_set_mc_addr_list, .vlan_filter_set = iavf_dev_vlan_filter_set, + .vlan_tpid_set = iavf_dev_vlan_tpid_set, .vlan_offload_set = iavf_dev_vlan_offload_set, .rx_queue_start = iavf_dev_rx_queue_start, .rx_queue_stop = iavf_dev_rx_queue_stop, @@ -326,6 +329,18 @@ iavf_queues_req_reset(struct rte_eth_dev *dev, uint16_t num) return 0; } +static inline uint16_t +iavf_curr_vlan_tpid(struct rte_eth_dev *dev) +{ + struct iavf_adapter *adapter = + IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); + bool qinq = !!(dev->data->dev_conf.rxmode.offloads & + DEV_RX_OFFLOAD_VLAN_EXTEND); + + return qinq ? vf->outer_vlan_tpid : vf->inner_vlan_tpid; +} + static int iavf_dev_configure(struct rte_eth_dev *dev) { @@ -387,6 +402,12 @@ iavf_dev_configure(struct rte_eth_dev *dev) vf->max_rss_qregion = IAVF_MAX_NUM_QUEUES_DFLT; } + /* Vlan v2 stripping setting */ + if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) + iavf_config_vlan_strip_v2(ad, iavf_curr_vlan_tpid(dev), + !!(dev_conf->rxmode.offloads & + DEV_RX_OFFLOAD_VLAN_STRIP)); + /* Vlan stripping setting */ if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) { if (dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_VLAN_STRIP) @@ -782,6 +803,9 @@ iavf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) DEV_RX_OFFLOAD_JUMBO_FRAME | DEV_RX_OFFLOAD_VLAN_FILTER | DEV_RX_OFFLOAD_RSS_HASH; + if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) + dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_VLAN_EXTEND; + dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_QINQ_INSERT | @@ -987,6 +1011,47 @@ iavf_dev_del_mac_addr(struct rte_eth_dev *dev, uint32_t index) vf->mac_num--; } +static int +iavf_dev_vlan_tpid_set(struct rte_eth_dev *dev, enum rte_vlan_type vlan_type, + uint16_t tpid) +{ + struct iavf_adapter *adapter = + IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); + bool qinq = !!(dev->data->dev_conf.rxmode.offloads & + DEV_RX_OFFLOAD_VLAN_EXTEND); + + if (vlan_type != ETH_VLAN_TYPE_INNER && + vlan_type != ETH_VLAN_TYPE_OUTER) { + PMD_DRV_LOG(ERR, "Unsupported vlan type"); + return -EINVAL; + } + + if (!qinq) { + PMD_DRV_LOG(ERR, "QinQ not enabled"); + return -EINVAL; + } + + if (vlan_type == ETH_VLAN_TYPE_OUTER) { + switch (tpid) { + case RTE_ETHER_TYPE_QINQ: + case RTE_ETHER_TYPE_VLAN: + case RTE_ETHER_TYPE_QINQ1: + vf->outer_vlan_tpid = tpid; + break; + default: + PMD_DRV_LOG(ERR, "Invalid TPID: %x", tpid); + return -EINVAL; + } + } else { + PMD_DRV_LOG(ERR, + "Can accelerate only outer vlan in QinQ"); + return -EINVAL; + } + + return 0; +} + static int iavf_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { @@ -995,6 +1060,15 @@ iavf_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); int err; + if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) { + uint16_t tpid = iavf_curr_vlan_tpid(dev); + + err = iavf_add_del_vlan_v2(adapter, tpid, vlan_id, on); + if (err) + return -EIO; + return 0; + } + if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)) return -ENOTSUP; @@ -1004,6 +1078,26 @@ iavf_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) return 0; } +static int +iavf_dev_vlan_offload_set_v2(struct rte_eth_dev *dev, int mask) +{ + struct iavf_adapter *adapter = + IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + struct rte_eth_conf *dev_conf = &dev->data->dev_conf; + uint16_t tpid = iavf_curr_vlan_tpid(dev); + int err; + + if (mask & ETH_VLAN_STRIP_MASK) { + err = iavf_config_vlan_strip_v2(adapter, tpid, + !!(dev_conf->rxmode.offloads & + DEV_RX_OFFLOAD_VLAN_STRIP)); + if (err) + return -EIO; + } + + return 0; +} + static int iavf_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask) { @@ -1013,6 +1107,9 @@ iavf_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask) struct rte_eth_conf *dev_conf = &dev->data->dev_conf; int err; + if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) + return iavf_dev_vlan_offload_set_v2(dev, mask); + if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)) return -ENOTSUP; @@ -1896,6 +1993,16 @@ iavf_init_vf(struct rte_eth_dev *dev) } } + if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) { + if (iavf_get_vlan_offload_caps_v2(adapter) != 0) { + PMD_INIT_LOG(ERR, "failed to do get VLAN offload v2 capabilities"); + goto err_rss; + } + + vf->outer_vlan_tpid = RTE_ETHER_TYPE_VLAN; + vf->inner_vlan_tpid = RTE_ETHER_TYPE_VLAN; + } + iavf_init_proto_xtr(dev); return 0; diff --git a/drivers/net/iavf/iavf_vchnl.c b/drivers/net/iavf/iavf_vchnl.c index c33194cdc..b2b5ace31 100644 --- a/drivers/net/iavf/iavf_vchnl.c +++ b/drivers/net/iavf/iavf_vchnl.c @@ -174,6 +174,7 @@ iavf_execute_vf_cmd(struct iavf_adapter *adapter, struct iavf_cmd_info *args) case VIRTCHNL_OP_VERSION: case VIRTCHNL_OP_GET_VF_RESOURCES: case VIRTCHNL_OP_GET_SUPPORTED_RXDIDS: + case VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS: /* for init virtchnl ops, need to poll the response */ do { result = iavf_read_msg_from_pf(adapter, args->out_size, @@ -366,6 +367,28 @@ iavf_enable_vlan_strip(struct iavf_adapter *adapter) return ret; } +static uint16_t +iavf_vc_vlan_tpid_flag(uint16_t tpid) +{ + uint16_t flag = VIRTCHNL_VLAN_UNSUPPORTED; + + switch (tpid) { + case RTE_ETHER_TYPE_VLAN: + flag = VIRTCHNL_VLAN_ETHERTYPE_8100; + break; + case RTE_ETHER_TYPE_QINQ1: + flag = VIRTCHNL_VLAN_ETHERTYPE_9100; + break; + case RTE_ETHER_TYPE_QINQ: + flag = VIRTCHNL_VLAN_ETHERTYPE_88A8; + break; + default: + break; + } + + return flag; +} + int iavf_disable_vlan_strip(struct iavf_adapter *adapter) { @@ -387,6 +410,52 @@ iavf_disable_vlan_strip(struct iavf_adapter *adapter) return ret; } +int +iavf_config_vlan_strip_v2(struct iavf_adapter *adapter, uint16_t tpid, + bool enable) +{ + struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); + struct virtchnl_vlan_strip vlan_strip; + struct iavf_cmd_info args; + u16 stripping_caps; + u16 vlan_tpid_flag; + u16 *vlan_setting; + int ret; + + /* Give priority over outer if it's enabled */ + if (vf->vlan_v2_caps.offloads.outer_stripping) { + stripping_caps = vf->vlan_v2_caps.offloads.outer_stripping; + vlan_setting = &vlan_strip.outer_ethertype_setting; + } else if (vf->vlan_v2_caps.offloads.inner_stripping) { + stripping_caps = vf->vlan_v2_caps.offloads.inner_stripping; + vlan_setting = &vlan_strip.inner_ethertype_setting; + } else { + return -ENOTSUP; + } + + vlan_tpid_flag = iavf_vc_vlan_tpid_flag(tpid); + if (!(stripping_caps & vlan_tpid_flag)) + return -EINVAL; + + memset(&vlan_strip, 0, sizeof(vlan_strip)); + vlan_strip.vsi_id = vf->vsi_res->vsi_id; + *vlan_setting = vlan_tpid_flag; + + args.ops = enable ? VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2 : + VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2; + args.in_args = (uint8_t *)&vlan_strip; + args.in_args_size = sizeof(vlan_strip); + args.out_buffer = vf->aq_resp; + args.out_size = IAVF_AQ_BUF_SZ; + ret = iavf_execute_vf_cmd(adapter, &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; +} + #define VIRTCHNL_VERSION_MAJOR_START 1 #define VIRTCHNL_VERSION_MINOR_START 1 @@ -459,6 +528,7 @@ iavf_get_vf_resource(struct iavf_adapter *adapter) VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF | VIRTCHNL_VF_OFFLOAD_REQ_QUEUES | VIRTCHNL_VF_OFFLOAD_CRC | + VIRTCHNL_VF_OFFLOAD_VLAN_V2 | VIRTCHNL_VF_LARGE_NUM_QPAIRS; args.in_args = (uint8_t *)∩︀ @@ -522,6 +592,31 @@ iavf_get_supported_rxdid(struct iavf_adapter *adapter) return 0; } +int +iavf_get_vlan_offload_caps_v2(struct iavf_adapter *adapter) +{ + struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); + struct iavf_cmd_info args; + int ret; + + args.ops = VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS; + args.in_args = NULL; + args.in_args_size = 0; + args.out_buffer = vf->aq_resp; + args.out_size = IAVF_AQ_BUF_SZ; + + ret = iavf_execute_vf_cmd(adapter, &args); + if (ret) { + PMD_DRV_LOG(ERR, + "Failed to execute command of VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS"); + return ret; + } + + rte_memcpy(&vf->vlan_v2_caps, vf->aq_resp, sizeof(vf->vlan_v2_caps)); + + return 0; +} + int iavf_enable_queues(struct iavf_adapter *adapter) { @@ -1167,6 +1262,52 @@ iavf_add_del_vlan(struct iavf_adapter *adapter, uint16_t vlanid, bool add) return err; } +int +iavf_add_del_vlan_v2(struct iavf_adapter *adapter, uint16_t tpid, + uint16_t vlanid, bool add) +{ + struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); + struct virtchnl_vlan_filter_list_v2 vlan_list; + struct virtchnl_vlan *vlan_setting; + struct iavf_cmd_info args; + uint16_t filtering_caps; + uint16_t vlan_tpid_flag; + int err; + + /* Give priority over outer if it's enabled */ + if (vf->vlan_v2_caps.filtering.outer) { + filtering_caps = vf->vlan_v2_caps.filtering.outer; + vlan_setting = &vlan_list.filters[0].outer; + } else if (vf->vlan_v2_caps.filtering.inner) { + filtering_caps = vf->vlan_v2_caps.filtering.inner; + vlan_setting = &vlan_list.filters[0].inner; + } else { + return -ENOTSUP; + } + + vlan_tpid_flag = iavf_vc_vlan_tpid_flag(tpid); + if (!(filtering_caps & vlan_tpid_flag)) + return -EINVAL; + + memset(&vlan_list, 0, sizeof(vlan_list)); + vlan_list.vport_id = vf->vsi_res->vsi_id; + vlan_list.num_elements = 1; + vlan_setting->tci = vlanid; + vlan_setting->tpid = tpid; + + args.ops = add ? VIRTCHNL_OP_ADD_VLAN_V2 : VIRTCHNL_OP_DEL_VLAN_V2; + args.in_args = (uint8_t *)&vlan_list; + args.in_args_size = sizeof(vlan_list); + args.out_buffer = vf->aq_resp; + args.out_size = IAVF_AQ_BUF_SZ; + err = iavf_execute_vf_cmd(adapter, &args); + if (err) + PMD_DRV_LOG(ERR, "fail to execute command %s", + add ? "OP_ADD_VLAN_V2" : "OP_DEL_VLAN_V2"); + + return err; +} + int iavf_fdir_add(struct iavf_adapter *adapter, struct iavf_fdir_conf *filter) -- 2.29.2