@@ -294,3 +294,19 @@ Metadata with L2 (1W/4B)
The vlan[0] is the innermost VLAN
The vlan[1] is the QinQ info
+
+TX
+~~
+
+NFP_NET_META_VLAN
+::
+
+ -----------------------------------------------------------------
+ 3 2 1 0
+ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | TPID | PCP |p| vlan outermost VID |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ^ ^
+ NOTE: | TCI |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -417,8 +417,10 @@ nfp_check_offloads(struct rte_eth_dev *dev)
hw->mtu = dev->data->mtu;
- if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
- ctrl |= NFP_NET_CFG_CTRL_TXVLAN;
+ if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) {
+ if (hw->cap & NFP_NET_CFG_CTRL_TXVLAN)
+ ctrl |= NFP_NET_CFG_CTRL_TXVLAN;
+ }
/* L2 broadcast */
if (hw->cap & NFP_NET_CFG_CTRL_L2BC)
@@ -29,6 +29,7 @@
/* 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
/* Working with metadata vlan api (NFD version >= 2.0) */
#define NFP_NET_META_VLAN_INFO 16
@@ -833,12 +833,77 @@ nfp_net_nfd3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
return 0;
}
+static void
+nfp_net_set_meta_vlan(struct nfp_net_meta_raw *meta_data,
+ struct rte_mbuf *pkt,
+ uint8_t layer)
+{
+ uint16_t vlan_tci;
+ uint16_t tpid;
+
+ tpid = RTE_ETHER_TYPE_VLAN;
+ vlan_tci = pkt->vlan_tci;
+
+ meta_data->data[layer] = rte_cpu_to_be_32(tpid << 16 | vlan_tci);
+}
+
+static void
+nfp_net_nfd3_set_meta_data(struct nfp_net_meta_raw *meta_data,
+ struct nfp_net_txq *txq,
+ struct rte_mbuf *pkt)
+{
+ uint8_t vlan_layer = 0;
+ struct nfp_net_hw *hw;
+ uint32_t meta_info;
+ uint8_t layer = 0;
+ char *meta;
+
+ hw = txq->hw;
+
+ if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) != 0 &&
+ (hw->ctrl & NFP_NET_CFG_CTRL_TXVLAN) != 0) {
+ if (meta_data->length == 0)
+ meta_data->length = NFP_NET_META_HEADER_SIZE;
+ meta_data->length += NFP_NET_META_FIELD_SIZE;
+ meta_data->header |= NFP_NET_META_VLAN;
+ }
+
+ if (meta_data->length == 0)
+ return;
+
+ meta_info = meta_data->header;
+ meta_data->header = rte_cpu_to_be_32(meta_data->header);
+ meta = rte_pktmbuf_prepend(pkt, meta_data->length);
+ memcpy(meta, &meta_data->header, sizeof(meta_data->header));
+ meta += NFP_NET_META_HEADER_SIZE;
+
+ for (; meta_info != 0; meta_info >>= NFP_NET_META_FIELD_SIZE, layer++,
+ meta += NFP_NET_META_FIELD_SIZE) {
+ switch (meta_info & NFP_NET_META_FIELD_MASK) {
+ case NFP_NET_META_VLAN:
+ if (vlan_layer > 0) {
+ PMD_DRV_LOG(ERR, "At most 1 layers of vlan is supported");
+ return;
+ }
+ nfp_net_set_meta_vlan(meta_data, pkt, layer);
+ vlan_layer++;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "The metadata type not supported");
+ return;
+ }
+
+ memcpy(meta, &meta_data->data[layer], sizeof(meta_data->data[layer]));
+ }
+}
+
uint16_t
nfp_net_nfd3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
{
struct nfp_net_txq *txq;
struct nfp_net_hw *hw;
struct nfp_net_nfd3_tx_desc *txds, txd;
+ struct nfp_net_meta_raw meta_data;
struct rte_mbuf *pkt;
uint64_t dma_addr;
int pkt_size, dma_size;
@@ -868,6 +933,7 @@ nfp_net_nfd3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pk
txq->qidx, nb_pkts);
/* Sending packets */
while ((i < nb_pkts) && free_descs) {
+ memset(&meta_data, 0, sizeof(meta_data));
/* Grabbing the mbuf linked to the current descriptor */
lmbuf = &txq->txbufs[txq->wr_p].mbuf;
/* Warming the cache for releasing the mbuf later on */
@@ -875,6 +941,8 @@ nfp_net_nfd3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pk
pkt = *(tx_pkts + i);
+ nfp_net_nfd3_set_meta_data(&meta_data, txq, pkt);
+
if (unlikely(pkt->nb_segs > 1 &&
!(hw->cap & NFP_NET_CFG_CTRL_GATHER))) {
PMD_INIT_LOG(INFO, "NFP_NET_CFG_CTRL_GATHER not set");
@@ -893,12 +961,6 @@ nfp_net_nfd3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pk
nfp_net_nfd3_tx_tso(txq, &txd, pkt);
nfp_net_nfd3_tx_cksum(txq, &txd, pkt);
- if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) &&
- (hw->cap & NFP_NET_CFG_CTRL_TXVLAN)) {
- txd.flags |= PCIE_DESC_TX_VLAN;
- txd.vlan = pkt->vlan_tci;
- }
-
/*
* mbuf data_len is the data in one segment and pkt_len data
* in the whole packet. When the packet is just one segment,
@@ -948,6 +1010,9 @@ nfp_net_nfd3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pk
else
txds->offset_eop = 0;
+ /* Set the meta_len */
+ txds->offset_eop |= meta_data.length;
+
pkt = pkt->next;
/* Referencing next free TX descriptor */
txds = &txq->txds[txq->wr_p];
@@ -27,6 +27,25 @@
/* Maximum number of supported VLANs in parsed form packet metadata. */
#define NFP_META_MAX_VLANS 2
+/* Maximum number of NFP packet metadata fields. */
+#define NFP_META_MAX_FIELDS 8
+
+/*
+ * struct nfp_net_meta_raw - Raw memory representation of packet metadata
+ *
+ * Describe the raw metadata format, useful when preparing metadata for a
+ * transmission mbuf.
+ *
+ * @header: NFD3 Contains the 8 4-bit type fields
+ * @data: Array of each fields data member
+ * @length: Keep track of number of valid fields in @header and data. Not part
+ * of the raw metadata.
+ */
+struct nfp_net_meta_raw {
+ uint32_t header;
+ uint32_t data[NFP_META_MAX_FIELDS];
+ uint8_t length;
+};
/*
* struct nfp_meta_parsed - Record metadata parsed from packet
@@ -121,7 +140,7 @@ struct nfp_net_nfd3_tx_desc {
uint8_t dma_addr_hi; /* High bits of host buf address */
__le16 dma_len; /* Length to DMA for this desc */
uint8_t offset_eop; /* Offset in buf where pkt starts +
- * highest bit is eop flag.
+ * highest bit is eop flag, low 7bit is meta_len.
*/
__le32 dma_addr_lo; /* Low 32bit of host buf addr */