From patchwork Tue Jan 12 08:13:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wang, Haiyue" X-Patchwork-Id: 86389 X-Patchwork-Delegate: qi.z.zhang@intel.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id C98DAA04B5; Tue, 12 Jan 2021 09:29:04 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 013BF140D61; Tue, 12 Jan 2021 09:28:49 +0100 (CET) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mails.dpdk.org (Postfix) with ESMTP id E4FAE140D5C for ; Tue, 12 Jan 2021 09:28:46 +0100 (CET) IronPort-SDR: EUJEnfcL02siU1q8cg+3qUW4vm2iex+L+MUwxsA+bY3AGpIVn1jAa0kDiojjGrH3TCLV849arB B+4fYbcY2rpQ== X-IronPort-AV: E=McAfee;i="6000,8403,9861"; a="262788611" X-IronPort-AV: E=Sophos;i="5.79,340,1602572400"; d="scan'208";a="262788611" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jan 2021 00:28:46 -0800 IronPort-SDR: JujiR0cKhJTUqtE4zR+AKNSqaCBn0OELC8grCTQElWF2qlqerUSZXWaiqkIE+8Gi1GzxK0iU0b 3+iBUB9MnFcw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.79,340,1602572400"; d="scan'208";a="464443652" Received: from npg-dpdk-haiyue-3.sh.intel.com ([10.67.118.237]) by fmsmga001.fm.intel.com with ESMTP; 12 Jan 2021 00:28:44 -0800 From: Haiyue Wang To: dev@dpdk.org Cc: qiming.yang@intel.com, jingjing.wu@intel.com, beilei.xing@intel.com, qi.z.zhang@intel.com, qi.fu@intel.com, Haiyue Wang Date: Tue, 12 Jan 2021 16:13:02 +0800 Message-Id: <20210112081302.87715-4-haiyue.wang@intel.com> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210112081302.87715-1-haiyue.wang@intel.com> References: <20201214071155.98764-1-haiyue.wang@intel.com> <20210112081302.87715-1-haiyue.wang@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v6 3/3] net/iavf: implement new VLAN capability handling X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 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 capabilities like VLAN filtering, stripping and insertion. The AVF needs to query the VLAN capabilities based on current device configuration firstly. AVF is able to configure inner VLAN filter when port VLAN is enabled base on negotiation; and AVF 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 AVF needs to reset to query the new VLAN capabilities. Signed-off-by: Qiming Yang Signed-off-by: Haiyue Wang --- drivers/net/iavf/iavf.h | 6 ++ drivers/net/iavf/iavf_ethdev.c | 117 +++++++++++++++++++++++-- drivers/net/iavf/iavf_vchnl.c | 153 +++++++++++++++++++++++++++++++++ 3 files changed, 269 insertions(+), 7 deletions(-) diff --git a/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h index 9754273b2..af11268fe 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 */ @@ -310,6 +311,11 @@ 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_config_vlan_strip_v2(struct iavf_adapter *adapter, bool enable); +int iavf_config_vlan_insert_v2(struct iavf_adapter *adapter, bool enable); +int iavf_add_del_vlan_v2(struct iavf_adapter *adapter, uint16_t vlanid, + bool add); +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); diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c index 49e6dd125..e22c62ed0 100644 --- a/drivers/net/iavf/iavf_ethdev.c +++ b/drivers/net/iavf/iavf_ethdev.c @@ -326,13 +326,52 @@ iavf_queues_req_reset(struct rte_eth_dev *dev, uint16_t num) return 0; } +static int +iavf_dev_vlan_insert_set(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 enable; + + if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2)) + return 0; + + enable = !!(dev->data->dev_conf.txmode.offloads & + DEV_TX_OFFLOAD_VLAN_INSERT); + iavf_config_vlan_insert_v2(adapter, enable); + + return 0; +} + +static int +iavf_dev_init_vlan(struct rte_eth_dev *dev) +{ + int err; + + err = iavf_dev_vlan_offload_set(dev, + ETH_VLAN_STRIP_MASK | + ETH_QINQ_STRIP_MASK | + ETH_VLAN_FILTER_MASK | + ETH_VLAN_EXTEND_MASK); + if (err) { + PMD_DRV_LOG(ERR, "Failed to update vlan offload"); + return err; + } + + err = iavf_dev_vlan_insert_set(dev); + if (err) + PMD_DRV_LOG(ERR, "Failed to update vlan insertion"); + + return err; +} + static int iavf_dev_configure(struct rte_eth_dev *dev) { struct iavf_adapter *ad = IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad); - struct rte_eth_conf *dev_conf = &dev->data->dev_conf; uint16_t num_queue_pairs = RTE_MAX(dev->data->nb_rx_queues, dev->data->nb_tx_queues); int ret; @@ -389,12 +428,10 @@ iavf_dev_configure(struct rte_eth_dev *dev) vf->max_rss_qregion = IAVF_MAX_NUM_QUEUES_DFLT; } - /* Vlan stripping setting */ - if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) { - if (dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_VLAN_STRIP) - iavf_enable_vlan_strip(ad); - else - iavf_disable_vlan_strip(ad); + ret = iavf_dev_init_vlan(dev); + if (ret) { + PMD_DRV_LOG(ERR, "configure VLAN failed: %d", ret); + return -1; } if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) { @@ -784,6 +821,7 @@ 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; + dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_QINQ_INSERT | @@ -997,6 +1035,13 @@ 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) { + err = iavf_add_del_vlan_v2(adapter, vlan_id, on); + if (err) + return -EIO; + return 0; + } + if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)) return -ENOTSUP; @@ -1006,6 +1051,54 @@ iavf_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) return 0; } +static void +iavf_iterate_vlan_filters_v2(struct rte_eth_dev *dev, bool enable) +{ + struct rte_vlan_filter_conf *vfc = &dev->data->vlan_filter_conf; + struct iavf_adapter *adapter = + IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + 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) + iavf_add_del_vlan_v2(adapter, + 64 * i + j, enable); + } + } +} + +static int +iavf_dev_vlan_offload_set_v2(struct rte_eth_dev *dev, int mask) +{ + struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; + struct iavf_adapter *adapter = + IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + bool enable; + int err; + + if (mask & ETH_VLAN_FILTER_MASK) { + enable = !!(rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER); + + iavf_iterate_vlan_filters_v2(dev, enable); + } + + if (mask & ETH_VLAN_STRIP_MASK) { + enable = !!(rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP); + + err = iavf_config_vlan_strip_v2(adapter, enable); + if (err) + return -EIO; + } + + return 0; +} + static int iavf_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask) { @@ -1015,6 +1108,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; @@ -1898,6 +1994,13 @@ 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; + } + } + 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..3ef29d509 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, @@ -459,6 +460,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 +524,157 @@ iavf_get_supported_rxdid(struct iavf_adapter *adapter) return 0; } +int +iavf_config_vlan_strip_v2(struct iavf_adapter *adapter, bool enable) +{ + struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); + struct virtchnl_vlan_supported_caps *supported_caps; + struct virtchnl_vlan_offload vlan_strip; + struct iavf_cmd_info args; + uint32_t stripping_caps; + uint32_t *vlan_setting; + int ret; + + supported_caps = &vf->vlan_v2_caps.offloads.stripping_support; + if (supported_caps->outer) { + stripping_caps = supported_caps->outer; + vlan_setting = &vlan_strip.outer_ethertype_setting; + } else { + stripping_caps = supported_caps->inner; + vlan_setting = &vlan_strip.inner_ethertype_setting; + } + + if (!(stripping_caps & VIRTCHNL_VLAN_ETHERTYPE_8100)) + return -ENOTSUP; + + memset(&vlan_strip, 0, sizeof(vlan_strip)); + vlan_strip.vport_id = vf->vsi_res->vsi_id; + *vlan_setting = VIRTCHNL_VLAN_ETHERTYPE_8100; + + 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; +} + +int +iavf_config_vlan_insert_v2(struct iavf_adapter *adapter, bool enable) +{ + struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); + struct virtchnl_vlan_supported_caps *supported_caps; + struct virtchnl_vlan_offload vlan_insert; + struct iavf_cmd_info args; + uint32_t insertion_caps; + uint32_t *vlan_setting; + int ret; + + supported_caps = &vf->vlan_v2_caps.offloads.insertion_support; + if (supported_caps->outer) { + insertion_caps = supported_caps->outer; + vlan_setting = &vlan_insert.outer_ethertype_setting; + } else { + insertion_caps = supported_caps->inner; + vlan_setting = &vlan_insert.inner_ethertype_setting; + } + + if (!(insertion_caps & VIRTCHNL_VLAN_ETHERTYPE_8100)) + return -ENOTSUP; + + memset(&vlan_insert, 0, sizeof(vlan_insert)); + vlan_insert.vport_id = vf->vsi_res->vsi_id; + *vlan_setting = VIRTCHNL_VLAN_ETHERTYPE_8100; + + args.ops = enable ? VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2 : + VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2; + args.in_args = (uint8_t *)&vlan_insert; + args.in_args_size = sizeof(vlan_insert); + 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_INSERTION_V2" : + "VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2"); + + return ret; +} + +int +iavf_add_del_vlan_v2(struct iavf_adapter *adapter, uint16_t vlanid, bool add) +{ + struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); + struct virtchnl_vlan_supported_caps *supported_caps; + struct virtchnl_vlan_filter_list_v2 vlan_filter; + struct virtchnl_vlan *vlan_setting; + struct iavf_cmd_info args; + uint32_t filtering_caps; + int err; + + supported_caps = &vf->vlan_v2_caps.filtering.filtering_support; + 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 = vf->vsi_res->vsi_id; + vlan_filter.num_elements = 1; + vlan_setting->tpid = RTE_ETHER_TYPE_VLAN; + vlan_setting->tci = vlanid; + + args.ops = add ? VIRTCHNL_OP_ADD_VLAN_V2 : VIRTCHNL_OP_DEL_VLAN_V2; + args.in_args = (uint8_t *)&vlan_filter; + args.in_args_size = sizeof(vlan_filter); + 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_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) {