1ddcd598fSLong Wu /* SPDX-License-Identifier: BSD-3-Clause 2ddcd598fSLong Wu * Copyright (c) 2023 Corigine, Inc. 3ddcd598fSLong Wu * All rights reserved. 4ddcd598fSLong Wu */ 5ddcd598fSLong Wu 6ddcd598fSLong Wu #include "nfp_net_meta.h" 7ddcd598fSLong Wu 8ddcd598fSLong Wu #include "nfp_net_common.h" 9ddcd598fSLong Wu #include "nfp_ipsec.h" 10ddcd598fSLong Wu #include "nfp_logs.h" 11ddcd598fSLong Wu 1279358e61SLong Wu enum nfp_net_meta_ipsec_layer { 1379358e61SLong Wu NFP_NET_META_IPSEC_SAIDX, /**< Order of SA index in metadata */ 1479358e61SLong Wu NFP_NET_META_IPSEC_SEQLOW, /**< Order of Sequence Number (low 32bits) in metadata */ 1579358e61SLong Wu NFP_NET_META_IPSEC_SEQHI, /**< Order of Sequence Number (high 32bits) in metadata */ 16ddcd598fSLong Wu }; 17ddcd598fSLong Wu 18ddcd598fSLong Wu /* Parse the chained metadata from packet */ 19ddcd598fSLong Wu static bool 200e131d77SLong Wu nfp_net_meta_parse_chained(uint8_t *meta_base, 21ddcd598fSLong Wu rte_be32_t meta_header, 2279358e61SLong Wu struct nfp_net_meta_parsed *meta) 23ddcd598fSLong Wu { 24ddcd598fSLong Wu uint32_t meta_info; 25ddcd598fSLong Wu uint32_t vlan_info; 26ddcd598fSLong Wu uint8_t *meta_offset; 27ddcd598fSLong Wu 28ddcd598fSLong Wu meta_info = rte_be_to_cpu_32(meta_header); 29ddcd598fSLong Wu meta_offset = meta_base + 4; 30ddcd598fSLong Wu 31ddcd598fSLong Wu for (; meta_info != 0; meta_info >>= NFP_NET_META_FIELD_SIZE, meta_offset += 4) { 32ddcd598fSLong Wu switch (meta_info & NFP_NET_META_FIELD_MASK) { 33ddcd598fSLong Wu case NFP_NET_META_PORTID: 345eed6ad5SLong Wu meta->flags |= (1 << NFP_NET_META_PORTID); 35ddcd598fSLong Wu meta->port_id = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset); 36ddcd598fSLong Wu break; 37ddcd598fSLong Wu case NFP_NET_META_HASH: 385eed6ad5SLong Wu meta->flags |= (1 << NFP_NET_META_HASH); 39ddcd598fSLong Wu /* Next field type is about the hash type */ 40ddcd598fSLong Wu meta_info >>= NFP_NET_META_FIELD_SIZE; 41ddcd598fSLong Wu /* Hash value is in the data field */ 42ddcd598fSLong Wu meta->hash = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset); 43ddcd598fSLong Wu meta->hash_type = meta_info & NFP_NET_META_FIELD_MASK; 44ddcd598fSLong Wu break; 45ddcd598fSLong Wu case NFP_NET_META_VLAN: 465eed6ad5SLong Wu meta->flags |= (1 << NFP_NET_META_VLAN); 47ddcd598fSLong Wu vlan_info = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset); 48ddcd598fSLong Wu meta->vlan[meta->vlan_layer].offload = 49ddcd598fSLong Wu vlan_info >> NFP_NET_META_VLAN_OFFLOAD; 50ddcd598fSLong Wu meta->vlan[meta->vlan_layer].tci = 51ddcd598fSLong Wu vlan_info & NFP_NET_META_VLAN_MASK; 52ddcd598fSLong Wu meta->vlan[meta->vlan_layer].tpid = NFP_NET_META_TPID(vlan_info); 53ddcd598fSLong Wu meta->vlan_layer++; 54ddcd598fSLong Wu break; 55ddcd598fSLong Wu case NFP_NET_META_IPSEC: 565eed6ad5SLong Wu meta->flags |= (1 << NFP_NET_META_IPSEC); 57ddcd598fSLong Wu meta->sa_idx = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset); 58ddcd598fSLong Wu break; 59ddcd598fSLong Wu case NFP_NET_META_MARK: 60ddcd598fSLong Wu meta->flags |= (1 << NFP_NET_META_MARK); 61ddcd598fSLong Wu meta->mark_id = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset); 62ddcd598fSLong Wu break; 63ddcd598fSLong Wu default: 64ddcd598fSLong Wu /* Unsupported metadata can be a performance issue */ 65ddcd598fSLong Wu return false; 66ddcd598fSLong Wu } 67ddcd598fSLong Wu } 68ddcd598fSLong Wu 69ddcd598fSLong Wu return true; 70ddcd598fSLong Wu } 71ddcd598fSLong Wu 72ddcd598fSLong Wu /* 73ddcd598fSLong Wu * Parse the single metadata 74ddcd598fSLong Wu * 75ddcd598fSLong Wu * The RSS hash and hash-type are prepended to the packet data. 76ddcd598fSLong Wu * Get it from metadata area. 77ddcd598fSLong Wu */ 78ddcd598fSLong Wu static inline void 790e131d77SLong Wu nfp_net_meta_parse_single(uint8_t *meta_base, 80ddcd598fSLong Wu rte_be32_t meta_header, 8179358e61SLong Wu struct nfp_net_meta_parsed *meta) 82ddcd598fSLong Wu { 83b6755530SLong Wu meta->flags = 0; 845eed6ad5SLong Wu meta->flags |= (1 << NFP_NET_META_HASH); 85ddcd598fSLong Wu meta->hash_type = rte_be_to_cpu_32(meta_header); 86ddcd598fSLong Wu meta->hash = rte_be_to_cpu_32(*(rte_be32_t *)(meta_base + 4)); 87ddcd598fSLong Wu } 88ddcd598fSLong Wu 89ddcd598fSLong Wu /* Set mbuf hash data based on the metadata info */ 90ddcd598fSLong Wu static void 910e131d77SLong Wu nfp_net_meta_parse_hash(const struct nfp_net_meta_parsed *meta, 92ddcd598fSLong Wu struct nfp_net_rxq *rxq, 93ddcd598fSLong Wu struct rte_mbuf *mbuf) 94ddcd598fSLong Wu { 95ddcd598fSLong Wu struct nfp_net_hw *hw = rxq->hw; 96ddcd598fSLong Wu 97ddcd598fSLong Wu if ((hw->super.ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) 98ddcd598fSLong Wu return; 99ddcd598fSLong Wu 1005eed6ad5SLong Wu if (((meta->flags >> NFP_NET_META_HASH) & 0x1) == 0) 1015eed6ad5SLong Wu return; 1025eed6ad5SLong Wu 103ddcd598fSLong Wu mbuf->hash.rss = meta->hash; 104ddcd598fSLong Wu mbuf->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; 105ddcd598fSLong Wu } 106ddcd598fSLong Wu 107ddcd598fSLong Wu /* Set mbuf vlan_strip data based on metadata info */ 108ddcd598fSLong Wu static void 1090e131d77SLong Wu nfp_net_meta_parse_vlan(const struct nfp_net_meta_parsed *meta, 110ddcd598fSLong Wu struct nfp_net_rx_desc *rxd, 111ddcd598fSLong Wu struct nfp_net_rxq *rxq, 112ddcd598fSLong Wu struct rte_mbuf *mb) 113ddcd598fSLong Wu { 114ddcd598fSLong Wu uint32_t ctrl = rxq->hw->super.ctrl; 115ddcd598fSLong Wu 116ddcd598fSLong Wu /* Skip if hardware don't support setting vlan. */ 117ddcd598fSLong Wu if ((ctrl & (NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_RXVLAN_V2)) == 0) 118ddcd598fSLong Wu return; 119ddcd598fSLong Wu 1205eed6ad5SLong Wu if (((meta->flags >> NFP_NET_META_VLAN) & 0x1) == 0) 1215eed6ad5SLong Wu return; 1225eed6ad5SLong Wu 123ddcd598fSLong Wu /* 124ddcd598fSLong Wu * The firmware support two ways to send the VLAN info (with priority) : 125ddcd598fSLong Wu * 1. Using the metadata when NFP_NET_CFG_CTRL_RXVLAN_V2 is set, 126ddcd598fSLong Wu * 2. Using the descriptor when NFP_NET_CFG_CTRL_RXVLAN is set. 127ddcd598fSLong Wu */ 128ddcd598fSLong Wu if ((ctrl & NFP_NET_CFG_CTRL_RXVLAN_V2) != 0) { 129ddcd598fSLong Wu if (meta->vlan_layer > 0 && meta->vlan[0].offload != 0) { 130ddcd598fSLong Wu mb->vlan_tci = rte_cpu_to_le_32(meta->vlan[0].tci); 131ddcd598fSLong Wu mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED; 132ddcd598fSLong Wu } 133ddcd598fSLong Wu } else if ((ctrl & NFP_NET_CFG_CTRL_RXVLAN) != 0) { 134ddcd598fSLong Wu if ((rxd->rxd.flags & PCIE_DESC_RX_VLAN) != 0) { 135ddcd598fSLong Wu mb->vlan_tci = rte_cpu_to_le_32(rxd->rxd.offload_info); 136ddcd598fSLong Wu mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED; 137ddcd598fSLong Wu } 138ddcd598fSLong Wu } 139ddcd598fSLong Wu } 140ddcd598fSLong Wu 141ddcd598fSLong Wu /* 142ddcd598fSLong Wu * Set mbuf qinq_strip data based on metadata info 143ddcd598fSLong Wu * 144ddcd598fSLong Wu * The out VLAN tci are prepended to the packet data. 145ddcd598fSLong Wu * Extract and decode it and set the mbuf fields. 146ddcd598fSLong Wu * 147ddcd598fSLong Wu * If both RTE_MBUF_F_RX_VLAN and NFP_NET_CFG_CTRL_RXQINQ are set, the 2 VLANs 148ddcd598fSLong Wu * have been stripped by the hardware and their TCIs are saved in 149ddcd598fSLong Wu * mbuf->vlan_tci (inner) and mbuf->vlan_tci_outer (outer). 150ddcd598fSLong Wu * If NFP_NET_CFG_CTRL_RXQINQ is set and RTE_MBUF_F_RX_VLAN is unset, only the 151ddcd598fSLong Wu * outer VLAN is removed from packet data, but both tci are saved in 152ddcd598fSLong Wu * mbuf->vlan_tci (inner) and mbuf->vlan_tci_outer (outer). 153ddcd598fSLong Wu * 154ddcd598fSLong Wu * qinq set & vlan set : meta->vlan_layer>=2, meta->vlan[0].offload=1, meta->vlan[1].offload=1 155ddcd598fSLong Wu * qinq set & vlan not set: meta->vlan_layer>=2, meta->vlan[1].offload=1,meta->vlan[0].offload=0 156ddcd598fSLong Wu * qinq not set & vlan set: meta->vlan_layer=1, meta->vlan[0].offload=1 157ddcd598fSLong Wu * qinq not set & vlan not set: meta->vlan_layer=0 158ddcd598fSLong Wu */ 159ddcd598fSLong Wu static void 1600e131d77SLong Wu nfp_net_meta_parse_qinq(const struct nfp_net_meta_parsed *meta, 161ddcd598fSLong Wu struct nfp_net_rxq *rxq, 162ddcd598fSLong Wu struct rte_mbuf *mb) 163ddcd598fSLong Wu { 164ddcd598fSLong Wu struct nfp_hw *hw = &rxq->hw->super; 165ddcd598fSLong Wu 166ddcd598fSLong Wu if ((hw->ctrl & NFP_NET_CFG_CTRL_RXQINQ) == 0 || 167ddcd598fSLong Wu (hw->cap & NFP_NET_CFG_CTRL_RXQINQ) == 0) 168ddcd598fSLong Wu return; 169ddcd598fSLong Wu 1705eed6ad5SLong Wu if (((meta->flags >> NFP_NET_META_VLAN) & 0x1) == 0) 1715eed6ad5SLong Wu return; 1725eed6ad5SLong Wu 17379358e61SLong Wu if (meta->vlan_layer < NFP_NET_META_MAX_VLANS) 174ddcd598fSLong Wu return; 175ddcd598fSLong Wu 176ddcd598fSLong Wu if (meta->vlan[0].offload == 0) 177ddcd598fSLong Wu mb->vlan_tci = rte_cpu_to_le_16(meta->vlan[0].tci); 178ddcd598fSLong Wu 179ddcd598fSLong Wu mb->vlan_tci_outer = rte_cpu_to_le_16(meta->vlan[1].tci); 180*b6de4353SZerun Fu PMD_RX_LOG(DEBUG, "Received outer vlan TCI is %u inner vlan TCI is %u.", 181ddcd598fSLong Wu mb->vlan_tci_outer, mb->vlan_tci); 182ddcd598fSLong Wu mb->ol_flags |= RTE_MBUF_F_RX_QINQ | RTE_MBUF_F_RX_QINQ_STRIPPED; 183ddcd598fSLong Wu } 184ddcd598fSLong Wu 185ddcd598fSLong Wu /* 186ddcd598fSLong Wu * Set mbuf IPsec Offload features based on metadata info. 187ddcd598fSLong Wu * 188ddcd598fSLong Wu * The IPsec Offload features is prepended to the mbuf ol_flags. 189ddcd598fSLong Wu * Extract and decode metadata info and set the mbuf ol_flags. 190ddcd598fSLong Wu */ 191ddcd598fSLong Wu static void 1920e131d77SLong Wu nfp_net_meta_parse_ipsec(struct nfp_net_meta_parsed *meta, 193ddcd598fSLong Wu struct nfp_net_rxq *rxq, 194ddcd598fSLong Wu struct rte_mbuf *mbuf) 195ddcd598fSLong Wu { 196ddcd598fSLong Wu int offset; 197ddcd598fSLong Wu uint32_t sa_idx; 198ddcd598fSLong Wu struct nfp_net_hw *hw; 199ddcd598fSLong Wu struct nfp_tx_ipsec_desc_msg *desc_md; 200ddcd598fSLong Wu 2015eed6ad5SLong Wu if (((meta->flags >> NFP_NET_META_IPSEC) & 0x1) == 0) 2025eed6ad5SLong Wu return; 2035eed6ad5SLong Wu 204ddcd598fSLong Wu hw = rxq->hw; 205ddcd598fSLong Wu sa_idx = meta->sa_idx; 206ddcd598fSLong Wu 207ddcd598fSLong Wu if (sa_idx >= NFP_NET_IPSEC_MAX_SA_CNT) { 208ddcd598fSLong Wu mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED; 209ddcd598fSLong Wu } else { 210ddcd598fSLong Wu mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD; 211ddcd598fSLong Wu offset = hw->ipsec_data->pkt_dynfield_offset; 212ddcd598fSLong Wu desc_md = RTE_MBUF_DYNFIELD(mbuf, offset, struct nfp_tx_ipsec_desc_msg *); 213ddcd598fSLong Wu desc_md->sa_idx = sa_idx; 214ddcd598fSLong Wu desc_md->enc = 0; 215ddcd598fSLong Wu } 216ddcd598fSLong Wu } 217ddcd598fSLong Wu 218ddcd598fSLong Wu static void 2190e131d77SLong Wu nfp_net_meta_parse_mark(const struct nfp_net_meta_parsed *meta, 220ddcd598fSLong Wu struct rte_mbuf *mbuf) 221ddcd598fSLong Wu { 222ddcd598fSLong Wu if (((meta->flags >> NFP_NET_META_MARK) & 0x1) == 0) 223ddcd598fSLong Wu return; 224ddcd598fSLong Wu 225ddcd598fSLong Wu mbuf->hash.fdir.hi = meta->mark_id; 226ddcd598fSLong Wu mbuf->ol_flags |= RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID; 227ddcd598fSLong Wu } 228ddcd598fSLong Wu 229ddcd598fSLong Wu /* Parse the metadata from packet */ 230ddcd598fSLong Wu void 2310e131d77SLong Wu nfp_net_meta_parse(struct nfp_net_rx_desc *rxds, 232ddcd598fSLong Wu struct nfp_net_rxq *rxq, 233ddcd598fSLong Wu struct nfp_net_hw *hw, 234ddcd598fSLong Wu struct rte_mbuf *mb, 23579358e61SLong Wu struct nfp_net_meta_parsed *meta) 236ddcd598fSLong Wu { 237ddcd598fSLong Wu uint8_t *meta_base; 238ddcd598fSLong Wu rte_be32_t meta_header; 239ddcd598fSLong Wu 2407223a7dfSLong Wu meta->flags = 0; 2417223a7dfSLong Wu 242ddcd598fSLong Wu if (unlikely(NFP_DESC_META_LEN(rxds) == 0)) 243ddcd598fSLong Wu return; 244ddcd598fSLong Wu 245ddcd598fSLong Wu meta_base = rte_pktmbuf_mtod_offset(mb, uint8_t *, -NFP_DESC_META_LEN(rxds)); 246ddcd598fSLong Wu meta_header = *(rte_be32_t *)meta_base; 247ddcd598fSLong Wu 248ddcd598fSLong Wu switch (hw->meta_format) { 249ddcd598fSLong Wu case NFP_NET_METAFORMAT_CHAINED: 2500e131d77SLong Wu if (nfp_net_meta_parse_chained(meta_base, meta_header, meta)) { 2510e131d77SLong Wu nfp_net_meta_parse_hash(meta, rxq, mb); 2520e131d77SLong Wu nfp_net_meta_parse_vlan(meta, rxds, rxq, mb); 2530e131d77SLong Wu nfp_net_meta_parse_qinq(meta, rxq, mb); 2540e131d77SLong Wu nfp_net_meta_parse_ipsec(meta, rxq, mb); 2550e131d77SLong Wu nfp_net_meta_parse_mark(meta, mb); 256ddcd598fSLong Wu } else { 257ddcd598fSLong Wu PMD_RX_LOG(DEBUG, "RX chained metadata format is wrong!"); 258ddcd598fSLong Wu } 259ddcd598fSLong Wu break; 260ddcd598fSLong Wu case NFP_NET_METAFORMAT_SINGLE: 261ddcd598fSLong Wu if ((rxds->rxd.flags & PCIE_DESC_RX_RSS) != 0) { 2620e131d77SLong Wu nfp_net_meta_parse_single(meta_base, meta_header, meta); 2630e131d77SLong Wu nfp_net_meta_parse_hash(meta, rxq, mb); 264ddcd598fSLong Wu } 265ddcd598fSLong Wu break; 266ddcd598fSLong Wu default: 267ddcd598fSLong Wu PMD_RX_LOG(DEBUG, "RX metadata do not exist."); 268ddcd598fSLong Wu } 269ddcd598fSLong Wu } 270ddcd598fSLong Wu 271ddcd598fSLong Wu void 272000feb4cSChaoyong He nfp_net_meta_init_format(struct nfp_net_hw *hw, 273000feb4cSChaoyong He struct nfp_pf_dev *pf_dev) 274ddcd598fSLong Wu { 275ddcd598fSLong Wu /* 276ddcd598fSLong Wu * ABI 4.x and ctrl vNIC always use chained metadata, in other cases we allow use of 277ddcd598fSLong Wu * single metadata if only RSS(v1) is supported by hw capability, and RSS(v2) 278ddcd598fSLong Wu * also indicate that we are using chained metadata. 279ddcd598fSLong Wu */ 280000feb4cSChaoyong He if (pf_dev->ver.major == 4) { 281ddcd598fSLong Wu hw->meta_format = NFP_NET_METAFORMAT_CHAINED; 282ddcd598fSLong Wu } else if ((hw->super.cap & NFP_NET_CFG_CTRL_CHAIN_META) != 0) { 283ddcd598fSLong Wu hw->meta_format = NFP_NET_METAFORMAT_CHAINED; 284ddcd598fSLong Wu /* 285ddcd598fSLong Wu * RSS is incompatible with chained metadata. hw->super.cap just represents 286ddcd598fSLong Wu * firmware's ability rather than the firmware's configuration. We decide 287ddcd598fSLong Wu * to reduce the confusion to allow us can use hw->super.cap to identify RSS later. 288ddcd598fSLong Wu */ 289ddcd598fSLong Wu hw->super.cap &= ~NFP_NET_CFG_CTRL_RSS; 290ddcd598fSLong Wu } else { 291ddcd598fSLong Wu hw->meta_format = NFP_NET_METAFORMAT_SINGLE; 292ddcd598fSLong Wu } 293ddcd598fSLong Wu } 294ddcd598fSLong Wu 295ddcd598fSLong Wu void 2960e131d77SLong Wu nfp_net_meta_set_vlan(struct nfp_net_meta_raw *meta_data, 297ddcd598fSLong Wu struct rte_mbuf *pkt, 298ddcd598fSLong Wu uint8_t layer) 299ddcd598fSLong Wu { 300ddcd598fSLong Wu uint16_t tpid; 301ddcd598fSLong Wu uint16_t vlan_tci; 302ddcd598fSLong Wu 303ddcd598fSLong Wu tpid = RTE_ETHER_TYPE_VLAN; 304ddcd598fSLong Wu vlan_tci = pkt->vlan_tci; 305ddcd598fSLong Wu 306b5894ec0SLong Wu meta_data->data[layer] = tpid << 16 | vlan_tci; 307ddcd598fSLong Wu } 308ddcd598fSLong Wu 309ddcd598fSLong Wu void 3100e131d77SLong Wu nfp_net_meta_set_ipsec(struct nfp_net_meta_raw *meta_data, 311ddcd598fSLong Wu struct nfp_net_txq *txq, 312ddcd598fSLong Wu struct rte_mbuf *pkt, 313ddcd598fSLong Wu uint8_t layer, 314ddcd598fSLong Wu uint8_t ipsec_layer) 315ddcd598fSLong Wu { 316ddcd598fSLong Wu int offset; 317ddcd598fSLong Wu struct nfp_net_hw *hw; 318ddcd598fSLong Wu struct nfp_tx_ipsec_desc_msg *desc_md; 319ddcd598fSLong Wu 320ddcd598fSLong Wu hw = txq->hw; 321ddcd598fSLong Wu offset = hw->ipsec_data->pkt_dynfield_offset; 322ddcd598fSLong Wu desc_md = RTE_MBUF_DYNFIELD(pkt, offset, struct nfp_tx_ipsec_desc_msg *); 323ddcd598fSLong Wu 324ddcd598fSLong Wu switch (ipsec_layer) { 32579358e61SLong Wu case NFP_NET_META_IPSEC_SAIDX: 326ddcd598fSLong Wu meta_data->data[layer] = desc_md->sa_idx; 327ddcd598fSLong Wu break; 32879358e61SLong Wu case NFP_NET_META_IPSEC_SEQLOW: 329ddcd598fSLong Wu meta_data->data[layer] = desc_md->esn.low; 330ddcd598fSLong Wu break; 33179358e61SLong Wu case NFP_NET_META_IPSEC_SEQHI: 332ddcd598fSLong Wu meta_data->data[layer] = desc_md->esn.hi; 333ddcd598fSLong Wu break; 334ddcd598fSLong Wu default: 335ddcd598fSLong Wu break; 336ddcd598fSLong Wu } 337ddcd598fSLong Wu } 338