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
next 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).