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 1558BA054A; Tue, 6 Sep 2022 10:17:16 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A9D3840143; Tue, 6 Sep 2022 10:17:15 +0200 (CEST) Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by mails.dpdk.org (Postfix) with ESMTP id D96D7400D6 for ; Tue, 6 Sep 2022 10:17:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1662452234; x=1693988234; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=vvyOl/qK4fOEyUohL1tGJyxYtHcNyh4wUVaVFxT+FkY=; b=Ob7ynLEJxXGrjNfE9Bp1joW2G+ScrIHN/l+fFYPpD1XPgIv0VlVnBlrc kCNJSWYecxGMS9AVA2W011ESONMZ/qoGwyxcbFGP9l89t0Z3aJy0m5M/1 gF/ElHKm6A7cq4Ru/X7ijp2V1HLDRjJ4AE2o6mk/rR6rblX+UIjmHY5nz fBGk3ZIG8Y1THx4I9cueqo3yNpCAY0RvFA7bK00Vplra2eSpmiiaIXq8E Ga4fI5GU+ApsGxbN2I5XkZplS4Y1k4CtqvAeeV9Xk0pIwUbXZL9vXWAso R19yGnHFhmbbvktlBFNHKID77fL0R/qKmSi3Aa9d/uLG8n4vFjPD8zy6M Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10461"; a="360484657" X-IronPort-AV: E=Sophos;i="5.93,293,1654585200"; d="scan'208";a="360484657" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Sep 2022 01:17:12 -0700 X-IronPort-AV: E=Sophos;i="5.93,293,1654585200"; d="scan'208";a="703129217" Received: from intel-cd-odc-kevin.cd.intel.com ([10.240.178.191]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Sep 2022 01:17:10 -0700 From: Kevin Liu To: dev@dpdk.org Cc: Yuying.Zhang@intel.com, beilei.xing@intel.com, stevex.yang@intel.com, Kevin Liu , Jiale Song Subject: [PATCH v3] net/i40e: fix single VLAN cannot work normal Date: Tue, 6 Sep 2022 16:15:08 +0000 Message-Id: <20220906161508.8194-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 disable QinQ, single VLAN can not work normal. 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 disable QinQ, need to set valid_flags to 0x0008 and set first_tag to 0x88a8. Fixes: 38e9762be16a ("net/i40e: add outer VLAN processing") Signed-off-by: Kevin Liu Tested-by: Jiale Song --- v2: refine code --- v3: refine code --- doc/guides/nics/i40e.rst | 1 - drivers/net/i40e/i40e_ethdev.c | 147 ++++++++++++++++++++++----------- 2 files changed, 100 insertions(+), 48 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..cf327ed576 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -1650,7 +1650,8 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused) vsi = pf->main_vsi; /* Disable double vlan by default */ - i40e_vsi_config_double_vlan(vsi, FALSE); + if (!pf->fw8_3gt) + i40e_vsi_config_double_vlan(vsi, FALSE); /* Disable S-TAG identification when floating_veb is disabled */ if (!pf->floating_veb) { @@ -3909,7 +3910,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 +3928,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 +3936,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,11 +3989,15 @@ 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 *vmac_filter[RTE_MAX_ETHPORTS]; + struct i40e_vsi *vvsi[RTE_MAX_ETHPORTS]; struct i40e_mac_filter_info *mac_filter; struct i40e_vsi *vsi = pf->main_vsi; struct rte_eth_rxmode *rxmode; + int vnum[RTE_MAX_ETHPORTS]; struct i40e_mac_filter *f; - int i, num; + int port_num = 0; + int i, num, j; void *temp; int ret; @@ -4018,50 +4018,75 @@ 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++; + /*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 (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."); + /*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); } - rte_free(mac_filter); } if (mask & RTE_ETH_QINQ_STRIP_MASK) { @@ -6177,8 +6202,36 @@ static int i40e_vsi_config_double_vlan(struct i40e_vsi *vsi, int on) { struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); + struct i40e_pf *pf = I40E_VSI_TO_PF(vsi); + u16 sw_flags = 0, valid_flags = 0; + int ret = 0; + + 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; + } - return i40e_aq_set_port_parameters(hw, vsi->seid, 0, 1, on, NULL); + if (pf->fw8_3gt) { + 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); + return -1; + } + } + + return ret; } static int -- 2.34.1