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 19017A0032; Thu, 1 Sep 2022 04:08:04 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id AB44A40684; Thu, 1 Sep 2022 04:08:03 +0200 (CEST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id 6035A40395 for ; Thu, 1 Sep 2022 04:08:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1661998081; x=1693534081; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=5oD+5UEOJJKzqj1CXvw63LqI8VGu2m73qlaDXIDYHlE=; b=GX5OD9bonSK2kc36msjuzc8ED6d3KkPimYIa9n3/KQ8Zw2VAVxGz5GvN I4nPofMPdRbeh5rNlPMdY6OviDECMzivSaTXKmtZ6EI1nZmphtwgbGIl8 +2pL45qxh1On22xiKG+HWvUPkg346tgEB/5cRSis4rkTL8d1lh5FqAyu2 LT2EIhYHdBG66GLt4NCQWh+MVIp/OjVQxiGtsbr+ZMFDhKvTtiX88QLai fM6GdFdqBH8n82BXM1uLEizWYz2Z5ECcDa02maK0PUMrS74/Ge92Hsmj2 VUNxpHWmSnopcxvqVaambmDV6VCA+FukqItRijqRFota6UN8EQC3JwZo4 A==; X-IronPort-AV: E=McAfee;i="6500,9779,10456"; a="321739305" X-IronPort-AV: E=Sophos;i="5.93,279,1654585200"; d="scan'208";a="321739305" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Aug 2022 19:08:00 -0700 X-IronPort-AV: E=Sophos;i="5.93,279,1654585200"; d="scan'208";a="589274501" 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; 31 Aug 2022 19:07:57 -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] net/i40e: fix incorrect VLAN stripping for QinQ Date: Thu, 1 Sep 2022 10:05:49 +0000 Message-Id: <20220901100549.2333654-1-kevinx.liu@intel.com> X-Mailer: git-send-email 2.34.1 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 QinQ enable, when enable strip function, it is wrong to strip inner VLAN of double VLAN package. The correct action is outer VLAN is stripped. So, need to configure 'outer_vlan_flags' to update vsi. When enable QinQ strip function, need to set 'port_vlan_flags' to configure inner VLAN strip. Signed-off-by: Kevin Liu --- doc/guides/nics/i40e.rst | 2 - drivers/net/i40e/i40e_ethdev.c | 170 +++++++++++++++++++++++++++++++-- drivers/net/i40e/i40e_ethdev.h | 4 + 3 files changed, 164 insertions(+), 12 deletions(-) diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst index 15b796e67a..ffcb2a2220 100644 --- a/doc/guides/nics/i40e.rst +++ b/doc/guides/nics/i40e.rst @@ -982,8 +982,6 @@ Vlan related Features miss when FW >= 8.4 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. -#. 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 27cfda6ff8..0c3009ebfa 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -52,6 +52,8 @@ #define I40E_VSI_TSR_QINQ_STRIP 0x4010 #define I40E_VSI_TSR(_i) (0x00050800 + ((_i) * 4)) +#define I40E_OVLAN_EMOD_SHIFT(x) ((x) << I40E_AQ_VSI_OVLAN_EMOD_SHIFT) + /* Maximun number of capability elements */ #define I40E_MAX_CAP_ELE_NUM 128 @@ -4011,10 +4013,15 @@ i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask) if (mask & RTE_ETH_VLAN_STRIP_MASK) { /* Enable or disable VLAN stripping */ - if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) - i40e_vsi_config_vlan_stripping(vsi, TRUE); - else + if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) { + if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_EXTEND) + i40e_vsi_config_vlan_stripping_v1(vsi, TRUE); + else + i40e_vsi_config_vlan_stripping(vsi, TRUE); + } else { i40e_vsi_config_vlan_stripping(vsi, FALSE); + i40e_vsi_config_vlan_stripping_v1(vsi, FALSE); + } } if (mask & RTE_ETH_VLAN_EXTEND_MASK) { @@ -4068,6 +4075,10 @@ i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask) if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_EXTEND) { if (pf->fw8_3gt) { i40e_vsi_config_qinq(vsi, TRUE); + if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) { + i40e_vsi_config_vlan_stripping(vsi, FALSE); + i40e_vsi_config_vlan_stripping_v1(vsi, TRUE); + } } else { i40e_vsi_config_double_vlan(vsi, TRUE); /* Set global registers with default ethertype. */ @@ -4077,10 +4088,15 @@ i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask) RTE_ETHER_TYPE_VLAN); } } else { - if (pf->fw8_3gt) + if (pf->fw8_3gt) { i40e_vsi_config_qinq(vsi, FALSE); - else + if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) { + i40e_vsi_config_vlan_stripping_v1(vsi, FALSE); + i40e_vsi_config_vlan_stripping(vsi, TRUE); + } + } else { i40e_vsi_config_double_vlan(vsi, FALSE); + } } /*restore mac/vlan filters of all ports*/ for (j = 0; j < port_num; j++) { @@ -4096,10 +4112,17 @@ i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask) if (mask & RTE_ETH_QINQ_STRIP_MASK) { /* Enable or disable outer VLAN stripping */ - if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) - i40e_vsi_config_outer_vlan_stripping(vsi, TRUE); - else - i40e_vsi_config_outer_vlan_stripping(vsi, FALSE); + if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) { + if (pf->fw8_3gt) + i40e_vsi_config_inner_vlan_stripping(vsi, TRUE); + else + i40e_vsi_config_outer_vlan_stripping(vsi, TRUE); + } else { + if (pf->fw8_3gt) + i40e_vsi_config_inner_vlan_stripping(vsi, FALSE); + else + i40e_vsi_config_outer_vlan_stripping(vsi, FALSE); + } } return 0; @@ -5231,6 +5254,7 @@ int i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi, struct i40e_vsi_vlan_pvid_info *info) { + struct i40e_pf *pf = I40E_VSI_TO_PF(vsi); struct i40e_hw *hw; struct i40e_vsi_context ctxt; uint8_t vlan_flags = 0; @@ -5241,6 +5265,9 @@ i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi, return I40E_ERR_PARAM; } + if (pf->fw8_3gt) + return i40e_vsi_vlan_ovid_set(vsi, info); + if (info->on) { vsi->info.pvid = info->config.pvid; /** @@ -5880,8 +5907,16 @@ i40e_vsi_setup(struct i40e_pf *pf, memset(&ctxt, 0, sizeof(ctxt)); vsi->info.valid_sections |= rte_cpu_to_le_16(I40E_AQ_VSI_PROP_VLAN_VALID); - vsi->info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL | + if (pf->fw8_3gt) { + vsi->info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL | + I40E_AQ_VSI_PVLAN_EMOD_NOTHING; + vsi->info.outer_vlan_flags = I40E_AQ_VSI_OVLAN_MODE_ALL | + I40E_OVLAN_EMOD_SHIFT(I40E_AQ_VSI_OVLAN_EMOD_SHOW_ALL) | + I40E_OVLAN_EMOD_SHIFT(I40E_AQ_VSI_OVLAN_CTRL_ENA); + } else { + vsi->info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL | I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH; + } rte_memcpy(&ctxt.info, &vsi->info, sizeof(struct i40e_aqc_vsi_properties_data)); ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info, @@ -6175,6 +6210,121 @@ i40e_vsi_config_vlan_stripping(struct i40e_vsi *vsi, bool on) return ret; } +int i40e_vsi_config_vlan_stripping_v1(struct i40e_vsi *vsi, bool on) +{ + struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); + struct i40e_vsi_context ctxt; + uint8_t vlan_flags; + int ret = I40E_SUCCESS; + + /* Check if it has been already on or off */ + if (vsi->info.valid_sections & + rte_cpu_to_le_16(I40E_AQ_VSI_PROP_VLAN_VALID)) { + if (on) { + if ((vsi->info.outer_vlan_flags & + I40E_AQ_VSI_OVLAN_EMOD_MASK) == 0) + return 0; /* already on */ + } else { + if ((vsi->info.outer_vlan_flags & + I40E_AQ_VSI_OVLAN_EMOD_MASK) == + I40E_AQ_VSI_OVLAN_EMOD_MASK) + return 0; /* already off */ + } + } + + if (on) + vlan_flags = I40E_AQ_VSI_OVLAN_MODE_ALL | + I40E_OVLAN_EMOD_SHIFT(I40E_AQ_VSI_OVLAN_EMOD_SHOW_ALL) | + I40E_OVLAN_EMOD_SHIFT(I40E_AQ_VSI_OVLAN_CTRL_ENA); + else + vlan_flags = I40E_AQ_VSI_OVLAN_MODE_ALL | + I40E_OVLAN_EMOD_SHIFT(I40E_AQ_VSI_OVLAN_EMOD_NOTHING) | + I40E_OVLAN_EMOD_SHIFT(I40E_AQ_VSI_OVLAN_CTRL_ENA); + + vsi->info.valid_sections = + rte_cpu_to_le_16(I40E_AQ_VSI_PROP_VLAN_VALID); + vsi->info.outer_vlan_flags = vlan_flags; + ctxt.seid = vsi->seid; + rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); + ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL); + if (ret) + PMD_DRV_LOG(INFO, "Update VSI failed to %s outer vlan stripping", + on ? "enable" : "disable"); + + return ret; +} + +int i40e_vsi_config_inner_vlan_stripping(struct i40e_vsi *vsi, bool on) +{ + struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); + struct i40e_vsi_context ctxt; + uint8_t vlan_flags; + int ret = I40E_SUCCESS; + + if (on) + vlan_flags = I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH; + else + vlan_flags = I40E_AQ_VSI_PVLAN_EMOD_NOTHING; + vsi->info.valid_sections = + rte_cpu_to_le_16(I40E_AQ_VSI_PROP_VLAN_VALID); + vsi->info.port_vlan_flags &= ~(I40E_AQ_VSI_PVLAN_EMOD_MASK); + vsi->info.port_vlan_flags |= vlan_flags; + ctxt.seid = vsi->seid; + rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); + ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL); + if (ret) + PMD_DRV_LOG(INFO, "Update VSI failed to %s inner stripping", + on ? "enable" : "disable"); + + return ret; +} + +int +i40e_vsi_vlan_ovid_set(struct i40e_vsi *vsi, + struct i40e_vsi_vlan_pvid_info *info) +{ + struct i40e_hw *hw; + struct i40e_vsi_context ctxt; + uint8_t vlan_flags = 0; + int ret; + + if (vsi == NULL || info == NULL) { + PMD_DRV_LOG(ERR, "invalid parameters"); + return I40E_ERR_PARAM; + } + + if (info->on) { + vsi->info.outer_vlan = info->config.pvid; + vlan_flags = I40E_AQ_VSI_OVLAN_MODE_UNTAGGED | + I40E_AQ_VSI_OVLAN_INSERT_PVID | + I40E_OVLAN_EMOD_SHIFT(I40E_AQ_VSI_OVLAN_EMOD_HIDE_ALL) | + I40E_OVLAN_EMOD_SHIFT(I40E_AQ_VSI_OVLAN_CTRL_ENA); + } else { + vsi->info.outer_vlan = 0; + if (info->config.reject.tagged == 0) + vlan_flags |= I40E_AQ_VSI_OVLAN_MODE_TAGGED; + + if (info->config.reject.untagged == 0) + vlan_flags |= I40E_AQ_VSI_OVLAN_MODE_UNTAGGED; + } + vsi->info.outer_vlan_flags |= vlan_flags; + vsi->info.outer_vlan_flags &= ~(I40E_AQ_VSI_OVLAN_INSERT_PVID | + I40E_AQ_VSI_OVLAN_MODE_MASK); + vsi->info.valid_sections = + rte_cpu_to_le_16(I40E_AQ_VSI_PROP_VLAN_VALID); + memset(&ctxt, 0, sizeof(ctxt)); + rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); + ctxt.seid = vsi->seid; + + hw = I40E_VSI_TO_HW(vsi); + ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL); + if (ret != I40E_SUCCESS) + PMD_DRV_LOG(ERR, "Failed to update VSI params"); + + return ret; +} + + static int i40e_dev_init_vlan(struct rte_eth_dev *dev) { diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index fe943a45ff..2f513fce52 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -1316,6 +1316,10 @@ void i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi); int i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi, struct i40e_vsi_vlan_pvid_info *info); int i40e_vsi_config_vlan_stripping(struct i40e_vsi *vsi, bool on); +int i40e_vsi_config_vlan_stripping_v1(struct i40e_vsi *vsi, bool on); +int i40e_vsi_config_inner_vlan_stripping(struct i40e_vsi *vsi, bool on); +int i40e_vsi_vlan_ovid_set(struct i40e_vsi *vsi, + struct i40e_vsi_vlan_pvid_info *info); int i40e_vsi_config_vlan_filter(struct i40e_vsi *vsi, bool on); uint64_t i40e_config_hena(const struct i40e_adapter *adapter, uint64_t flags); uint64_t i40e_parse_hena(const struct i40e_adapter *adapter, uint64_t flags); -- 2.34.1