From: Peng Zhang <peng.zh...@corigine.com>

Control the offload of outer layer VLAN strip in QinQ mode
through the RTE_ETH_QINQ_STRIP_OFFLOAD mask bit.

Signed-off-by: Peng Zhang <peng.zh...@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderl...@corigine.com>
Reviewed-by: Chaoyong He <chaoyong...@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  1 +
 doc/guides/nics/nfp.rst          |  1 +
 drivers/net/nfp/nfp_common.c     | 19 ++++++++++++++-
 drivers/net/nfp/nfp_ctrl.h       |  1 +
 drivers/net/nfp/nfp_rxtx.c       | 41 ++++++++++++++++++++++++++++++++
 drivers/net/nfp/nfp_rxtx.h       |  3 ++-
 6 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 9e075a680b..b15a1ec52c 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -17,6 +17,7 @@ RSS key update       = Y
 RSS reta update      = Y
 Flow control         = Y
 VLAN offload         = Y
+QinQ offload         = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
 Basic stats          = Y
diff --git a/doc/guides/nics/nfp.rst b/doc/guides/nics/nfp.rst
index fffff00f1e..2be15b63d3 100644
--- a/doc/guides/nics/nfp.rst
+++ b/doc/guides/nics/nfp.rst
@@ -293,3 +293,4 @@ Metadata with L2 (1W/4B)
    Tpid just be stored, now we don't handle it
 
    The vlan[0] is the innermost VLAN
+   The vlan[1] is the QinQ info
diff --git a/drivers/net/nfp/nfp_common.c b/drivers/net/nfp/nfp_common.c
index f112a70980..d1822f6b71 100644
--- a/drivers/net/nfp/nfp_common.c
+++ b/drivers/net/nfp/nfp_common.c
@@ -195,7 +195,7 @@ nfp_net_log_device_information(const struct nfp_net_hw *hw)
                        NFD_CFG_MAJOR_VERSION_of(hw->ver),
                        NFD_CFG_MINOR_VERSION_of(hw->ver), hw->max_mtu);
 
-       PMD_INIT_LOG(INFO, "CAP: %#x, %s%s%s%s%s%s%s%s%s%s%s%s%s%s", hw->cap,
+       PMD_INIT_LOG(INFO, "CAP: %#x, %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", hw->cap,
                        hw->cap & NFP_NET_CFG_CTRL_PROMISC   ? "PROMISC "   : 
"",
                        hw->cap & NFP_NET_CFG_CTRL_L2BC      ? "L2BCFILT "  : 
"",
                        hw->cap & NFP_NET_CFG_CTRL_L2MC      ? "L2MCFILT "  : 
"",
@@ -203,6 +203,7 @@ nfp_net_log_device_information(const struct nfp_net_hw *hw)
                        hw->cap & NFP_NET_CFG_CTRL_TXCSUM    ? "TXCSUM "    : 
"",
                        hw->cap & NFP_NET_CFG_CTRL_RXVLAN    ? "RXVLAN "    : 
"",
                        hw->cap & NFP_NET_CFG_CTRL_TXVLAN    ? "TXVLAN "    : 
"",
+                       hw->cap & NFP_NET_CFG_CTRL_RXQINQ    ? "RXQINQ "    : 
"",
                        hw->cap & NFP_NET_CFG_CTRL_SCATTER   ? "SCATTER "   : 
"",
                        hw->cap & NFP_NET_CFG_CTRL_GATHER    ? "GATHER "    : 
"",
                        hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR ? "LIVE_ADDR " : 
"",
@@ -401,6 +402,11 @@ nfp_check_offloads(struct rte_eth_dev *dev)
                        ctrl |= NFP_NET_CFG_CTRL_RXVLAN;
        }
 
+       if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) {
+               if (hw->cap & NFP_NET_CFG_CTRL_RXQINQ)
+                       ctrl |= NFP_NET_CFG_CTRL_RXQINQ;
+       }
+
        hw->mtu = dev->data->mtu;
 
        if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
@@ -751,6 +757,9 @@ nfp_net_infos_get(struct rte_eth_dev *dev, struct 
rte_eth_dev_info *dev_info)
        if (hw->cap & NFP_NET_CFG_CTRL_RXVLAN)
                dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
 
+       if (hw->cap & NFP_NET_CFG_CTRL_RXQINQ)
+               dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_QINQ_STRIP;
+
        if (hw->cap & NFP_NET_CFG_CTRL_RXCSUM)
                dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
                                             RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
@@ -1042,6 +1051,14 @@ nfp_net_vlan_offload_set(struct rte_eth_dev *dev, int 
mask)
                        new_ctrl &= ~NFP_NET_CFG_CTRL_RXVLAN;
        }
 
+       /* QinQ stripping setting */
+       if (mask & RTE_ETH_QINQ_STRIP_MASK) {
+               if (dev_conf->rxmode.offloads & RTE_ETH_RX_OFFLOAD_QINQ_STRIP)
+                       new_ctrl |= NFP_NET_CFG_CTRL_RXQINQ;
+               else
+                       new_ctrl &= ~NFP_NET_CFG_CTRL_RXQINQ;
+       }
+
        if (new_ctrl == hw->ctrl)
                return 0;
 
