From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 841CBA054A; Wed, 7 Sep 2022 09:19:26 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2A384400D6; Wed, 7 Sep 2022 09:19:26 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mails.dpdk.org (Postfix) with ESMTP id 7807940042 for ; Wed, 7 Sep 2022 09:19:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1662535164; x=1694071164; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=rJ+ow87ymv0MHzkMTRfZPzK9WAqOPwZAuMh7uYG3dSI=; b=aKvh6XvS3n5KgtLax9Pwz6hFILtOpCpQxN4bJ4+GbIVB21hLLPM7h4fk FsLBM3EhrQWHnXLD/gAoECcvbxdDl5qbgUNVuMDmhDRhqtHpBs92IR2n/ UVn8Bmve8cjn++dvIlFFfnbvnO2y+8ft6vrE0MXTpf22Uych1T19EbouJ tfjJ5kVOz6gUSR8R4UvZ1laUR/I0tXDezdkbSY89ocbx/Z0y7AJwMLXNN YweWgUNln2O/C6ss6McRkIAiuYjMwrdnY2cLina+D8CZaAGcUOuCPCSGb 70vyyZJignw3KuiUVjzXprQpP0eH5cAsruttEdi6qt+wDl8/oDzjNztIR g==; X-IronPort-AV: E=McAfee;i="6500,9779,10462"; a="279814787" X-IronPort-AV: E=Sophos;i="5.93,296,1654585200"; d="scan'208";a="279814787" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Sep 2022 00:19:21 -0700 X-IronPort-AV: E=Sophos;i="5.93,296,1654585200"; d="scan'208";a="591578731" Received: from intel-cd-odc-kevin.cd.intel.com ([10.240.178.191]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Sep 2022 00:19:19 -0700 From: Kevin Liu To: dev@dpdk.org Cc: Yuying.Zhang@intel.com, beilei.xing@intel.com, stevex.yang@intel.com, Kevin Liu Subject: [PATCH v4] net/i40e: fix single VLAN cannot work normally Date: Wed, 7 Sep 2022 15:18:19 +0000 Message-Id: <20220907151819.93024-1-kevinx.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220818160351.1353003-1-kevinx.liu@intel.com> References: <20220818160351.1353003-1-kevinx.liu@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 After disabling QinQ, single VLAN can not work normally. The reason is that QinQ is not disabled correctly. Before configuring QinQ, need to back up and clean MAC/VLAN filters of all ports. After configuring QinQ, restore MAC/VLAN filters of all ports. When QinQ is disabled, need to set valid_flags to 'I40E_AQ_SET_SWITCH_CFG_OUTER_VLAN' and set first_tag to 'RTE_ETHER_TYPE_QINQ'. Fixes: 38e9762be16a ("net/i40e: add outer VLAN processing") Signed-off-by: Kevin Liu --- v2: refine code --- v3: refine code --- v4: refine code and commit log --- doc/guides/nics/i40e.rst | 1 - drivers/net/i40e/i40e_ethdev.c | 156 ++++++++++++++++++++++----------- 2 files changed, 104 insertions(+), 53 deletions(-) diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst index abb99406b3..15b796e67a 100644 --- a/doc/guides/nics/i40e.rst +++ b/doc/guides/nics/i40e.rst @@ -983,7 +983,6 @@ If FW version >= 8.4, there'll be some Vlan related issues: #. TCI input set for QinQ is invalid. #. Fail to configure TPID for QinQ. -#. Need to enable QinQ before enabling Vlan filter. #. Fail to strip outer Vlan. Example of getting best performance with l3fwd example diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 67d79de08d..4fb0993cc2 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -3909,7 +3909,6 @@ i40e_vlan_tpid_set(struct rte_eth_dev *dev, struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); int qinq = dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_VLAN_EXTEND; - u16 sw_flags = 0, valid_flags = 0; int ret = 0; if ((vlan_type != RTE_ETH_VLAN_TYPE_INNER && @@ -3928,10 +3927,6 @@ i40e_vlan_tpid_set(struct rte_eth_dev *dev, /* 802.1ad frames ability is added in NVM API 1.7*/ if (hw->flags & I40E_HW_FLAG_802_1AD_CAPABLE) { if (qinq) { - if (pf->fw8_3gt) { - sw_flags = I40E_AQ_SET_SWITCH_CFG_OUTER_VLAN; - valid_flags = I40E_AQ_SET_SWITCH_CFG_OUTER_VLAN; - } if (vlan_type == RTE_ETH_VLAN_TYPE_OUTER) hw->first_tag = rte_cpu_to_le_16(tpid); else if (vlan_type == RTE_ETH_VLAN_TYPE_INNER) @@ -3940,8 +3935,8 @@ i40e_vlan_tpid_set(struct rte_eth_dev *dev, if (vlan_type == RTE_ETH_VLAN_TYPE_OUTER) hw->second_tag = rte_cpu_to_le_16(tpid); } - ret = i40e_aq_set_switch_config(hw, sw_flags, - valid_flags, 0, NULL); + ret = i40e_aq_set_switch_config(hw, 0, + 0, 0, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Set switch config failed aq_err: %d", @@ -3993,13 +3988,8 @@ static int i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); - struct i40e_mac_filter_info *mac_filter; struct i40e_vsi *vsi = pf->main_vsi; struct rte_eth_rxmode *rxmode; - struct i40e_mac_filter *f; - int i, num; - void *temp; - int ret; rxmode = &dev->data->dev_conf.rxmode; if (mask & RTE_ETH_VLAN_FILTER_MASK) { @@ -4018,50 +4008,18 @@ i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask) } if (mask & RTE_ETH_VLAN_EXTEND_MASK) { - i = 0; - num = vsi->mac_num; - mac_filter = rte_zmalloc("mac_filter_info_data", - num * sizeof(*mac_filter), 0); - if (mac_filter == NULL) { - PMD_DRV_LOG(ERR, "failed to allocate memory"); - return I40E_ERR_NO_MEMORY; - } - - /* - * Outer VLAN processing is supported after firmware v8.4, kernel driver - * also change the default behavior to support this feature. To align with - * kernel driver, set switch config in 'i40e_vlan_tpie_set' to support for - * outer VLAN processing. But it is forbidden for firmware to change the - * Inner/Outer VLAN configuration while there are MAC/VLAN filters in the - * switch table. Therefore, we need to clear the MAC table before setting - * config, and then restore the MAC table after setting. This feature is - * recommended to be used in firmware v8.6. - */ - /* Remove all existing mac */ - RTE_TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) { - mac_filter[i] = f->mac_info; - ret = i40e_vsi_delete_mac(vsi, &f->mac_info.mac_addr); - if (ret) - PMD_DRV_LOG(ERR, "i40e vsi delete mac fail."); - i++; - } if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_EXTEND) { i40e_vsi_config_double_vlan(vsi, TRUE); - /* Set global registers with default ethertype. */ - i40e_vlan_tpid_set(dev, RTE_ETH_VLAN_TYPE_OUTER, - RTE_ETHER_TYPE_VLAN); - i40e_vlan_tpid_set(dev, RTE_ETH_VLAN_TYPE_INNER, - RTE_ETHER_TYPE_VLAN); + if (!pf->fw8_3gt) { + /* Set global registers with default ethertype. */ + i40e_vlan_tpid_set(dev, RTE_ETH_VLAN_TYPE_OUTER, + RTE_ETHER_TYPE_VLAN); + i40e_vlan_tpid_set(dev, RTE_ETH_VLAN_TYPE_INNER, + RTE_ETHER_TYPE_VLAN); + } } else { i40e_vsi_config_double_vlan(vsi, FALSE); } - /* Restore all mac */ - for (i = 0; i < num; i++) { - ret = i40e_vsi_add_mac(vsi, &mac_filter[i]); - if (ret) - PMD_DRV_LOG(ERR, "i40e vsi add mac fail."); - } - rte_free(mac_filter); } if (mask & RTE_ETH_QINQ_STRIP_MASK) { @@ -6176,9 +6134,103 @@ i40e_dev_init_vlan(struct rte_eth_dev *dev) static int i40e_vsi_config_double_vlan(struct i40e_vsi *vsi, int on) { + struct i40e_mac_filter_info *vmac_filter[RTE_MAX_ETHPORTS]; struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); + struct i40e_pf *pf = I40E_VSI_TO_PF(vsi); + struct i40e_vsi *vvsi[RTE_MAX_ETHPORTS]; + struct i40e_mac_filter_info *mac_filter; + u16 sw_flags = 0, valid_flags = 0; + int vnum[RTE_MAX_ETHPORTS]; + struct i40e_mac_filter *f; + int port_num = 0; + int i, num, j; + void *temp; + int ret = 0; - return i40e_aq_set_port_parameters(hw, vsi->seid, 0, 1, on, NULL); + ret = i40e_aq_set_port_parameters(hw, vsi->seid, 0, 1, on, NULL); + if (ret != I40E_SUCCESS) { + PMD_DRV_LOG(ERR, "Failed to set port params"); + return -1; + } + + if (pf->fw8_3gt) { + /* back up and clean mac/vlan filters of all ports */ + for (j = 0; j < RTE_MAX_ETHPORTS; j++) { + /* + * It is impossible to confirm whether the port is pf + * only through the state field, so it is also necessary + * to verify the intr_handle field. + */ + if (rte_eth_devices[j].state != RTE_ETH_DEV_UNUSED && + rte_eth_devices[j].intr_handle) { + struct rte_eth_dev *tmp_dev = &rte_eth_devices[j]; + struct i40e_pf *tmp_pf = + I40E_DEV_PRIVATE_TO_PF(tmp_dev->data->dev_private); + struct i40e_vsi *tmp_vsi = tmp_pf->main_vsi; + i = 0; + num = tmp_vsi->mac_num; + mac_filter = rte_zmalloc("mac_filter_info_data", + num * sizeof(*mac_filter), 0); + if (mac_filter == NULL) { + PMD_DRV_LOG(ERR, "failed to allocate memory"); + return I40E_ERR_NO_MEMORY; + } + /* + * Outer VLAN processing is supported after firmware v8.4, + * kernel driver also change the default behavior to support + * this feature. To align with kernel driver, set switch + * config in 'i40e_vlan_tpid_set' to support for outer VLAN + * processing. But it is forbidden for firmware to change the + * Inner/Outer VLAN configuration while there are MAC/VLAN + * filters in the switch table. Therefore, we need to clean + * MAC/VLAN filters of all ports before setting config, and + * then restore the MAC table after setting. This feature is + * recommended to be used in firmware v8.6. + */ + /* Remove all existing mac */ + RTE_TAILQ_FOREACH_SAFE(f, &tmp_vsi->mac_list, next, temp) { + mac_filter[i] = f->mac_info; + ret = i40e_vsi_delete_mac(tmp_vsi, &f->mac_info.mac_addr); + if (ret) + PMD_DRV_LOG(ERR, "i40e vsi delete mac fail."); + i++; + } + vmac_filter[port_num] = mac_filter; + vvsi[port_num] = tmp_vsi; + vnum[port_num] = num; + port_num++; + } + } + + if (on) { + sw_flags = I40E_AQ_SET_SWITCH_CFG_OUTER_VLAN; + valid_flags = I40E_AQ_SET_SWITCH_CFG_OUTER_VLAN; + hw->first_tag = rte_cpu_to_le_16(RTE_ETHER_TYPE_VLAN); + } else { + valid_flags = I40E_AQ_SET_SWITCH_CFG_OUTER_VLAN; + hw->first_tag = rte_cpu_to_le_16(RTE_ETHER_TYPE_QINQ); + } + + ret = i40e_aq_set_switch_config(hw, sw_flags, valid_flags, 0, NULL); + if (ret) { + PMD_DRV_LOG(ERR, + "Set switch config failed aq_err: %d", + hw->aq.asq_last_status); + } + + /* restore mac/vlan filters of all ports */ + for (j = 0; j < port_num; j++) { + mac_filter = vmac_filter[j]; + for (i = 0; i < vnum[j]; i++) { + ret = i40e_vsi_add_mac(vvsi[j], &mac_filter[i]); + if (ret) + PMD_DRV_LOG(ERR, "i40e vsi add mac fail."); + } + rte_free(mac_filter); + } + } + + return ret; } static int -- 2.34.1