@@ -13,47 +13,6 @@
*/
#define NFP_NET_CFG_BAR_SZ (32 * 1024)
-/* Offset in Freelist buffer where packet starts on RX */
-#define NFP_NET_RX_OFFSET 32
-
-/* Working with metadata api (NFD version > 3.0) */
-#define NFP_NET_META_FIELD_SIZE 4
-#define NFP_NET_META_FIELD_MASK ((1 << NFP_NET_META_FIELD_SIZE) - 1)
-#define NFP_NET_META_HEADER_SIZE 4
-#define NFP_NET_META_NFDK_LENGTH 8
-
-/* Working with metadata vlan api (NFD version >= 2.0) */
-#define NFP_NET_META_VLAN_INFO 16
-#define NFP_NET_META_VLAN_OFFLOAD 31
-#define NFP_NET_META_VLAN_TPID 3
-#define NFP_NET_META_VLAN_MASK ((1 << NFP_NET_META_VLAN_INFO) - 1)
-#define NFP_NET_META_VLAN_TPID_MASK ((1 << NFP_NET_META_VLAN_TPID) - 1)
-#define NFP_NET_META_TPID(d) (((d) >> NFP_NET_META_VLAN_INFO) & \
- NFP_NET_META_VLAN_TPID_MASK)
-
-/* Prepend field types */
-#define NFP_NET_META_HASH 1 /* Next field carries hash type */
-#define NFP_NET_META_MARK 2
-#define NFP_NET_META_VLAN 4
-#define NFP_NET_META_PORTID 5
-#define NFP_NET_META_IPSEC 9
-
-#define NFP_META_PORT_ID_CTRL ~0U
-
-/* Hash type prepended when a RSS hash was computed */
-#define NFP_NET_RSS_NONE 0
-#define NFP_NET_RSS_IPV4 1
-#define NFP_NET_RSS_IPV6 2
-#define NFP_NET_RSS_IPV6_EX 3
-#define NFP_NET_RSS_IPV4_TCP 4
-#define NFP_NET_RSS_IPV6_TCP 5
-#define NFP_NET_RSS_IPV6_EX_TCP 6
-#define NFP_NET_RSS_IPV4_UDP 7
-#define NFP_NET_RSS_IPV6_UDP 8
-#define NFP_NET_RSS_IPV6_EX_UDP 9
-#define NFP_NET_RSS_IPV4_SCTP 10
-#define NFP_NET_RSS_IPV6_SCTP 11
-
/*
* @NFP_NET_TXR_MAX: Maximum number of TX rings
* @NFP_NET_TXR_MASK: Mask for TX rings
@@ -16,6 +16,7 @@
#include "../nfp_cpp_bridge.h"
#include "../nfp_logs.h"
#include "../nfp_mtr.h"
+#include "../nfp_net_meta.h"
#include "nfp_flower_ctrl.h"
#include "nfp_flower_representor.h"
#include "nfp_flower_service.h"
@@ -7,6 +7,7 @@
#include "../nfpcore/nfp_nsp.h"
#include "../nfp_logs.h"
+#include "../nfp_net_meta.h"
#include "nfp_flower_ctrl.h"
#include "nfp_flower_representor.h"
@@ -10,6 +10,7 @@
#include "../nfd3/nfp_nfd3.h"
#include "../nfdk/nfp_nfdk.h"
#include "../nfp_logs.h"
+#include "../nfp_net_meta.h"
#include "nfp_flower_representor.h"
#include "nfp_mtr.h"
#include "nfp_flower_service.h"
@@ -41,6 +41,7 @@ sources = files(
'nfp_net_common.c',
'nfp_net_ctrl.c',
'nfp_net_flow.c',
+ 'nfp_net_meta.c',
'nfp_rxtx.c',
'nfp_service.c',
)
@@ -10,6 +10,7 @@
#include "../flower/nfp_flower.h"
#include "../nfp_logs.h"
+#include "../nfp_net_meta.h"
/* Flags in the host TX descriptor */
#define NFD3_DESC_TX_CSUM RTE_BIT32(7)
@@ -11,6 +11,7 @@
#include "../flower/nfp_flower.h"
#include "../nfp_logs.h"
+#include "../nfp_net_meta.h"
#define NFDK_TX_DESC_GATHER_MAX 17
@@ -18,6 +18,7 @@
#include "nfp_net_common.h"
#include "nfp_net_ctrl.h"
#include "nfp_rxtx.h"
+#include "nfp_net_meta.h"
#define NFP_UDP_ESP_PORT 4500
@@ -168,12 +168,6 @@ struct nfp_net_ipsec_data {
struct nfp_ipsec_session *sa_entries[NFP_NET_IPSEC_MAX_SA_CNT];
};
-enum nfp_ipsec_meta_layer {
- NFP_IPSEC_META_SAIDX, /**< Order of SA index in metadata */
- NFP_IPSEC_META_SEQLOW, /**< Order of Sequence Number (low 32bits) in metadata */
- NFP_IPSEC_META_SEQHI, /**< Order of Sequence Number (high 32bits) in metadata */
-};
-
int nfp_ipsec_init(struct rte_eth_dev *dev);
void nfp_ipsec_uninit(struct rte_eth_dev *dev);
@@ -15,6 +15,7 @@
#include "nfpcore/nfp_mip.h"
#include "nfpcore/nfp_nsp.h"
#include "nfp_logs.h"
+#include "nfp_net_meta.h"
#define NFP_TX_MAX_SEG UINT8_MAX
#define NFP_TX_MAX_MTU_SEG 8
@@ -2038,29 +2039,6 @@ nfp_net_check_dma_mask(struct nfp_net_hw *hw,
return 0;
}
-void
-nfp_net_init_metadata_format(struct nfp_net_hw *hw)
-{
- /*
- * ABI 4.x and ctrl vNIC always use chained metadata, in other cases we allow use of
- * single metadata if only RSS(v1) is supported by hw capability, and RSS(v2)
- * also indicate that we are using chained metadata.
- */
- if (hw->ver.major == 4) {
- hw->meta_format = NFP_NET_METAFORMAT_CHAINED;
- } else if ((hw->super.cap & NFP_NET_CFG_CTRL_CHAIN_META) != 0) {
- hw->meta_format = NFP_NET_METAFORMAT_CHAINED;
- /*
- * RSS is incompatible with chained metadata. hw->super.cap just represents
- * firmware's ability rather than the firmware's configuration. We decide
- * to reduce the confusion to allow us can use hw->super.cap to identify RSS later.
- */
- hw->super.cap &= ~NFP_NET_CFG_CTRL_RSS;
- } else {
- hw->meta_format = NFP_NET_METAFORMAT_SINGLE;
- }
-}
-
void
nfp_net_cfg_read_version(struct nfp_net_hw *hw)
{
@@ -16,6 +16,7 @@
#include "nfpcore/nfp_sync.h"
#include "nfp_net_ctrl.h"
#include "nfp_service.h"
+#include "nfp_net_meta.h"
/* Interrupt definitions */
#define NFP_NET_IRQ_LSC_IDX 0
@@ -67,11 +68,6 @@ enum nfp_app_fw_id {
NFP_APP_FW_FLOWER_NIC = 0x3,
};
-enum nfp_net_meta_format {
- NFP_NET_METAFORMAT_SINGLE,
- NFP_NET_METAFORMAT_CHAINED,
-};
-
/* Parsed control BAR TLV capabilities */
struct nfp_net_tlv_caps {
uint32_t mbox_off; /**< VNIC mailbox area offset */
@@ -306,7 +302,6 @@ void nfp_net_tx_desc_limits(struct nfp_net_hw *hw,
uint16_t *min_tx_desc,
uint16_t *max_tx_desc);
int nfp_net_check_dma_mask(struct nfp_net_hw *hw, char *name);
-void nfp_net_init_metadata_format(struct nfp_net_hw *hw);
void nfp_net_cfg_read_version(struct nfp_net_hw *hw);
int nfp_net_firmware_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size);
bool nfp_net_is_valid_nfd_version(struct nfp_net_fw_ver version);
new file mode 100644
@@ -0,0 +1,320 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Corigine, Inc.
+ * All rights reserved.
+ */
+
+#include "nfp_net_meta.h"
+
+#include "nfp_net_common.h"
+#include "nfp_ipsec.h"
+#include "nfp_logs.h"
+
+enum nfp_ipsec_meta_layer {
+ NFP_IPSEC_META_SAIDX, /**< Order of SA index in metadata */
+ NFP_IPSEC_META_SEQLOW, /**< Order of Sequence Number (low 32bits) in metadata */
+ NFP_IPSEC_META_SEQHI, /**< Order of Sequence Number (high 32bits) in metadata */
+};
+
+/* Parse the chained metadata from packet */
+static bool
+nfp_net_parse_chained_meta(uint8_t *meta_base,
+ rte_be32_t meta_header,
+ struct nfp_meta_parsed *meta)
+{
+ uint32_t meta_info;
+ uint32_t vlan_info;
+ uint8_t *meta_offset;
+
+ meta_info = rte_be_to_cpu_32(meta_header);
+ meta_offset = meta_base + 4;
+
+ for (; meta_info != 0; meta_info >>= NFP_NET_META_FIELD_SIZE, meta_offset += 4) {
+ switch (meta_info & NFP_NET_META_FIELD_MASK) {
+ case NFP_NET_META_PORTID:
+ meta->port_id = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
+ break;
+ case NFP_NET_META_HASH:
+ /* Next field type is about the hash type */
+ meta_info >>= NFP_NET_META_FIELD_SIZE;
+ /* Hash value is in the data field */
+ meta->hash = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
+ meta->hash_type = meta_info & NFP_NET_META_FIELD_MASK;
+ break;
+ case NFP_NET_META_VLAN:
+ vlan_info = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
+ meta->vlan[meta->vlan_layer].offload =
+ vlan_info >> NFP_NET_META_VLAN_OFFLOAD;
+ meta->vlan[meta->vlan_layer].tci =
+ vlan_info & NFP_NET_META_VLAN_MASK;
+ meta->vlan[meta->vlan_layer].tpid = NFP_NET_META_TPID(vlan_info);
+ meta->vlan_layer++;
+ break;
+ case NFP_NET_META_IPSEC:
+ meta->sa_idx = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
+ meta->ipsec_type = meta_info & NFP_NET_META_FIELD_MASK;
+ break;
+ case NFP_NET_META_MARK:
+ meta->flags |= (1 << NFP_NET_META_MARK);
+ meta->mark_id = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
+ break;
+ default:
+ /* Unsupported metadata can be a performance issue */
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
+ * Parse the single metadata
+ *
+ * The RSS hash and hash-type are prepended to the packet data.
+ * Get it from metadata area.
+ */
+static inline void
+nfp_net_parse_single_meta(uint8_t *meta_base,
+ rte_be32_t meta_header,
+ struct nfp_meta_parsed *meta)
+{
+ meta->hash_type = rte_be_to_cpu_32(meta_header);
+ meta->hash = rte_be_to_cpu_32(*(rte_be32_t *)(meta_base + 4));
+}
+
+/* Set mbuf hash data based on the metadata info */
+static void
+nfp_net_parse_meta_hash(const struct nfp_meta_parsed *meta,
+ struct nfp_net_rxq *rxq,
+ struct rte_mbuf *mbuf)
+{
+ struct nfp_net_hw *hw = rxq->hw;
+
+ if ((hw->super.ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0)
+ return;
+
+ mbuf->hash.rss = meta->hash;
+ mbuf->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
+}
+
+/* Set mbuf vlan_strip data based on metadata info */
+static void
+nfp_net_parse_meta_vlan(const struct nfp_meta_parsed *meta,
+ struct nfp_net_rx_desc *rxd,
+ struct nfp_net_rxq *rxq,
+ struct rte_mbuf *mb)
+{
+ uint32_t ctrl = rxq->hw->super.ctrl;
+
+ /* Skip if hardware don't support setting vlan. */
+ if ((ctrl & (NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_RXVLAN_V2)) == 0)
+ return;
+
+ /*
+ * The firmware support two ways to send the VLAN info (with priority) :
+ * 1. Using the metadata when NFP_NET_CFG_CTRL_RXVLAN_V2 is set,
+ * 2. Using the descriptor when NFP_NET_CFG_CTRL_RXVLAN is set.
+ */
+ if ((ctrl & NFP_NET_CFG_CTRL_RXVLAN_V2) != 0) {
+ if (meta->vlan_layer > 0 && meta->vlan[0].offload != 0) {
+ mb->vlan_tci = rte_cpu_to_le_32(meta->vlan[0].tci);
+ mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
+ }
+ } else if ((ctrl & NFP_NET_CFG_CTRL_RXVLAN) != 0) {
+ if ((rxd->rxd.flags & PCIE_DESC_RX_VLAN) != 0) {
+ mb->vlan_tci = rte_cpu_to_le_32(rxd->rxd.offload_info);
+ mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
+ }
+ }
+}
+
+/*
+ * 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_hw *hw = &rxq->hw->super;
+
+ 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 TCI is %u inner vlan TCI is %u",
+ mb->vlan_tci_outer, mb->vlan_tci);
+ mb->ol_flags |= RTE_MBUF_F_RX_QINQ | RTE_MBUF_F_RX_QINQ_STRIPPED;
+}
+
+/*
+ * Set mbuf IPsec Offload features based on metadata info.
+ *
+ * The IPsec Offload features is prepended to the mbuf ol_flags.
+ * Extract and decode metadata info and set the mbuf ol_flags.
+ */
+static void
+nfp_net_parse_meta_ipsec(struct nfp_meta_parsed *meta,
+ struct nfp_net_rxq *rxq,
+ struct rte_mbuf *mbuf)
+{
+ int offset;
+ uint32_t sa_idx;
+ struct nfp_net_hw *hw;
+ struct nfp_tx_ipsec_desc_msg *desc_md;
+
+ hw = rxq->hw;
+ sa_idx = meta->sa_idx;
+
+ if (meta->ipsec_type != NFP_NET_META_IPSEC)
+ return;
+
+ if (sa_idx >= NFP_NET_IPSEC_MAX_SA_CNT) {
+ mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED;
+ } else {
+ mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD;
+ offset = hw->ipsec_data->pkt_dynfield_offset;
+ desc_md = RTE_MBUF_DYNFIELD(mbuf, offset, struct nfp_tx_ipsec_desc_msg *);
+ desc_md->sa_idx = sa_idx;
+ desc_md->enc = 0;
+ }
+}
+
+static void
+nfp_net_parse_meta_mark(const struct nfp_meta_parsed *meta,
+ struct rte_mbuf *mbuf)
+{
+ if (((meta->flags >> NFP_NET_META_MARK) & 0x1) == 0)
+ return;
+
+ mbuf->hash.fdir.hi = meta->mark_id;
+ mbuf->ol_flags |= RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID;
+}
+
+/* Parse the metadata from packet */
+void
+nfp_net_parse_meta(struct nfp_net_rx_desc *rxds,
+ struct nfp_net_rxq *rxq,
+ struct nfp_net_hw *hw,
+ struct rte_mbuf *mb,
+ struct nfp_meta_parsed *meta)
+{
+ uint8_t *meta_base;
+ rte_be32_t meta_header;
+
+ if (unlikely(NFP_DESC_META_LEN(rxds) == 0))
+ return;
+
+ meta_base = rte_pktmbuf_mtod_offset(mb, uint8_t *, -NFP_DESC_META_LEN(rxds));
+ meta_header = *(rte_be32_t *)meta_base;
+
+ switch (hw->meta_format) {
+ case NFP_NET_METAFORMAT_CHAINED:
+ if (nfp_net_parse_chained_meta(meta_base, meta_header, meta)) {
+ nfp_net_parse_meta_hash(meta, rxq, mb);
+ nfp_net_parse_meta_vlan(meta, rxds, rxq, mb);
+ nfp_net_parse_meta_qinq(meta, rxq, mb);
+ nfp_net_parse_meta_ipsec(meta, rxq, mb);
+ nfp_net_parse_meta_mark(meta, mb);
+ } else {
+ PMD_RX_LOG(DEBUG, "RX chained metadata format is wrong!");
+ }
+ break;
+ case NFP_NET_METAFORMAT_SINGLE:
+ if ((rxds->rxd.flags & PCIE_DESC_RX_RSS) != 0) {
+ nfp_net_parse_single_meta(meta_base, meta_header, meta);
+ nfp_net_parse_meta_hash(meta, rxq, mb);
+ }
+ break;
+ default:
+ PMD_RX_LOG(DEBUG, "RX metadata do not exist.");
+ }
+}
+
+void
+nfp_net_init_metadata_format(struct nfp_net_hw *hw)
+{
+ /*
+ * ABI 4.x and ctrl vNIC always use chained metadata, in other cases we allow use of
+ * single metadata if only RSS(v1) is supported by hw capability, and RSS(v2)
+ * also indicate that we are using chained metadata.
+ */
+ if (hw->ver.major == 4) {
+ hw->meta_format = NFP_NET_METAFORMAT_CHAINED;
+ } else if ((hw->super.cap & NFP_NET_CFG_CTRL_CHAIN_META) != 0) {
+ hw->meta_format = NFP_NET_METAFORMAT_CHAINED;
+ /*
+ * RSS is incompatible with chained metadata. hw->super.cap just represents
+ * firmware's ability rather than the firmware's configuration. We decide
+ * to reduce the confusion to allow us can use hw->super.cap to identify RSS later.
+ */
+ hw->super.cap &= ~NFP_NET_CFG_CTRL_RSS;
+ } else {
+ hw->meta_format = NFP_NET_METAFORMAT_SINGLE;
+ }
+}
+
+void
+nfp_net_set_meta_vlan(struct nfp_net_meta_raw *meta_data,
+ struct rte_mbuf *pkt,
+ uint8_t layer)
+{
+ uint16_t tpid;
+ uint16_t vlan_tci;
+
+ tpid = RTE_ETHER_TYPE_VLAN;
+ vlan_tci = pkt->vlan_tci;
+
+ meta_data->data[layer] = rte_cpu_to_be_32(tpid << 16 | vlan_tci);
+}
+
+void
+nfp_net_set_meta_ipsec(struct nfp_net_meta_raw *meta_data,
+ struct nfp_net_txq *txq,
+ struct rte_mbuf *pkt,
+ uint8_t layer,
+ uint8_t ipsec_layer)
+{
+ int offset;
+ struct nfp_net_hw *hw;
+ struct nfp_tx_ipsec_desc_msg *desc_md;
+
+ hw = txq->hw;
+ offset = hw->ipsec_data->pkt_dynfield_offset;
+ desc_md = RTE_MBUF_DYNFIELD(pkt, offset, struct nfp_tx_ipsec_desc_msg *);
+
+ switch (ipsec_layer) {
+ case NFP_IPSEC_META_SAIDX:
+ meta_data->data[layer] = desc_md->sa_idx;
+ break;
+ case NFP_IPSEC_META_SEQLOW:
+ meta_data->data[layer] = desc_md->esn.low;
+ break;
+ case NFP_IPSEC_META_SEQHI:
+ meta_data->data[layer] = desc_md->esn.hi;
+ break;
+ default:
+ break;
+ }
+}
new file mode 100644
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2014, 2015 Netronome Systems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef __NFP_NET_META_H__
+#define __NFP_NET_META_H__
+
+#include "nfp_rxtx.h"
+
+/* Hash type prepended when a RSS hash was computed */
+#define NFP_NET_RSS_NONE 0
+#define NFP_NET_RSS_IPV4 1
+#define NFP_NET_RSS_IPV6 2
+#define NFP_NET_RSS_IPV6_EX 3
+#define NFP_NET_RSS_IPV4_TCP 4
+#define NFP_NET_RSS_IPV6_TCP 5
+#define NFP_NET_RSS_IPV6_EX_TCP 6
+#define NFP_NET_RSS_IPV4_UDP 7
+#define NFP_NET_RSS_IPV6_UDP 8
+#define NFP_NET_RSS_IPV6_EX_UDP 9
+#define NFP_NET_RSS_IPV4_SCTP 10
+#define NFP_NET_RSS_IPV6_SCTP 11
+
+/* Offset in Freelist buffer where packet starts on RX */
+#define NFP_NET_RX_OFFSET 32
+
+/* Working with metadata api (NFD version > 3.0) */
+#define NFP_NET_META_FIELD_SIZE 4
+#define NFP_NET_META_FIELD_MASK ((1 << NFP_NET_META_FIELD_SIZE) - 1)
+#define NFP_NET_META_HEADER_SIZE 4
+#define NFP_NET_META_NFDK_LENGTH 8
+
+/* Working with metadata vlan api (NFD version >= 2.0) */
+#define NFP_NET_META_VLAN_INFO 16
+#define NFP_NET_META_VLAN_OFFLOAD 31
+#define NFP_NET_META_VLAN_TPID 3
+#define NFP_NET_META_VLAN_MASK ((1 << NFP_NET_META_VLAN_INFO) - 1)
+#define NFP_NET_META_VLAN_TPID_MASK ((1 << NFP_NET_META_VLAN_TPID) - 1)
+#define NFP_NET_META_TPID(d) (((d) >> NFP_NET_META_VLAN_INFO) & \
+ NFP_NET_META_VLAN_TPID_MASK)
+
+/* Prepend field types */
+#define NFP_NET_META_HASH 1 /* Next field carries hash type */
+#define NFP_NET_META_MARK 2
+#define NFP_NET_META_VLAN 4
+#define NFP_NET_META_PORTID 5
+#define NFP_NET_META_IPSEC 9
+
+#define NFP_META_PORT_ID_CTRL ~0U
+
+#define NFP_DESC_META_LEN(d) ((d)->rxd.meta_len_dd & PCIE_DESC_RX_META_LEN_MASK)
+
+/* Maximum number of NFP packet metadata fields. */
+#define NFP_META_MAX_FIELDS 8
+
+/* Maximum number of supported VLANs in parsed form packet metadata. */
+#define NFP_META_MAX_VLANS 2
+
+enum nfp_net_meta_format {
+ NFP_NET_METAFORMAT_SINGLE,
+ NFP_NET_METAFORMAT_CHAINED,
+};
+
+/* Describe the raw metadata format. */
+struct nfp_net_meta_raw {
+ uint32_t header; /**< Field type header (see format in nfp.rst) */
+ uint32_t data[NFP_META_MAX_FIELDS]; /**< Array of each fields data member */
+ uint8_t length; /**< Number of valid fields in @header */
+};
+
+/* Record metadata parsed from packet */
+struct nfp_meta_parsed {
+ uint32_t port_id; /**< Port id value */
+ uint32_t sa_idx; /**< IPsec SA index */
+ uint32_t hash; /**< RSS hash value */
+ uint32_t mark_id; /**< Mark id value */
+ uint16_t flags; /**< Bitmap to indicate if meta exist */
+ uint8_t hash_type; /**< RSS hash type */
+ uint8_t ipsec_type; /**< IPsec type */
+ uint8_t vlan_layer; /**< The valid number of value in @vlan[] */
+ /**
+ * Holds information parses from NFP_NET_META_VLAN.
+ * The inner most vlan starts at position 0
+ */
+ struct {
+ uint8_t offload; /**< Flag indicates whether VLAN is offloaded */
+ uint8_t tpid; /**< Vlan TPID */
+ uint16_t tci; /**< Vlan TCI (PCP + Priority + VID) */
+ } vlan[NFP_META_MAX_VLANS];
+};
+
+void nfp_net_init_metadata_format(struct nfp_net_hw *hw);
+void nfp_net_parse_meta(struct nfp_net_rx_desc *rxds,
+ struct nfp_net_rxq *rxq,
+ struct nfp_net_hw *hw,
+ struct rte_mbuf *mb,
+ struct nfp_meta_parsed *meta);
+void nfp_net_set_meta_vlan(struct nfp_net_meta_raw *meta_data,
+ struct rte_mbuf *pkt,
+ uint8_t layer);
+void nfp_net_set_meta_ipsec(struct nfp_net_meta_raw *meta_data,
+ struct nfp_net_txq *txq,
+ struct rte_mbuf *pkt,
+ uint8_t layer,
+ uint8_t ipsec_layer);
+
+#endif /* __NFP_NET_META_H__ */
@@ -16,30 +16,7 @@
#include "nfp_ipsec.h"
#include "nfp_logs.h"
-
-/* Maximum number of supported VLANs in parsed form packet metadata. */
-#define NFP_META_MAX_VLANS 2
-
-/* Record metadata parsed from packet */
-struct nfp_meta_parsed {
- uint32_t port_id; /**< Port id value */
- uint32_t sa_idx; /**< IPsec SA index */
- uint32_t hash; /**< RSS hash value */
- uint32_t mark_id; /**< Mark id value */
- uint16_t flags; /**< Bitmap to indicate if meta exist */
- uint8_t hash_type; /**< RSS hash type */
- uint8_t ipsec_type; /**< IPsec type */
- uint8_t vlan_layer; /**< The valid number of value in @vlan[] */
- /**
- * Holds information parses from NFP_NET_META_VLAN.
- * The inner most vlan starts at position 0
- */
- struct {
- uint8_t offload; /**< Flag indicates whether VLAN is offloaded */
- uint8_t tpid; /**< Vlan TPID */
- uint16_t tci; /**< Vlan TCI (PCP + Priority + VID) */
- } vlan[NFP_META_MAX_VLANS];
-};
+#include "nfp_net_meta.h"
/*
* The bit format and map of nfp packet type for rxd.offload_info in Rx descriptor.
@@ -254,242 +231,6 @@ nfp_net_rx_queue_count(void *rx_queue)
return count;
}
-/* Parse the chained metadata from packet */
-static bool
-nfp_net_parse_chained_meta(uint8_t *meta_base,
- rte_be32_t meta_header,
- struct nfp_meta_parsed *meta)
-{
- uint32_t meta_info;
- uint32_t vlan_info;
- uint8_t *meta_offset;
-
- meta_info = rte_be_to_cpu_32(meta_header);
- meta_offset = meta_base + 4;
-
- for (; meta_info != 0; meta_info >>= NFP_NET_META_FIELD_SIZE, meta_offset += 4) {
- switch (meta_info & NFP_NET_META_FIELD_MASK) {
- case NFP_NET_META_PORTID:
- meta->port_id = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
- break;
- case NFP_NET_META_HASH:
- /* Next field type is about the hash type */
- meta_info >>= NFP_NET_META_FIELD_SIZE;
- /* Hash value is in the data field */
- meta->hash = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
- meta->hash_type = meta_info & NFP_NET_META_FIELD_MASK;
- break;
- case NFP_NET_META_VLAN:
- vlan_info = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
- meta->vlan[meta->vlan_layer].offload =
- vlan_info >> NFP_NET_META_VLAN_OFFLOAD;
- meta->vlan[meta->vlan_layer].tci =
- vlan_info & NFP_NET_META_VLAN_MASK;
- meta->vlan[meta->vlan_layer].tpid = NFP_NET_META_TPID(vlan_info);
- meta->vlan_layer++;
- break;
- case NFP_NET_META_IPSEC:
- meta->sa_idx = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
- meta->ipsec_type = meta_info & NFP_NET_META_FIELD_MASK;
- break;
- case NFP_NET_META_MARK:
- meta->flags |= (1 << NFP_NET_META_MARK);
- meta->mark_id = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
- break;
- default:
- /* Unsupported metadata can be a performance issue */
- return false;
- }
- }
-
- return true;
-}
-
-/* Set mbuf hash data based on the metadata info */
-static void
-nfp_net_parse_meta_hash(const struct nfp_meta_parsed *meta,
- struct nfp_net_rxq *rxq,
- struct rte_mbuf *mbuf)
-{
- struct nfp_net_hw *hw = rxq->hw;
-
- if ((hw->super.ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0)
- return;
-
- mbuf->hash.rss = meta->hash;
- mbuf->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
-}
-
-/*
- * Parse the single metadata
- *
- * The RSS hash and hash-type are prepended to the packet data.
- * Get it from metadata area.
- */
-static inline void
-nfp_net_parse_single_meta(uint8_t *meta_base,
- rte_be32_t meta_header,
- struct nfp_meta_parsed *meta)
-{
- meta->hash_type = rte_be_to_cpu_32(meta_header);
- meta->hash = rte_be_to_cpu_32(*(rte_be32_t *)(meta_base + 4));
-}
-
-/* Set mbuf vlan_strip data based on metadata info */
-static void
-nfp_net_parse_meta_vlan(const struct nfp_meta_parsed *meta,
- struct nfp_net_rx_desc *rxd,
- struct nfp_net_rxq *rxq,
- struct rte_mbuf *mb)
-{
- uint32_t ctrl = rxq->hw->super.ctrl;
-
- /* Skip if hardware don't support setting vlan. */
- if ((ctrl & (NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_RXVLAN_V2)) == 0)
- return;
-
- /*
- * The firmware support two ways to send the VLAN info (with priority) :
- * 1. Using the metadata when NFP_NET_CFG_CTRL_RXVLAN_V2 is set,
- * 2. Using the descriptor when NFP_NET_CFG_CTRL_RXVLAN is set.
- */
- if ((ctrl & NFP_NET_CFG_CTRL_RXVLAN_V2) != 0) {
- if (meta->vlan_layer > 0 && meta->vlan[0].offload != 0) {
- mb->vlan_tci = rte_cpu_to_le_32(meta->vlan[0].tci);
- mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
- }
- } else if ((ctrl & NFP_NET_CFG_CTRL_RXVLAN) != 0) {
- if ((rxd->rxd.flags & PCIE_DESC_RX_VLAN) != 0) {
- mb->vlan_tci = rte_cpu_to_le_32(rxd->rxd.offload_info);
- mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
- }
- }
-}
-
-/*
- * 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_hw *hw = &rxq->hw->super;
-
- if ((hw->ctrl & 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 TCI is %u inner vlan TCI is %u",
- mb->vlan_tci_outer, mb->vlan_tci);
- mb->ol_flags |= RTE_MBUF_F_RX_QINQ | RTE_MBUF_F_RX_QINQ_STRIPPED;
-}
-
-/*
- * Set mbuf IPsec Offload features based on metadata info.
- *
- * The IPsec Offload features is prepended to the mbuf ol_flags.
- * Extract and decode metadata info and set the mbuf ol_flags.
- */
-static void
-nfp_net_parse_meta_ipsec(struct nfp_meta_parsed *meta,
- struct nfp_net_rxq *rxq,
- struct rte_mbuf *mbuf)
-{
- int offset;
- uint32_t sa_idx;
- struct nfp_net_hw *hw;
- struct nfp_tx_ipsec_desc_msg *desc_md;
-
- hw = rxq->hw;
- sa_idx = meta->sa_idx;
-
- if (meta->ipsec_type != NFP_NET_META_IPSEC)
- return;
-
- if (sa_idx >= NFP_NET_IPSEC_MAX_SA_CNT) {
- mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED;
- } else {
- mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD;
- offset = hw->ipsec_data->pkt_dynfield_offset;
- desc_md = RTE_MBUF_DYNFIELD(mbuf, offset, struct nfp_tx_ipsec_desc_msg *);
- desc_md->sa_idx = sa_idx;
- desc_md->enc = 0;
- }
-}
-
-static void
-nfp_net_parse_meta_mark(const struct nfp_meta_parsed *meta,
- struct rte_mbuf *mbuf)
-{
- if (((meta->flags >> NFP_NET_META_MARK) & 0x1) == 0)
- return;
-
- mbuf->hash.fdir.hi = meta->mark_id;
- mbuf->ol_flags |= RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID;
-}
-
-/* Parse the metadata from packet */
-static void
-nfp_net_parse_meta(struct nfp_net_rx_desc *rxds,
- struct nfp_net_rxq *rxq,
- struct nfp_net_hw *hw,
- struct rte_mbuf *mb,
- struct nfp_meta_parsed *meta)
-{
- uint8_t *meta_base;
- rte_be32_t meta_header;
-
- if (unlikely(NFP_DESC_META_LEN(rxds) == 0))
- return;
-
- meta_base = rte_pktmbuf_mtod_offset(mb, uint8_t *, -NFP_DESC_META_LEN(rxds));
- meta_header = *(rte_be32_t *)meta_base;
-
- switch (hw->meta_format) {
- case NFP_NET_METAFORMAT_CHAINED:
- if (nfp_net_parse_chained_meta(meta_base, meta_header, meta)) {
- nfp_net_parse_meta_hash(meta, rxq, mb);
- nfp_net_parse_meta_vlan(meta, rxds, rxq, mb);
- nfp_net_parse_meta_qinq(meta, rxq, mb);
- nfp_net_parse_meta_ipsec(meta, rxq, mb);
- nfp_net_parse_meta_mark(meta, mb);
- } else {
- PMD_RX_LOG(DEBUG, "RX chained metadata format is wrong!");
- }
- break;
- case NFP_NET_METAFORMAT_SINGLE:
- if ((rxds->rxd.flags & PCIE_DESC_RX_RSS) != 0) {
- nfp_net_parse_single_meta(meta_base, meta_header, meta);
- nfp_net_parse_meta_hash(meta, rxq, mb);
- }
- break;
- default:
- PMD_RX_LOG(DEBUG, "RX metadata do not exist.");
- }
-}
-
/**
* Set packet type to mbuf based on parsed structure.
*
@@ -1038,50 +779,6 @@ nfp_net_reset_tx_queue(struct nfp_net_txq *txq)
txq->rd_p = 0;
}
-void
-nfp_net_set_meta_vlan(struct nfp_net_meta_raw *meta_data,
- struct rte_mbuf *pkt,
- uint8_t layer)
-{
- uint16_t tpid;
- uint16_t vlan_tci;
-
- tpid = RTE_ETHER_TYPE_VLAN;
- vlan_tci = pkt->vlan_tci;
-
- meta_data->data[layer] = rte_cpu_to_be_32(tpid << 16 | vlan_tci);
-}
-
-void
-nfp_net_set_meta_ipsec(struct nfp_net_meta_raw *meta_data,
- struct nfp_net_txq *txq,
- struct rte_mbuf *pkt,
- uint8_t layer,
- uint8_t ipsec_layer)
-{
- int offset;
- struct nfp_net_hw *hw;
- struct nfp_tx_ipsec_desc_msg *desc_md;
-
- hw = txq->hw;
- offset = hw->ipsec_data->pkt_dynfield_offset;
- desc_md = RTE_MBUF_DYNFIELD(pkt, offset, struct nfp_tx_ipsec_desc_msg *);
-
- switch (ipsec_layer) {
- case NFP_IPSEC_META_SAIDX:
- meta_data->data[layer] = desc_md->sa_idx;
- break;
- case NFP_IPSEC_META_SEQLOW:
- meta_data->data[layer] = desc_md->esn.low;
- break;
- case NFP_IPSEC_META_SEQHI:
- meta_data->data[layer] = desc_md->esn.hi;
- break;
- default:
- break;
- }
-}
-
int
nfp_net_tx_queue_setup(struct rte_eth_dev *dev,
uint16_t queue_idx,
@@ -8,18 +8,6 @@
#include <ethdev_driver.h>
-#define NFP_DESC_META_LEN(d) ((d)->rxd.meta_len_dd & PCIE_DESC_RX_META_LEN_MASK)
-
-/* Maximum number of NFP packet metadata fields. */
-#define NFP_META_MAX_FIELDS 8
-
-/* Describe the raw metadata format. */
-struct nfp_net_meta_raw {
- uint32_t header; /**< Field type header (see format in nfp.rst) */
- uint32_t data[NFP_META_MAX_FIELDS]; /**< Array of each fields data member */
- uint8_t length; /**< Number of valid fields in @header */
-};
-
/* Descriptor alignment */
#define NFP_ALIGN_RING_DESC 128
@@ -238,13 +226,5 @@ int nfp_net_tx_queue_setup(struct rte_eth_dev *dev,
unsigned int socket_id,
const struct rte_eth_txconf *tx_conf);
uint32_t nfp_net_tx_free_bufs(struct nfp_net_txq *txq);
-void nfp_net_set_meta_vlan(struct nfp_net_meta_raw *meta_data,
- struct rte_mbuf *pkt,
- uint8_t layer);
-void nfp_net_set_meta_ipsec(struct nfp_net_meta_raw *meta_data,
- struct nfp_net_txq *txq,
- struct rte_mbuf *pkt,
- uint8_t layer,
- uint8_t ipsec_layer);
#endif /* __NFP_RXTX_H__ */