diff --git a/drivers/net/nfp/nfp_ctrl.h b/drivers/net/nfp/nfp_ctrl.h
index a90846fddf..106779c080 100644
--- a/drivers/net/nfp/nfp_ctrl.h
+++ b/drivers/net/nfp/nfp_ctrl.h
@@ -93,6 +93,7 @@
 #define   NFP_NET_CFG_CTRL_SCATTER        (0x1 <<  8) /* Scatter DMA */
 #define   NFP_NET_CFG_CTRL_GATHER         (0x1 <<  9) /* Gather DMA */
 #define   NFP_NET_CFG_CTRL_LSO            (0x1 << 10) /* LSO/TSO */
+#define   NFP_NET_CFG_CTRL_RXQINQ         (0x1 << 13) /* Enable QINQ strip */
 #define   NFP_NET_CFG_CTRL_RINGCFG        (0x1 << 16) /* Ring runtime changes 
*/
 #define   NFP_NET_CFG_CTRL_RSS            (0x1 << 17) /* RSS */
 #define   NFP_NET_CFG_CTRL_IRQMOD         (0x1 << 18) /* Interrupt moderation 
*/
diff --git a/drivers/net/nfp/nfp_rxtx.c b/drivers/net/nfp/nfp_rxtx.c
index fb271e6d96..40f1702bde 100644
--- a/drivers/net/nfp/nfp_rxtx.c
+++ b/drivers/net/nfp/nfp_rxtx.c
@@ -257,6 +257,46 @@ nfp_net_parse_meta_vlan(const struct nfp_meta_parsed *meta,
        }
 }
 
+/*
+ * nfp_net_parse_meta_qinq() - Set mbuf qinq_strip data based on metadata info
+ *
+ * The out VLAN tci are prepended to the packet data.
+ * Extract and decode it and set the mbuf fields.
+ *
+ * If both RTE_MBUF_F_RX_VLAN and NFP_NET_CFG_CTRL_RXQINQ are set, the 2 VLANs
+ *   have been stripped by the hardware and their TCIs are saved in
+ *   mbuf->vlan_tci (inner) and mbuf->vlan_tci_outer (outer).
+ * If NFP_NET_CFG_CTRL_RXQINQ is set and RTE_MBUF_F_RX_VLAN is unset, only the
+ *   outer VLAN is removed from packet data, but both tci are saved in
+ *   mbuf->vlan_tci (inner) and mbuf->vlan_tci_outer (outer).
+ *
+ * qinq set & vlan set : meta->vlan_layer>=2, meta->vlan[0].offload=1, 
meta->vlan[1].offload=1
+ * qinq set & vlan not set: meta->vlan_layer>=2, 
meta->vlan[1].offload=1,meta->vlan[0].offload=0
+ * qinq not set & vlan set: meta->vlan_layer=1, meta->vlan[0].offload=1
+ * qinq not set & vlan not set: meta->vlan_layer=0
+ */
+static void
+nfp_net_parse_meta_qinq(const struct nfp_meta_parsed *meta,
+               struct nfp_net_rxq *rxq,
+               struct rte_mbuf *mb)
+{
+       struct nfp_net_hw *hw = rxq->hw;
+
+       if ((hw->ctrl & NFP_NET_CFG_CTRL_RXQINQ) == 0 ||
+                       (hw->cap & NFP_NET_CFG_CTRL_RXQINQ) == 0)
+               return;
+
+       if (meta->vlan_layer < NFP_META_MAX_VLANS)
+               return;
+
+       if (meta->vlan[0].offload == 0)
+               mb->vlan_tci = rte_cpu_to_le_16(meta->vlan[0].tci);
+       mb->vlan_tci_outer = rte_cpu_to_le_16(meta->vlan[1].tci);
+       PMD_RX_LOG(DEBUG, "Received outer vlan is %u inter vlan is %u",
+                       mb->vlan_tci_outer, mb->vlan_tci);
+       mb->ol_flags |= RTE_MBUF_F_RX_QINQ | RTE_MBUF_F_RX_QINQ_STRIPPED;
+}
+
 /*
  * RX path design:
  *
@@ -394,6 +434,7 @@ nfp_net_recv_pkts(void *rx_queue, struct rte_mbuf 
**rx_pkts, uint16_t nb_pkts)
                nfp_net_parse_meta(&meta, rxds, rxq, mb);
                nfp_net_parse_meta_hash(&meta, rxds, rxq, mb);
                nfp_net_parse_meta_vlan(&meta, rxds, rxq, mb);
+               nfp_net_parse_meta_qinq(&meta, rxq, mb);
 
                /* Checking the checksum flag */
                nfp_net_rx_cksum(rxq, rxds, mb);
diff --git a/drivers/net/nfp/nfp_rxtx.h b/drivers/net/nfp/nfp_rxtx.h
index a24ec9e560..e3e8b00b48 100644
--- a/drivers/net/nfp/nfp_rxtx.h
+++ b/drivers/net/nfp/nfp_rxtx.h
@@ -43,8 +43,9 @@
  *        starts at position 0 and only @vlan_layer entries contain valid
  *        information.
  *
- *        Currently only 1 layer of vlan is supported,
+ *        Currently only 2 layers of vlan are supported,
  *        vlan[0] - vlan strip info
+ *        vlan[1] - qinq strip info
  *
  * @vlan.offload:  Flag indicates whether VLAN is offloaded
  * @vlan.tpid: Vlan TPID
-- 
2.29.3

Reply via email to