From: Peng Zhang <peng.zh...@corigine.com> As the firmware with NFD3 change, using the metadata sends the VLAN info to the nic to achieve the VLAN offload insert.
The VLAN INFO consists of 16bit TPID + 16bit TCI 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/nfp.rst | 16 ++++++++ drivers/net/nfp/nfp_common.c | 6 ++- drivers/net/nfp/nfp_ctrl.h | 1 + drivers/net/nfp/nfp_rxtx.c | 77 +++++++++++++++++++++++++++++++++--- drivers/net/nfp/nfp_rxtx.h | 21 +++++++++- 5 files changed, 112 insertions(+), 9 deletions(-) diff --git a/doc/guides/nics/nfp.rst b/doc/guides/nics/nfp.rst index 2be15b63d3..a636fd0fde 100644 --- a/doc/guides/nics/nfp.rst +++ b/doc/guides/nics/nfp.rst @@ -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 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ diff --git a/drivers/net/nfp/nfp_common.c b/drivers/net/nfp/nfp_common.c index a62a7386ab..9c740ee9b5 100644 --- a/drivers/net/nfp/nfp_common.c +++ b/drivers/net/nfp/nfp_common.c @@ -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) diff --git a/drivers/net/nfp/nfp_ctrl.h b/drivers/net/nfp/nfp_ctrl.h index c7ebcf43b3..bffdd8345e 100644 --- a/drivers/net/nfp/nfp_ctrl.h +++ b/drivers/net/nfp/nfp_ctrl.h @@ -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 diff --git a/drivers/net/nfp/nfp_rxtx.c b/drivers/net/nfp/nfp_rxtx.c index 2bc0eb2625..200886111e 100644 --- a/drivers/net/nfp/nfp_rxtx.c +++ b/drivers/net/nfp/nfp_rxtx.c @@ -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]; diff --git a/drivers/net/nfp/nfp_rxtx.h b/drivers/net/nfp/nfp_rxtx.h index e3e8b00b48..d16d557fd3 100644 --- a/drivers/net/nfp/nfp_rxtx.h +++ b/drivers/net/nfp/nfp_rxtx.h @@ -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 */ -- 2.29.3