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 : : uint16_t flags;
115 : 0 : uint32_t ctrl = rxq->hw->super.ctrl;
116 : :
117 : : /* Skip if hardware don't support setting vlan. */
118 [ # # ]: 0 : if ((ctrl & (NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_RXVLAN_V2)) == 0)
119 : : return;
120 : :
121 [ # # ]: 0 : if (((meta->flags >> NFP_NET_META_VLAN) & 0x1) == 0)
122 : : return;
123 : :
124 : : /*
125 : : * The firmware support two ways to send the VLAN info (with priority) :
126 : : * 1. Using the metadata when NFP_NET_CFG_CTRL_RXVLAN_V2 is set,
127 : : * 2. Using the descriptor when NFP_NET_CFG_CTRL_RXVLAN is set.
128 : : */
129 [ # # ]: 0 : if ((ctrl & NFP_NET_CFG_CTRL_RXVLAN_V2) != 0) {
130 [ # # # # ]: 0 : if (meta->vlan_layer > 0 && meta->vlan[0].offload != 0) {
131 : 0 : mb->vlan_tci = rte_cpu_to_le_32(meta->vlan[0].tci);
132 : 0 : mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
133 : : }
134 [ # # ]: 0 : } else if ((ctrl & NFP_NET_CFG_CTRL_RXVLAN) != 0) {
135 : 0 : flags = rte_le_to_cpu_16(rxd->rxd.flags);
136 [ # # ]: 0 : if ((flags & PCIE_DESC_RX_VLAN) != 0) {
137 : 0 : mb->vlan_tci = rte_cpu_to_le_32(rxd->rxd.offload_info);
138 : 0 : mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
139 : : }
140 : : }
141 : : }
142 : :
143 : : /*
144 : : * Set mbuf qinq_strip data based on metadata info
145 : : *
146 : : * The out VLAN tci are prepended to the packet data.
147 : : * Extract and decode it and set the mbuf fields.
148 : : *
149 : : * If both RTE_MBUF_F_RX_VLAN and NFP_NET_CFG_CTRL_RXQINQ are set, the 2 VLANs
150 : : * have been stripped by the hardware and their TCIs are saved in
151 : : * mbuf->vlan_tci (inner) and mbuf->vlan_tci_outer (outer).
152 : : * If NFP_NET_CFG_CTRL_RXQINQ is set and RTE_MBUF_F_RX_VLAN is unset, only the
153 : : * outer VLAN is removed from packet data, but both tci are saved in
154 : : * mbuf->vlan_tci (inner) and mbuf->vlan_tci_outer (outer).
155 : : *
156 : : * qinq set & vlan set : meta->vlan_layer>=2, meta->vlan[0].offload=1, meta->vlan[1].offload=1
157 : : * qinq set & vlan not set: meta->vlan_layer>=2, meta->vlan[1].offload=1,meta->vlan[0].offload=0
158 : : * qinq not set & vlan set: meta->vlan_layer=1, meta->vlan[0].offload=1
159 : : * qinq not set & vlan not set: meta->vlan_layer=0
160 : : */
161 : : static void
162 : 0 : nfp_net_meta_parse_qinq(const struct nfp_net_meta_parsed *meta,
163 : : struct nfp_net_rxq *rxq,
164 : : struct rte_mbuf *mb)
165 : : {
166 : 0 : struct nfp_hw *hw = &rxq->hw->super;
167 : :
168 [ # # ]: 0 : if ((hw->ctrl & NFP_NET_CFG_CTRL_RXQINQ) == 0 ||
169 [ # # ]: 0 : (hw->cap & NFP_NET_CFG_CTRL_RXQINQ) == 0)
170 : : return;
171 : :
172 [ # # ]: 0 : if (((meta->flags >> NFP_NET_META_VLAN) & 0x1) == 0)
173 : : return;
174 : :
175 [ # # ]: 0 : if (meta->vlan_layer < NFP_NET_META_MAX_VLANS)
176 : : return;
177 : :
178 [ # # ]: 0 : if (meta->vlan[0].offload == 0)
179 : 0 : mb->vlan_tci = rte_cpu_to_le_16(meta->vlan[0].tci);
180 : :
181 : 0 : mb->vlan_tci_outer = rte_cpu_to_le_16(meta->vlan[1].tci);
182 : : PMD_RX_LOG(DEBUG, "Received outer vlan TCI is %u inner vlan TCI is %u.",
183 : : mb->vlan_tci_outer, mb->vlan_tci);
184 : 0 : mb->ol_flags |= RTE_MBUF_F_RX_QINQ | RTE_MBUF_F_RX_QINQ_STRIPPED;
185 : : }
186 : :
187 : : /*
188 : : * Set mbuf IPsec Offload features based on metadata info.
189 : : *
190 : : * The IPsec Offload features is prepended to the mbuf ol_flags.
191 : : * Extract and decode metadata info and set the mbuf ol_flags.
192 : : */
193 : : static void
194 : : nfp_net_meta_parse_ipsec(struct nfp_net_meta_parsed *meta,
195 : : struct nfp_net_rxq *rxq,
196 : : struct rte_mbuf *mbuf)
197 : : {
198 : : int offset;
199 : : uint32_t sa_idx;
200 : : struct nfp_net_hw *hw;
201 : : struct nfp_tx_ipsec_desc_msg *desc_md;
202 : :
203 [ # # ]: 0 : if (((meta->flags >> NFP_NET_META_IPSEC) & 0x1) == 0)
204 : : return;
205 : :
206 : : hw = rxq->hw;
207 : 0 : sa_idx = meta->sa_idx;
208 : :
209 [ # # ]: 0 : if (sa_idx >= NFP_NET_IPSEC_MAX_SA_CNT) {
210 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED;
211 : : } else {
212 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD;
213 : 0 : offset = hw->ipsec_data->pkt_dynfield_offset;
214 : 0 : desc_md = RTE_MBUF_DYNFIELD(mbuf, offset, struct nfp_tx_ipsec_desc_msg *);
215 : 0 : desc_md->sa_idx = sa_idx;
216 : 0 : desc_md->enc = 0;
217 : : }
218 : : }
219 : :
220 : : static void
221 : : nfp_net_meta_parse_mark(const struct nfp_net_meta_parsed *meta,
222 : : struct rte_mbuf *mbuf)
223 : : {
224 [ # # ]: 0 : if (((meta->flags >> NFP_NET_META_MARK) & 0x1) == 0)
225 : : return;
226 : :
227 : 0 : mbuf->hash.fdir.hi = meta->mark_id;
228 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID;
229 : : }
230 : :
231 : : /* Parse the metadata from packet */
232 : : void
233 : 0 : nfp_net_meta_parse(struct nfp_net_rx_desc *rxds,
234 : : struct nfp_net_rxq *rxq,
235 : : struct nfp_net_hw *hw,
236 : : struct rte_mbuf *mb,
237 : : struct nfp_net_meta_parsed *meta)
238 : : {
239 : : uint16_t flags;
240 : : uint8_t *meta_base;
241 : : rte_be32_t meta_header;
242 : :
243 : 0 : meta->flags = 0;
244 : 0 : flags = rte_le_to_cpu_16(rxds->rxd.flags);
245 : :
246 [ # # ]: 0 : if (unlikely(NFP_DESC_META_LEN(rxds) == 0))
247 : : return;
248 : :
249 : 0 : meta_base = rte_pktmbuf_mtod_offset(mb, uint8_t *, -NFP_DESC_META_LEN(rxds));
250 : 0 : meta_header = *(rte_be32_t *)meta_base;
251 : :
252 [ # # # ]: 0 : switch (hw->meta_format) {
253 : 0 : case NFP_NET_METAFORMAT_CHAINED:
254 [ # # ]: 0 : if (nfp_net_meta_parse_chained(meta_base, meta_header, meta)) {
255 : : nfp_net_meta_parse_hash(meta, rxq, mb);
256 : 0 : nfp_net_meta_parse_vlan(meta, rxds, rxq, mb);
257 : 0 : nfp_net_meta_parse_qinq(meta, rxq, mb);
258 : : nfp_net_meta_parse_ipsec(meta, rxq, mb);
259 : : nfp_net_meta_parse_mark(meta, mb);
260 : : } else {
261 : : PMD_RX_LOG(DEBUG, "RX chained metadata format is wrong!");
262 : : }
263 : : break;
264 : 0 : case NFP_NET_METAFORMAT_SINGLE:
265 [ # # ]: 0 : if ((flags & PCIE_DESC_RX_RSS) != 0) {
266 : 0 : nfp_net_meta_parse_single(meta_base, meta_header, meta);
267 : : nfp_net_meta_parse_hash(meta, rxq, mb);
268 : : }
269 : : break;
270 : 0 : default:
271 : : PMD_RX_LOG(DEBUG, "RX metadata do not exist.");
272 : : }
273 : : }
274 : :
275 : : void
276 : 0 : nfp_net_meta_init_format(struct nfp_net_hw *hw,
277 : : struct nfp_pf_dev *pf_dev)
278 : : {
279 : : /*
280 : : * ABI 4.x and ctrl vNIC always use chained metadata, in other cases we allow use of
281 : : * single metadata if only RSS(v1) is supported by hw capability, and RSS(v2)
282 : : * also indicate that we are using chained metadata.
283 : : */
284 [ # # ]: 0 : if (pf_dev->ver.major == 4) {
285 : 0 : hw->meta_format = NFP_NET_METAFORMAT_CHAINED;
286 [ # # ]: 0 : } else if ((hw->super.cap & NFP_NET_CFG_CTRL_CHAIN_META) != 0) {
287 : 0 : hw->meta_format = NFP_NET_METAFORMAT_CHAINED;
288 : : /*
289 : : * RSS is incompatible with chained metadata. hw->super.cap just represents
290 : : * firmware's ability rather than the firmware's configuration. We decide
291 : : * to reduce the confusion to allow us can use hw->super.cap to identify RSS later.
292 : : */
293 : 0 : hw->super.cap &= ~NFP_NET_CFG_CTRL_RSS;
294 : : } else {
295 : 0 : hw->meta_format = NFP_NET_METAFORMAT_SINGLE;
296 : : }
297 : 0 : }
298 : :
299 : : void
300 : 0 : nfp_net_meta_set_vlan(struct nfp_net_meta_raw *meta_data,
301 : : struct rte_mbuf *pkt,
302 : : uint8_t layer)
303 : : {
304 : : uint16_t tpid;
305 : : uint16_t vlan_tci;
306 : :
307 : : tpid = RTE_ETHER_TYPE_VLAN;
308 : 0 : vlan_tci = pkt->vlan_tci;
309 : :
310 : 0 : meta_data->data[layer] = tpid << 16 | vlan_tci;
311 : 0 : }
312 : :
313 : : void
314 : 0 : nfp_net_meta_set_ipsec(struct nfp_net_meta_raw *meta_data,
315 : : struct nfp_net_txq *txq,
316 : : struct rte_mbuf *pkt,
317 : : uint8_t layer,
318 : : uint8_t ipsec_layer)
319 : : {
320 : : int offset;
321 : : struct nfp_net_hw *hw;
322 : : struct nfp_tx_ipsec_desc_msg *desc_md;
323 : :
324 : 0 : hw = txq->hw;
325 : 0 : offset = hw->ipsec_data->pkt_dynfield_offset;
326 : 0 : desc_md = RTE_MBUF_DYNFIELD(pkt, offset, struct nfp_tx_ipsec_desc_msg *);
327 : :
328 [ # # # # ]: 0 : switch (ipsec_layer) {
329 : 0 : case NFP_NET_META_IPSEC_SAIDX:
330 : 0 : meta_data->data[layer] = desc_md->sa_idx;
331 : 0 : break;
332 : 0 : case NFP_NET_META_IPSEC_SEQLOW:
333 : 0 : meta_data->data[layer] = desc_md->esn.low;
334 : 0 : break;
335 : 0 : case NFP_NET_META_IPSEC_SEQHI:
336 : 0 : meta_data->data[layer] = desc_md->esn.hi;
337 : 0 : break;
338 : : default:
339 : : break;
340 : : }
341 : 0 : }
|