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