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 : 0 : meta->flags = 0;
31 : :
32 [ # # ]: 0 : for (; meta_info != 0; meta_info >>= NFP_NET_META_FIELD_SIZE, meta_offset += 4) {
33 [ # # # # : 0 : switch (meta_info & NFP_NET_META_FIELD_MASK) {
# # ]
34 : 0 : case NFP_NET_META_PORTID:
35 : 0 : meta->flags |= (1 << NFP_NET_META_PORTID);
36 [ # # ]: 0 : meta->port_id = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
37 : 0 : break;
38 : 0 : case NFP_NET_META_HASH:
39 : 0 : meta->flags |= (1 << NFP_NET_META_HASH);
40 : : /* Next field type is about the hash type */
41 : 0 : meta_info >>= NFP_NET_META_FIELD_SIZE;
42 : : /* Hash value is in the data field */
43 [ # # ]: 0 : meta->hash = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
44 : 0 : meta->hash_type = meta_info & NFP_NET_META_FIELD_MASK;
45 : 0 : break;
46 : 0 : case NFP_NET_META_VLAN:
47 : 0 : meta->flags |= (1 << NFP_NET_META_VLAN);
48 [ # # ]: 0 : vlan_info = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
49 : 0 : meta->vlan[meta->vlan_layer].offload =
50 : 0 : vlan_info >> NFP_NET_META_VLAN_OFFLOAD;
51 : 0 : meta->vlan[meta->vlan_layer].tci =
52 : : vlan_info & NFP_NET_META_VLAN_MASK;
53 : 0 : meta->vlan[meta->vlan_layer].tpid = NFP_NET_META_TPID(vlan_info);
54 : 0 : meta->vlan_layer++;
55 : 0 : break;
56 : 0 : case NFP_NET_META_IPSEC:
57 : 0 : meta->flags |= (1 << NFP_NET_META_IPSEC);
58 [ # # ]: 0 : meta->sa_idx = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
59 : 0 : break;
60 : 0 : case NFP_NET_META_MARK:
61 : 0 : meta->flags |= (1 << NFP_NET_META_MARK);
62 [ # # ]: 0 : meta->mark_id = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
63 : 0 : break;
64 : : default:
65 : : /* Unsupported metadata can be a performance issue */
66 : : return false;
67 : : }
68 : : }
69 : :
70 : : return true;
71 : : }
72 : :
73 : : /*
74 : : * Parse the single metadata
75 : : *
76 : : * The RSS hash and hash-type are prepended to the packet data.
77 : : * Get it from metadata area.
78 : : */
79 : : static inline void
80 : 0 : nfp_net_meta_parse_single(uint8_t *meta_base,
81 : : rte_be32_t meta_header,
82 : : struct nfp_net_meta_parsed *meta)
83 : : {
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 : if (unlikely(NFP_DESC_META_LEN(rxds) == 0))
241 : : return;
242 : :
243 : 0 : meta_base = rte_pktmbuf_mtod_offset(mb, uint8_t *, -NFP_DESC_META_LEN(rxds));
244 : 0 : meta_header = *(rte_be32_t *)meta_base;
245 : :
246 [ # # # ]: 0 : switch (hw->meta_format) {
247 : 0 : case NFP_NET_METAFORMAT_CHAINED:
248 [ # # ]: 0 : if (nfp_net_meta_parse_chained(meta_base, meta_header, meta)) {
249 : : nfp_net_meta_parse_hash(meta, rxq, mb);
250 : 0 : nfp_net_meta_parse_vlan(meta, rxds, rxq, mb);
251 : 0 : nfp_net_meta_parse_qinq(meta, rxq, mb);
252 : : nfp_net_meta_parse_ipsec(meta, rxq, mb);
253 : : nfp_net_meta_parse_mark(meta, mb);
254 : : } else {
255 : : PMD_RX_LOG(DEBUG, "RX chained metadata format is wrong!");
256 : : }
257 : : break;
258 : 0 : case NFP_NET_METAFORMAT_SINGLE:
259 [ # # ]: 0 : if ((rxds->rxd.flags & PCIE_DESC_RX_RSS) != 0) {
260 : 0 : nfp_net_meta_parse_single(meta_base, meta_header, meta);
261 : : nfp_net_meta_parse_hash(meta, rxq, mb);
262 : : }
263 : : break;
264 : 0 : default:
265 : : PMD_RX_LOG(DEBUG, "RX metadata do not exist.");
266 : : }
267 : : }
268 : :
269 : : void
270 : 0 : nfp_net_meta_init_format(struct nfp_net_hw *hw)
271 : : {
272 : : /*
273 : : * ABI 4.x and ctrl vNIC always use chained metadata, in other cases we allow use of
274 : : * single metadata if only RSS(v1) is supported by hw capability, and RSS(v2)
275 : : * also indicate that we are using chained metadata.
276 : : */
277 [ # # ]: 0 : if (hw->ver.major == 4) {
278 : 0 : hw->meta_format = NFP_NET_METAFORMAT_CHAINED;
279 [ # # ]: 0 : } else if ((hw->super.cap & NFP_NET_CFG_CTRL_CHAIN_META) != 0) {
280 : 0 : hw->meta_format = NFP_NET_METAFORMAT_CHAINED;
281 : : /*
282 : : * RSS is incompatible with chained metadata. hw->super.cap just represents
283 : : * firmware's ability rather than the firmware's configuration. We decide
284 : : * to reduce the confusion to allow us can use hw->super.cap to identify RSS later.
285 : : */
286 : 0 : hw->super.cap &= ~NFP_NET_CFG_CTRL_RSS;
287 : : } else {
288 : 0 : hw->meta_format = NFP_NET_METAFORMAT_SINGLE;
289 : : }
290 : 0 : }
291 : :
292 : : void
293 : 0 : nfp_net_meta_set_vlan(struct nfp_net_meta_raw *meta_data,
294 : : struct rte_mbuf *pkt,
295 : : uint8_t layer)
296 : : {
297 : : uint16_t tpid;
298 : : uint16_t vlan_tci;
299 : :
300 : : tpid = RTE_ETHER_TYPE_VLAN;
301 : 0 : vlan_tci = pkt->vlan_tci;
302 : :
303 : 0 : meta_data->data[layer] = tpid << 16 | vlan_tci;
304 : 0 : }
305 : :
306 : : void
307 : 0 : nfp_net_meta_set_ipsec(struct nfp_net_meta_raw *meta_data,
308 : : struct nfp_net_txq *txq,
309 : : struct rte_mbuf *pkt,
310 : : uint8_t layer,
311 : : uint8_t ipsec_layer)
312 : : {
313 : : int offset;
314 : : struct nfp_net_hw *hw;
315 : : struct nfp_tx_ipsec_desc_msg *desc_md;
316 : :
317 : 0 : hw = txq->hw;
318 : 0 : offset = hw->ipsec_data->pkt_dynfield_offset;
319 : 0 : desc_md = RTE_MBUF_DYNFIELD(pkt, offset, struct nfp_tx_ipsec_desc_msg *);
320 : :
321 [ # # # # ]: 0 : switch (ipsec_layer) {
322 : 0 : case NFP_NET_META_IPSEC_SAIDX:
323 : 0 : meta_data->data[layer] = desc_md->sa_idx;
324 : 0 : break;
325 : 0 : case NFP_NET_META_IPSEC_SEQLOW:
326 : 0 : meta_data->data[layer] = desc_md->esn.low;
327 : 0 : break;
328 : 0 : case NFP_NET_META_IPSEC_SEQHI:
329 : 0 : meta_data->data[layer] = desc_md->esn.hi;
330 : 0 : break;
331 : : default:
332 : : break;
333 : : }
334 : 0 : }
|