DPDK patches and discussions
 help / color / mirror / Atom feed
From: Kevin Liu <kevinx.liu@intel.com>
To: dev@dpdk.org
Cc: Yuying.Zhang@intel.com, beilei.xing@intel.com,
	stevex.yang@intel.com, Kevin Liu <kevinx.liu@intel.com>
Subject: [PATCH] net/i40e: fix incorrect VLAN stripping for QinQ
Date: Thu,  1 Sep 2022 10:05:49 +0000	[thread overview]
Message-ID: <20220901100549.2333654-1-kevinx.liu@intel.com> (raw)

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 <kevinx.liu@intel.com>
---
 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


             reply	other threads:[~2022-09-01  2:08 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-01 10:05 Kevin Liu [this message]
2022-09-02  3:29 ` Yang, Qiming
2022-09-02  6:18   ` Liu, KevinX

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220901100549.2333654-1-kevinx.liu@intel.com \
    --to=kevinx.liu@intel.com \
    --cc=Yuying.Zhang@intel.com \
    --cc=beilei.xing@intel.com \
    --cc=dev@dpdk.org \
    --cc=stevex.yang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).