Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include <rte_cryptodev.h>
6 : : #include <rte_eventdev.h>
7 : : #include <rte_security.h>
8 : : #include <rte_security_driver.h>
9 : : #include <rte_pmd_cnxk.h>
10 : :
11 : : #include <cn10k_ethdev.h>
12 : : #include <cn10k_rx.h>
13 : : #include <cnxk_ethdev_mcs.h>
14 : : #include <cnxk_security.h>
15 : : #include <roc_priv.h>
16 : :
17 : : static struct rte_cryptodev_capabilities cn10k_eth_sec_crypto_caps[] = {
18 : : { /* AES GCM */
19 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
20 : : {.sym = {
21 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD,
22 : : {.aead = {
23 : : .algo = RTE_CRYPTO_AEAD_AES_GCM,
24 : : .block_size = 16,
25 : : .key_size = {
26 : : .min = 16,
27 : : .max = 32,
28 : : .increment = 8
29 : : },
30 : : .digest_size = {
31 : : .min = 16,
32 : : .max = 16,
33 : : .increment = 0
34 : : },
35 : : .aad_size = {
36 : : .min = 8,
37 : : .max = 12,
38 : : .increment = 4
39 : : },
40 : : .iv_size = {
41 : : .min = 12,
42 : : .max = 12,
43 : : .increment = 0
44 : : }
45 : : }, }
46 : : }, }
47 : : },
48 : : { /* AES CBC */
49 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
50 : : {.sym = {
51 : : .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
52 : : {.cipher = {
53 : : .algo = RTE_CRYPTO_CIPHER_AES_CBC,
54 : : .block_size = 16,
55 : : .key_size = {
56 : : .min = 16,
57 : : .max = 32,
58 : : .increment = 8
59 : : },
60 : : .iv_size = {
61 : : .min = 16,
62 : : .max = 16,
63 : : .increment = 0
64 : : }
65 : : }, }
66 : : }, }
67 : : },
68 : : { /* AES CTR */
69 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
70 : : {.sym = {
71 : : .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
72 : : {.cipher = {
73 : : .algo = RTE_CRYPTO_CIPHER_AES_CTR,
74 : : .block_size = 16,
75 : : .key_size = {
76 : : .min = 16,
77 : : .max = 32,
78 : : .increment = 8
79 : : },
80 : : .iv_size = {
81 : : .min = 12,
82 : : .max = 16,
83 : : .increment = 4
84 : : }
85 : : }, }
86 : : }, }
87 : : },
88 : : { /* 3DES CBC */
89 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
90 : : {.sym = {
91 : : .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
92 : : {.cipher = {
93 : : .algo = RTE_CRYPTO_CIPHER_3DES_CBC,
94 : : .block_size = 8,
95 : : .key_size = {
96 : : .min = 24,
97 : : .max = 24,
98 : : .increment = 0
99 : : },
100 : : .iv_size = {
101 : : .min = 8,
102 : : .max = 16,
103 : : .increment = 8
104 : : }
105 : : }, }
106 : : }, }
107 : : },
108 : : { /* AES-XCBC */
109 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
110 : : { .sym = {
111 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
112 : : {.auth = {
113 : : .algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
114 : : .block_size = 16,
115 : : .key_size = {
116 : : .min = 16,
117 : : .max = 16,
118 : : .increment = 0
119 : : },
120 : : .digest_size = {
121 : : .min = 12,
122 : : .max = 12,
123 : : .increment = 0,
124 : : },
125 : : }, }
126 : : }, }
127 : : },
128 : : { /* SHA1 HMAC */
129 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
130 : : {.sym = {
131 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
132 : : {.auth = {
133 : : .algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
134 : : .block_size = 64,
135 : : .key_size = {
136 : : .min = 20,
137 : : .max = 64,
138 : : .increment = 1
139 : : },
140 : : .digest_size = {
141 : : .min = 12,
142 : : .max = 12,
143 : : .increment = 0
144 : : },
145 : : }, }
146 : : }, }
147 : : },
148 : : { /* SHA256 HMAC */
149 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
150 : : {.sym = {
151 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
152 : : {.auth = {
153 : : .algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
154 : : .block_size = 64,
155 : : .key_size = {
156 : : .min = 1,
157 : : .max = 1024,
158 : : .increment = 1
159 : : },
160 : : .digest_size = {
161 : : .min = 16,
162 : : .max = 32,
163 : : .increment = 16
164 : : },
165 : : }, }
166 : : }, }
167 : : },
168 : : { /* SHA384 HMAC */
169 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
170 : : {.sym = {
171 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
172 : : {.auth = {
173 : : .algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
174 : : .block_size = 64,
175 : : .key_size = {
176 : : .min = 1,
177 : : .max = 1024,
178 : : .increment = 1
179 : : },
180 : : .digest_size = {
181 : : .min = 24,
182 : : .max = 48,
183 : : .increment = 24
184 : : },
185 : : }, }
186 : : }, }
187 : : },
188 : : { /* SHA512 HMAC */
189 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
190 : : {.sym = {
191 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
192 : : {.auth = {
193 : : .algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
194 : : .block_size = 128,
195 : : .key_size = {
196 : : .min = 1,
197 : : .max = 1024,
198 : : .increment = 1
199 : : },
200 : : .digest_size = {
201 : : .min = 32,
202 : : .max = 64,
203 : : .increment = 32
204 : : },
205 : : }, }
206 : : }, }
207 : : },
208 : : { /* AES GMAC (AUTH) */
209 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
210 : : {.sym = {
211 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
212 : : {.auth = {
213 : : .algo = RTE_CRYPTO_AUTH_AES_GMAC,
214 : : .block_size = 16,
215 : : .key_size = {
216 : : .min = 16,
217 : : .max = 32,
218 : : .increment = 8
219 : : },
220 : : .digest_size = {
221 : : .min = 8,
222 : : .max = 16,
223 : : .increment = 4
224 : : },
225 : : .iv_size = {
226 : : .min = 12,
227 : : .max = 12,
228 : : .increment = 0
229 : : }
230 : : }, }
231 : : }, }
232 : : },
233 : : { /* AES CCM */
234 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
235 : : {.sym = {
236 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD,
237 : : {.aead = {
238 : : .algo = RTE_CRYPTO_AEAD_AES_CCM,
239 : : .block_size = 16,
240 : : .key_size = {
241 : : .min = 16,
242 : : .max = 32,
243 : : .increment = 8
244 : : },
245 : : .digest_size = {
246 : : .min = 16,
247 : : .max = 16,
248 : : .increment = 0
249 : : },
250 : : .aad_size = {
251 : : .min = 8,
252 : : .max = 12,
253 : : .increment = 4
254 : : },
255 : : .iv_size = {
256 : : .min = 11,
257 : : .max = 13,
258 : : .increment = 1
259 : : }
260 : : }, }
261 : : }, }
262 : : },
263 : : { /* NULL (AUTH) */
264 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
265 : : {.sym = {
266 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
267 : : {.auth = {
268 : : .algo = RTE_CRYPTO_AUTH_NULL,
269 : : .block_size = 1,
270 : : .key_size = {
271 : : .min = 0,
272 : : .max = 0,
273 : : .increment = 0
274 : : },
275 : : .digest_size = {
276 : : .min = 0,
277 : : .max = 0,
278 : : .increment = 0
279 : : },
280 : : }, },
281 : : }, },
282 : : },
283 : : { /* NULL (CIPHER) */
284 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
285 : : {.sym = {
286 : : .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
287 : : {.cipher = {
288 : : .algo = RTE_CRYPTO_CIPHER_NULL,
289 : : .block_size = 1,
290 : : .key_size = {
291 : : .min = 0,
292 : : .max = 0,
293 : : .increment = 0
294 : : },
295 : : .iv_size = {
296 : : .min = 0,
297 : : .max = 0,
298 : : .increment = 0
299 : : }
300 : : }, },
301 : : }, }
302 : : },
303 : :
304 : : RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
305 : : };
306 : :
307 : : static const struct rte_security_capability cn10k_eth_sec_ipsec_capabilities[] = {
308 : : { /* IPsec Inline Protocol ESP Tunnel Ingress */
309 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
310 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
311 : : .ipsec = {
312 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
313 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
314 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
315 : : .replay_win_sz_max = ROC_AR_WIN_SIZE_MAX,
316 : : .options = {
317 : : .udp_encap = 1,
318 : : .udp_ports_verify = 1,
319 : : .copy_df = 1,
320 : : .copy_dscp = 1,
321 : : .copy_flabel = 1,
322 : : .tunnel_hdr_verify = RTE_SECURITY_IPSEC_TUNNEL_VERIFY_SRC_DST_ADDR,
323 : : .dec_ttl = 1,
324 : : .ip_csum_enable = 1,
325 : : .l4_csum_enable = 1,
326 : : .stats = 1,
327 : : .esn = 1,
328 : : .ingress_oop = 1,
329 : : },
330 : : },
331 : : .crypto_capabilities = cn10k_eth_sec_crypto_caps,
332 : : .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
333 : : },
334 : : { /* IPsec Inline Protocol ESP Tunnel Egress */
335 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
336 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
337 : : .ipsec = {
338 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
339 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
340 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
341 : : .replay_win_sz_max = ROC_AR_WIN_SIZE_MAX,
342 : : .options = {
343 : : .iv_gen_disable = 1,
344 : : .udp_encap = 1,
345 : : .udp_ports_verify = 1,
346 : : .copy_df = 1,
347 : : .copy_dscp = 1,
348 : : .copy_flabel = 1,
349 : : .dec_ttl = 1,
350 : : .ip_csum_enable = 1,
351 : : .l4_csum_enable = 1,
352 : : .stats = 1,
353 : : .esn = 1,
354 : : },
355 : : },
356 : : .crypto_capabilities = cn10k_eth_sec_crypto_caps,
357 : : .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
358 : : },
359 : : { /* IPsec Inline Protocol ESP Transport Egress */
360 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
361 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
362 : : .ipsec = {
363 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
364 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
365 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
366 : : .replay_win_sz_max = ROC_AR_WIN_SIZE_MAX,
367 : : .options = {
368 : : .iv_gen_disable = 1,
369 : : .udp_encap = 1,
370 : : .udp_ports_verify = 1,
371 : : .copy_df = 1,
372 : : .copy_dscp = 1,
373 : : .dec_ttl = 1,
374 : : .ip_csum_enable = 1,
375 : : .l4_csum_enable = 1,
376 : : .stats = 1,
377 : : .esn = 1,
378 : : .ingress_oop = 1,
379 : : },
380 : : },
381 : : .crypto_capabilities = cn10k_eth_sec_crypto_caps,
382 : : .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
383 : : },
384 : : { /* IPsec Inline Protocol ESP Transport Ingress */
385 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
386 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
387 : : .ipsec = {
388 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
389 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
390 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
391 : : .replay_win_sz_max = ROC_AR_WIN_SIZE_MAX,
392 : : .options = {
393 : : .udp_encap = 1,
394 : : .udp_ports_verify = 1,
395 : : .copy_df = 1,
396 : : .copy_dscp = 1,
397 : : .dec_ttl = 1,
398 : : .ip_csum_enable = 1,
399 : : .l4_csum_enable = 1,
400 : : .stats = 1,
401 : : .esn = 1,
402 : : .ingress_oop = 1,
403 : : },
404 : : },
405 : : .crypto_capabilities = cn10k_eth_sec_crypto_caps,
406 : : .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
407 : : },
408 : : };
409 : :
410 : : static const struct rte_security_capability cn10k_eth_sec_macsec_capabilities[] = {
411 : : { /* MACsec Inline Protocol, AES-GCM-128 algo */
412 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
413 : : .protocol = RTE_SECURITY_PROTOCOL_MACSEC,
414 : : .macsec = {
415 : : .mtu = ROC_MCS_MAX_MTU,
416 : : .alg = RTE_SECURITY_MACSEC_ALG_GCM_128,
417 : : .max_nb_sc = 128,
418 : : .max_nb_sa = 256,
419 : : .max_nb_sess = 256,
420 : : .replay_win_sz = ROC_MCS_MAX_AR_WINSZ,
421 : : .relative_sectag_insert = 1,
422 : : .fixed_sectag_insert = 1,
423 : : .icv_include_da_sa = 1,
424 : : .ctrl_port_enable = 1,
425 : : .preserve_sectag = 1,
426 : : .preserve_icv = 1,
427 : : .validate_frames = 1,
428 : : .re_key = 1,
429 : : .anti_replay = 1,
430 : : },
431 : : },
432 : : { /* MACsec Inline Protocol, AES-GCM-256 algo */
433 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
434 : : .protocol = RTE_SECURITY_PROTOCOL_MACSEC,
435 : : .macsec = {
436 : : .mtu = ROC_MCS_MAX_MTU,
437 : : .alg = RTE_SECURITY_MACSEC_ALG_GCM_256,
438 : : .max_nb_sc = 128,
439 : : .max_nb_sa = 256,
440 : : .max_nb_sess = 256,
441 : : .replay_win_sz = ROC_MCS_MAX_AR_WINSZ,
442 : : .relative_sectag_insert = 1,
443 : : .fixed_sectag_insert = 1,
444 : : .icv_include_da_sa = 1,
445 : : .ctrl_port_enable = 1,
446 : : .preserve_sectag = 1,
447 : : .preserve_icv = 1,
448 : : .validate_frames = 1,
449 : : .re_key = 1,
450 : : .anti_replay = 1,
451 : : },
452 : : },
453 : : { /* MACsec Inline Protocol, AES-GCM-XPN-128 algo */
454 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
455 : : .protocol = RTE_SECURITY_PROTOCOL_MACSEC,
456 : : .macsec = {
457 : : .mtu = ROC_MCS_MAX_MTU,
458 : : .alg = RTE_SECURITY_MACSEC_ALG_GCM_XPN_128,
459 : : .max_nb_sc = 128,
460 : : .max_nb_sa = 256,
461 : : .max_nb_sess = 256,
462 : : .replay_win_sz = ROC_MCS_MAX_AR_WINSZ,
463 : : .relative_sectag_insert = 1,
464 : : .fixed_sectag_insert = 1,
465 : : .icv_include_da_sa = 1,
466 : : .ctrl_port_enable = 1,
467 : : .preserve_sectag = 1,
468 : : .preserve_icv = 1,
469 : : .validate_frames = 1,
470 : : .re_key = 1,
471 : : .anti_replay = 1,
472 : : },
473 : : },
474 : : { /* MACsec Inline Protocol, AES-GCM-XPN-256 algo */
475 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
476 : : .protocol = RTE_SECURITY_PROTOCOL_MACSEC,
477 : : .macsec = {
478 : : .mtu = ROC_MCS_MAX_MTU,
479 : : .alg = RTE_SECURITY_MACSEC_ALG_GCM_XPN_256,
480 : : .max_nb_sc = 128,
481 : : .max_nb_sa = 256,
482 : : .max_nb_sess = 256,
483 : : .replay_win_sz = ROC_MCS_MAX_AR_WINSZ,
484 : : .relative_sectag_insert = 1,
485 : : .fixed_sectag_insert = 1,
486 : : .icv_include_da_sa = 1,
487 : : .ctrl_port_enable = 1,
488 : : .preserve_sectag = 1,
489 : : .preserve_icv = 1,
490 : : .validate_frames = 1,
491 : : .re_key = 1,
492 : : .anti_replay = 1,
493 : : },
494 : : },
495 : : };
496 : :
497 : : #define SEC_CAPS_LEN (RTE_DIM(cn10k_eth_sec_ipsec_capabilities) + \
498 : : RTE_DIM(cn10k_eth_sec_macsec_capabilities) + 1)
499 : :
500 : : static struct rte_security_capability cn10k_eth_sec_capabilities[SEC_CAPS_LEN];
501 : :
502 : : static inline void
503 : : cnxk_pktmbuf_free_no_cache(struct rte_mbuf *mbuf)
504 : : {
505 : : struct rte_mbuf *next;
506 : :
507 [ # # # # ]: 0 : if (!mbuf)
508 : : return;
509 : : do {
510 : 0 : next = mbuf->next;
511 [ # # # # ]: 0 : roc_npa_aura_op_free(mbuf->pool->pool_id, 1, (rte_iova_t)mbuf);
512 : : mbuf = next;
513 [ # # # # ]: 0 : } while (mbuf != NULL);
514 : : }
515 : :
516 : : void
517 : 0 : cn10k_eth_sec_sso_work_cb(uint64_t *gw, void *args, uint32_t soft_exp_event)
518 : : {
519 : : struct rte_eth_event_ipsec_desc desc;
520 : : struct cn10k_sec_sess_priv sess_priv;
521 : : struct cn10k_outb_priv_data *priv;
522 : : struct roc_ot_ipsec_outb_sa *sa;
523 : : struct cpt_cn10k_res_s *res;
524 : : struct rte_eth_dev *eth_dev;
525 : : struct cnxk_eth_dev *dev;
526 : : static uint64_t warn_cnt;
527 : : uint16_t dlen_adj, rlen;
528 : : struct rte_mbuf *mbuf;
529 : : uintptr_t sa_base;
530 : : uintptr_t nixtx;
531 : : uint8_t port;
532 : :
533 : : RTE_SET_USED(args);
534 : :
535 [ # # # ]: 0 : switch ((gw[0] >> 28) & 0xF) {
536 : 0 : case RTE_EVENT_TYPE_ETHDEV:
537 : : /* Event from inbound inline dev due to IPSEC packet bad L4 */
538 : 0 : mbuf = (struct rte_mbuf *)(gw[1] - sizeof(struct rte_mbuf));
539 : 0 : plt_nix_dbg("Received mbuf %p from inline dev inbound", mbuf);
540 : : cnxk_pktmbuf_free_no_cache(mbuf);
541 : 0 : return;
542 : 0 : case RTE_EVENT_TYPE_CPU:
543 : : /* Check for subtype */
544 [ # # ]: 0 : if (((gw[0] >> 20) & 0xFF) == CNXK_ETHDEV_SEC_OUTB_EV_SUB) {
545 : : /* Event from outbound inline error */
546 : 0 : mbuf = (struct rte_mbuf *)gw[1];
547 : : break;
548 : : }
549 : : /* Fall through */
550 : : default:
551 [ # # ]: 0 : if (soft_exp_event & 0x1) {
552 : : sa = (struct roc_ot_ipsec_outb_sa *)args;
553 : : priv = roc_nix_inl_ot_ipsec_outb_sa_sw_rsvd(sa);
554 : 0 : desc.metadata = (uint64_t)priv->userdata;
555 [ # # ]: 0 : if (sa->w2.s.life_unit == ROC_IE_OT_SA_LIFE_UNIT_PKTS)
556 : 0 : desc.subtype =
557 : : RTE_ETH_EVENT_IPSEC_SA_PKT_EXPIRY;
558 : : else
559 : 0 : desc.subtype =
560 : : RTE_ETH_EVENT_IPSEC_SA_BYTE_EXPIRY;
561 : 0 : eth_dev = &rte_eth_devices[soft_exp_event >> 8];
562 : 0 : rte_eth_dev_callback_process(eth_dev,
563 : : RTE_ETH_EVENT_IPSEC, &desc);
564 : : } else {
565 : 0 : plt_err("Unknown event gw[0] = 0x%016lx, gw[1] = 0x%016lx",
566 : : gw[0], gw[1]);
567 : : }
568 : : return;
569 : : }
570 : :
571 : : /* Get ethdev port from tag */
572 : 0 : port = gw[0] & 0xFF;
573 : 0 : eth_dev = &rte_eth_devices[port];
574 : : dev = cnxk_eth_pmd_priv(eth_dev);
575 : :
576 : 0 : sess_priv.u64 = *rte_security_dynfield(mbuf);
577 : : /* Calculate dlen adj */
578 : 0 : dlen_adj = mbuf->pkt_len - mbuf->l2_len;
579 : 0 : rlen = (dlen_adj + sess_priv.roundup_len) +
580 : 0 : (sess_priv.roundup_byte - 1);
581 : 0 : rlen &= ~(uint64_t)(sess_priv.roundup_byte - 1);
582 : 0 : rlen += sess_priv.partial_len;
583 : 0 : dlen_adj = rlen - dlen_adj;
584 : :
585 : : /* Find the res area residing on next cacheline after end of data */
586 : 0 : nixtx = rte_pktmbuf_mtod(mbuf, uintptr_t) + mbuf->pkt_len + dlen_adj;
587 : : nixtx += BIT_ULL(7);
588 : 0 : nixtx = (nixtx - 1) & ~(BIT_ULL(7) - 1);
589 : 0 : res = (struct cpt_cn10k_res_s *)nixtx;
590 : :
591 : 0 : plt_nix_dbg("Outbound error, mbuf %p, sa_index %u, compcode %x uc %x",
592 : : mbuf, sess_priv.sa_idx, res->compcode, res->uc_compcode);
593 : :
594 : 0 : sess_priv.u64 = *rte_security_dynfield(mbuf);
595 : :
596 : 0 : sa_base = dev->outb.sa_base;
597 [ # # # # ]: 0 : sa = roc_nix_inl_ot_ipsec_outb_sa(sa_base, sess_priv.sa_idx);
598 : : priv = roc_nix_inl_ot_ipsec_outb_sa_sw_rsvd(sa);
599 : :
600 : : memset(&desc, 0, sizeof(desc));
601 : :
602 [ # # # # ]: 0 : switch (res->uc_compcode) {
603 : 0 : case ROC_IE_OT_UCC_ERR_SA_OVERFLOW:
604 : 0 : desc.subtype = RTE_ETH_EVENT_IPSEC_ESN_OVERFLOW;
605 : 0 : break;
606 : 0 : case ROC_IE_OT_UCC_ERR_SA_EXPIRED:
607 [ # # ]: 0 : if (sa->w2.s.life_unit == ROC_IE_OT_SA_LIFE_UNIT_PKTS)
608 : 0 : desc.subtype = RTE_ETH_EVENT_IPSEC_SA_PKT_HARD_EXPIRY;
609 : : else
610 : 0 : desc.subtype = RTE_ETH_EVENT_IPSEC_SA_BYTE_HARD_EXPIRY;
611 : : break;
612 : 0 : case ROC_IE_OT_UCC_ERR_PKT_IP:
613 : 0 : warn_cnt++;
614 [ # # ]: 0 : if (warn_cnt % 10000 == 0)
615 : 0 : plt_warn("Outbound error, bad ip pkt, mbuf %p,"
616 : : " sa_index %u (total warnings %" PRIu64 ")",
617 : : mbuf, sess_priv.sa_idx, warn_cnt);
618 : 0 : desc.subtype = -res->uc_compcode;
619 : 0 : break;
620 : 0 : default:
621 : 0 : warn_cnt++;
622 [ # # ]: 0 : if (warn_cnt % 10000 == 0)
623 : 0 : plt_warn("Outbound error, mbuf %p, sa_index %u,"
624 : : " compcode %x uc %x,"
625 : : " (total warnings %" PRIu64 ")",
626 : : mbuf, sess_priv.sa_idx, res->compcode,
627 : : res->uc_compcode, warn_cnt);
628 : 0 : desc.subtype = -res->uc_compcode;
629 : 0 : break;
630 : : }
631 : :
632 : 0 : desc.metadata = (uint64_t)priv->userdata;
633 : 0 : rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_IPSEC, &desc);
634 : : cnxk_pktmbuf_free_no_cache(mbuf);
635 : : }
636 : :
637 : : static void
638 : 0 : outb_dbg_iv_update(struct roc_ot_ipsec_outb_sa *outb_sa, const char *__iv_str)
639 : : {
640 : 0 : uint8_t *iv_dbg = outb_sa->iv.iv_dbg;
641 : 0 : char *iv_str = strdup(__iv_str);
642 : : char *iv_b = NULL, len = 16;
643 : : char *save;
644 : : int i;
645 : :
646 [ # # ]: 0 : if (!iv_str)
647 : 0 : return;
648 : :
649 [ # # ]: 0 : if (outb_sa->w2.s.enc_type == ROC_IE_OT_SA_ENC_AES_GCM ||
650 : 0 : outb_sa->w2.s.enc_type == ROC_IE_OT_SA_ENC_AES_CTR ||
651 [ # # ]: 0 : outb_sa->w2.s.enc_type == ROC_IE_OT_SA_ENC_AES_CCM ||
652 [ # # ]: 0 : outb_sa->w2.s.auth_type == ROC_IE_OT_SA_AUTH_AES_GMAC) {
653 : 0 : memset(outb_sa->iv.s.iv_dbg1, 0, sizeof(outb_sa->iv.s.iv_dbg1));
654 : 0 : memset(outb_sa->iv.s.iv_dbg2, 0, sizeof(outb_sa->iv.s.iv_dbg2));
655 : :
656 : : iv_dbg = outb_sa->iv.s.iv_dbg1;
657 [ # # ]: 0 : for (i = 0; i < 4; i++) {
658 [ # # ]: 0 : iv_b = strtok_r(i ? NULL : iv_str, ",", &save);
659 [ # # ]: 0 : if (!iv_b)
660 : : break;
661 : 0 : iv_dbg[i] = strtoul(iv_b, NULL, 0);
662 : : }
663 [ # # ]: 0 : *(uint32_t *)iv_dbg = rte_be_to_cpu_32(*(uint32_t *)iv_dbg);
664 : :
665 : : iv_dbg = outb_sa->iv.s.iv_dbg2;
666 [ # # ]: 0 : for (i = 0; i < 4; i++) {
667 : 0 : iv_b = strtok_r(NULL, ",", &save);
668 [ # # ]: 0 : if (!iv_b)
669 : : break;
670 : 0 : iv_dbg[i] = strtoul(iv_b, NULL, 0);
671 : : }
672 [ # # ]: 0 : *(uint32_t *)iv_dbg = rte_be_to_cpu_32(*(uint32_t *)iv_dbg);
673 : :
674 : : } else {
675 : : iv_dbg = outb_sa->iv.iv_dbg;
676 : : memset(iv_dbg, 0, sizeof(outb_sa->iv.iv_dbg));
677 : :
678 [ # # ]: 0 : for (i = 0; i < len; i++) {
679 [ # # ]: 0 : iv_b = strtok_r(i ? NULL : iv_str, ",", &save);
680 [ # # ]: 0 : if (!iv_b)
681 : : break;
682 : 0 : iv_dbg[i] = strtoul(iv_b, NULL, 0);
683 : : }
684 [ # # ]: 0 : *(uint64_t *)iv_dbg = rte_be_to_cpu_64(*(uint64_t *)iv_dbg);
685 : 0 : *(uint64_t *)&iv_dbg[8] =
686 [ # # ]: 0 : rte_be_to_cpu_64(*(uint64_t *)&iv_dbg[8]);
687 : : }
688 : :
689 : : /* Update source of IV */
690 : 0 : outb_sa->w2.s.iv_src = ROC_IE_OT_SA_IV_SRC_FROM_SA;
691 : 0 : free(iv_str);
692 : : }
693 : :
694 : : static int
695 : 0 : cn10k_eth_sec_outb_sa_misc_fill(struct roc_nix *roc_nix,
696 : : struct roc_ot_ipsec_outb_sa *sa, void *sa_cptr,
697 : : struct rte_security_ipsec_xform *ipsec_xfrm,
698 : : uint32_t sa_idx)
699 : : {
700 : : uint64_t *ring_base, ring_addr;
701 : :
702 : 0 : if (ipsec_xfrm->life.bytes_soft_limit |
703 [ # # ]: 0 : ipsec_xfrm->life.packets_soft_limit) {
704 : 0 : ring_base = roc_nix_inl_outb_ring_base_get(roc_nix);
705 [ # # ]: 0 : if (ring_base == NULL)
706 : : return -ENOTSUP;
707 : :
708 : 0 : ring_addr = ring_base[sa_idx >>
709 : : ROC_NIX_SOFT_EXP_ERR_RING_MAX_ENTRY_LOG2];
710 : 0 : sa->ctx.err_ctl.s.mode = ROC_IE_OT_ERR_CTL_MODE_RING;
711 : 0 : sa->ctx.err_ctl.s.address = ring_addr >> 3;
712 : 0 : sa->w0.s.ctx_id = ((uintptr_t)sa_cptr >> 51) & 0x1ff;
713 : : }
714 : :
715 : : return 0;
716 : : }
717 : :
718 : : static int
719 [ # # ]: 0 : cn10k_eth_sec_session_create(void *device,
720 : : struct rte_security_session_conf *conf,
721 : : struct rte_security_session *sess)
722 : : {
723 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
724 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
725 : : struct rte_security_ipsec_xform *ipsec;
726 : : struct cn10k_sec_sess_priv sess_priv;
727 : : struct rte_crypto_sym_xform *crypto;
728 : 0 : struct cnxk_eth_sec_sess *eth_sec = SECURITY_GET_SESS_PRIV(sess);
729 : 0 : struct roc_nix *nix = &dev->nix;
730 : : bool inbound, inl_dev;
731 : : rte_spinlock_t *lock;
732 : 0 : char tbuf[128] = {0};
733 : : int rc = 0;
734 : :
735 [ # # ]: 0 : if (conf->action_type != RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL)
736 : : return -ENOTSUP;
737 : :
738 [ # # ]: 0 : if (conf->protocol == RTE_SECURITY_PROTOCOL_MACSEC)
739 : 0 : return cnxk_eth_macsec_session_create(dev, conf, sess);
740 [ # # ]: 0 : else if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC)
741 : : return -ENOTSUP;
742 : :
743 [ # # ]: 0 : if (rte_security_dynfield_register() < 0)
744 : : return -ENOTSUP;
745 : :
746 [ # # ]: 0 : if (conf->ipsec.options.ip_reassembly_en &&
747 [ # # ]: 0 : dev->reass_dynfield_off < 0) {
748 [ # # ]: 0 : if (rte_eth_ip_reassembly_dynfield_register(&dev->reass_dynfield_off,
749 : : &dev->reass_dynflag_bit) < 0)
750 : 0 : return -rte_errno;
751 : : }
752 : :
753 [ # # ]: 0 : if (conf->ipsec.options.ingress_oop &&
754 [ # # ]: 0 : rte_security_oop_dynfield_offset < 0) {
755 : : /* Register for security OOP dynfield if required */
756 [ # # ]: 0 : if (rte_security_oop_dynfield_register() < 0)
757 : 0 : return -rte_errno;
758 : : }
759 : :
760 : : /* We cannot support inbound reassembly and OOP together */
761 [ # # ]: 0 : if (conf->ipsec.options.ip_reassembly_en &&
762 : : conf->ipsec.options.ingress_oop) {
763 : 0 : plt_err("Cannot support Inbound reassembly and OOP together");
764 : 0 : return -ENOTSUP;
765 : : }
766 : :
767 : 0 : ipsec = &conf->ipsec;
768 : 0 : crypto = conf->crypto_xform;
769 : 0 : inbound = !!(ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
770 : 0 : inl_dev = !!dev->inb.inl_dev;
771 : :
772 : : /* Search if a session already exits */
773 [ # # ]: 0 : if (cnxk_eth_sec_sess_get_by_spi(dev, ipsec->spi, inbound)) {
774 [ # # ]: 0 : plt_err("%s SA with SPI %u already in use",
775 : : inbound ? "Inbound" : "Outbound", ipsec->spi);
776 : 0 : return -EEXIST;
777 : : }
778 : :
779 : : memset(eth_sec, 0, sizeof(struct cnxk_eth_sec_sess));
780 : 0 : sess_priv.u64 = 0;
781 : :
782 [ # # ]: 0 : lock = inbound ? &dev->inb.lock : &dev->outb.lock;
783 : : rte_spinlock_lock(lock);
784 : :
785 : : /* Acquire lock on inline dev for inbound */
786 [ # # ]: 0 : if (inbound && inl_dev)
787 : 0 : roc_nix_inl_dev_lock();
788 : :
789 [ # # ]: 0 : if (inbound) {
790 : : struct roc_ot_ipsec_inb_sa *inb_sa, *inb_sa_dptr;
791 : : struct cn10k_inb_priv_data *inb_priv;
792 : : uint32_t spi_mask;
793 : : uintptr_t sa;
794 : :
795 : : PLT_STATIC_ASSERT(sizeof(struct cn10k_inb_priv_data) <
796 : : ROC_NIX_INL_OT_IPSEC_INB_SW_RSVD);
797 : :
798 : 0 : spi_mask = roc_nix_inl_inb_spi_range(nix, inl_dev, NULL, NULL);
799 : :
800 : : /* Get Inbound SA from NIX_RX_IPSEC_SA_BASE */
801 : 0 : sa = roc_nix_inl_inb_sa_get(nix, inl_dev, ipsec->spi);
802 [ # # # # ]: 0 : if (!sa && dev->inb.inl_dev) {
803 : : snprintf(tbuf, sizeof(tbuf),
804 : : "Failed to create ingress sa, inline dev "
805 : : "not found or spi not in range");
806 : : rc = -ENOTSUP;
807 : 0 : goto err;
808 [ # # ]: 0 : } else if (!sa) {
809 : : snprintf(tbuf, sizeof(tbuf),
810 : : "Failed to create ingress sa");
811 : : rc = -EFAULT;
812 : 0 : goto err;
813 : : }
814 : :
815 : 0 : inb_sa = (struct roc_ot_ipsec_inb_sa *)sa;
816 : :
817 : : /* Check if SA is already in use */
818 [ # # ]: 0 : if (inb_sa->w2.s.valid) {
819 : 0 : snprintf(tbuf, sizeof(tbuf),
820 : : "Inbound SA with SPI %u already in use",
821 : : ipsec->spi);
822 : : rc = -EBUSY;
823 : 0 : goto err;
824 : : }
825 : :
826 : 0 : inb_sa_dptr = (struct roc_ot_ipsec_inb_sa *)dev->inb.sa_dptr;
827 : : memset(inb_sa_dptr, 0, sizeof(struct roc_ot_ipsec_inb_sa));
828 : :
829 : : /* Fill inbound sa params */
830 : 0 : rc = cnxk_ot_ipsec_inb_sa_fill(inb_sa_dptr, ipsec, crypto,
831 : : true);
832 [ # # ]: 0 : if (rc) {
833 : : snprintf(tbuf, sizeof(tbuf),
834 : : "Failed to init inbound sa, rc=%d", rc);
835 : 0 : goto err;
836 : : }
837 : :
838 : : inb_priv = roc_nix_inl_ot_ipsec_inb_sa_sw_rsvd(inb_sa);
839 : : /* Back pointer to get eth_sec */
840 : 0 : inb_priv->eth_sec = eth_sec;
841 : : /* Save userdata in inb private area */
842 : 0 : inb_priv->userdata = conf->userdata;
843 : :
844 : : /* Save SA index/SPI in cookie for now */
845 : 0 : inb_sa_dptr->w1.s.cookie =
846 [ # # ]: 0 : rte_cpu_to_be_32(ipsec->spi & spi_mask);
847 : :
848 [ # # ]: 0 : if (ipsec->options.stats == 1) {
849 : : /* Enable mib counters */
850 : 0 : inb_sa_dptr->w0.s.count_mib_bytes = 1;
851 : 0 : inb_sa_dptr->w0.s.count_mib_pkts = 1;
852 : : }
853 : :
854 : : /* Enable out-of-place processing */
855 [ # # ]: 0 : if (ipsec->options.ingress_oop)
856 : 0 : inb_sa_dptr->w0.s.pkt_format =
857 : : ROC_IE_OT_SA_PKT_FMT_FULL;
858 : :
859 : : /* Prepare session priv */
860 : 0 : sess_priv.inb_sa = 1;
861 : 0 : sess_priv.sa_idx = ipsec->spi & spi_mask;
862 : :
863 : : /* Pointer from eth_sec -> inb_sa */
864 : 0 : eth_sec->sa = inb_sa;
865 : 0 : eth_sec->sess = sess;
866 : 0 : eth_sec->sa_idx = ipsec->spi & spi_mask;
867 : 0 : eth_sec->spi = ipsec->spi;
868 : 0 : eth_sec->inl_dev = !!dev->inb.inl_dev;
869 : 0 : eth_sec->inb = true;
870 : 0 : eth_sec->inb_oop = !!ipsec->options.ingress_oop;
871 : :
872 : 0 : TAILQ_INSERT_TAIL(&dev->inb.list, eth_sec, entry);
873 : 0 : dev->inb.nb_sess++;
874 : : /* Sync session in context cache */
875 : 0 : rc = roc_nix_inl_ctx_write(&dev->nix, inb_sa_dptr, eth_sec->sa,
876 : : eth_sec->inb,
877 : : sizeof(struct roc_ot_ipsec_inb_sa));
878 [ # # ]: 0 : if (rc)
879 : 0 : goto err;
880 : :
881 [ # # ]: 0 : if (conf->ipsec.options.ip_reassembly_en) {
882 : 0 : inb_priv->reass_dynfield_off = dev->reass_dynfield_off;
883 : 0 : inb_priv->reass_dynflag_bit = dev->reass_dynflag_bit;
884 : : }
885 : :
886 [ # # ]: 0 : if (ipsec->options.ingress_oop)
887 : 0 : dev->inb.nb_oop++;
888 : :
889 : : /* Update function pointer to handle OOP sessions */
890 [ # # ]: 0 : if (dev->inb.nb_oop &&
891 [ # # ]: 0 : !(dev->rx_offload_flags & NIX_RX_REAS_F)) {
892 : 0 : dev->rx_offload_flags |= NIX_RX_REAS_F;
893 : 0 : cn10k_eth_set_rx_function(eth_dev);
894 : : }
895 : : } else {
896 : : struct roc_ot_ipsec_outb_sa *outb_sa, *outb_sa_dptr;
897 : : struct cn10k_outb_priv_data *outb_priv;
898 : : struct cnxk_ipsec_outb_rlens *rlens;
899 : 0 : uint64_t sa_base = dev->outb.sa_base;
900 : : const char *iv_str;
901 : : uint32_t sa_idx;
902 : :
903 : : PLT_STATIC_ASSERT(sizeof(struct cn10k_outb_priv_data) <
904 : : ROC_NIX_INL_OT_IPSEC_OUTB_SW_RSVD);
905 : :
906 : : /* Alloc an sa index */
907 : 0 : rc = cnxk_eth_outb_sa_idx_get(dev, &sa_idx, ipsec->spi);
908 [ # # ]: 0 : if (rc)
909 : 0 : goto err;
910 : :
911 : 0 : outb_sa = roc_nix_inl_ot_ipsec_outb_sa(sa_base, sa_idx);
912 : : outb_priv = roc_nix_inl_ot_ipsec_outb_sa_sw_rsvd(outb_sa);
913 : 0 : rlens = &outb_priv->rlens;
914 : :
915 : 0 : outb_sa_dptr = (struct roc_ot_ipsec_outb_sa *)dev->outb.sa_dptr;
916 : : memset(outb_sa_dptr, 0, sizeof(struct roc_ot_ipsec_outb_sa));
917 : :
918 : : /* Fill outbound sa params */
919 : 0 : rc = cnxk_ot_ipsec_outb_sa_fill(outb_sa_dptr, ipsec, crypto);
920 [ # # ]: 0 : if (rc) {
921 : : snprintf(tbuf, sizeof(tbuf),
922 : : "Failed to init outbound sa, rc=%d", rc);
923 : 0 : rc |= cnxk_eth_outb_sa_idx_put(dev, sa_idx);
924 : 0 : goto err;
925 : : }
926 : :
927 [ # # ]: 0 : if (conf->ipsec.options.iv_gen_disable == 1) {
928 : 0 : iv_str = getenv("ETH_SEC_IV_OVR");
929 [ # # ]: 0 : if (iv_str)
930 : 0 : outb_dbg_iv_update(outb_sa_dptr, iv_str);
931 : : }
932 : : /* Fill outbound sa misc params */
933 : 0 : rc = cn10k_eth_sec_outb_sa_misc_fill(&dev->nix, outb_sa_dptr,
934 : : outb_sa, ipsec, sa_idx);
935 [ # # ]: 0 : if (rc) {
936 : : snprintf(tbuf, sizeof(tbuf),
937 : : "Failed to init outb sa misc params, rc=%d",
938 : : rc);
939 : 0 : rc |= cnxk_eth_outb_sa_idx_put(dev, sa_idx);
940 : 0 : goto err;
941 : : }
942 : :
943 : : /* Save userdata */
944 : 0 : outb_priv->userdata = conf->userdata;
945 : 0 : outb_priv->sa_idx = sa_idx;
946 : 0 : outb_priv->eth_sec = eth_sec;
947 : :
948 : : /* Save rlen info */
949 : 0 : cnxk_ipsec_outb_rlens_get(rlens, ipsec, crypto);
950 : :
951 [ # # ]: 0 : if (ipsec->options.stats == 1) {
952 : : /* Enable mib counters */
953 : 0 : outb_sa_dptr->w0.s.count_mib_bytes = 1;
954 : 0 : outb_sa_dptr->w0.s.count_mib_pkts = 1;
955 : : }
956 : :
957 : : /* Prepare session priv */
958 : 0 : sess_priv.sa_idx = outb_priv->sa_idx;
959 : 0 : sess_priv.roundup_byte = rlens->roundup_byte;
960 : 0 : sess_priv.roundup_len = rlens->roundup_len;
961 : 0 : sess_priv.partial_len = rlens->partial_len;
962 : 0 : sess_priv.mode = outb_sa_dptr->w2.s.ipsec_mode;
963 : 0 : sess_priv.outer_ip_ver = outb_sa_dptr->w2.s.outer_ip_ver;
964 : : /* Propagate inner checksum enable from SA to fast path */
965 [ # # ]: 0 : sess_priv.chksum = (!ipsec->options.ip_csum_enable << 1 |
966 : 0 : !ipsec->options.l4_csum_enable);
967 [ # # ]: 0 : sess_priv.dec_ttl = ipsec->options.dec_ttl;
968 [ # # ]: 0 : if (roc_feature_nix_has_inl_ipsec_mseg() &&
969 [ # # ]: 0 : dev->outb.cpt_eng_caps & BIT_ULL(35))
970 : 0 : sess_priv.nixtx_off = 1;
971 : :
972 : : /* Pointer from eth_sec -> outb_sa */
973 : 0 : eth_sec->sa = outb_sa;
974 : 0 : eth_sec->sess = sess;
975 : 0 : eth_sec->sa_idx = sa_idx;
976 : 0 : eth_sec->spi = ipsec->spi;
977 : :
978 : 0 : TAILQ_INSERT_TAIL(&dev->outb.list, eth_sec, entry);
979 : 0 : dev->outb.nb_sess++;
980 : : /* Sync session in context cache */
981 : 0 : rc = roc_nix_inl_ctx_write(&dev->nix, outb_sa_dptr, eth_sec->sa,
982 : 0 : eth_sec->inb,
983 : : sizeof(struct roc_ot_ipsec_outb_sa));
984 [ # # ]: 0 : if (rc)
985 : 0 : goto err;
986 : : }
987 [ # # ]: 0 : if (inbound && inl_dev)
988 : 0 : roc_nix_inl_dev_unlock();
989 : : rte_spinlock_unlock(lock);
990 : :
991 [ # # ]: 0 : plt_nix_dbg("Created %s session with spi=%u, sa_idx=%u inl_dev=%u",
992 : : inbound ? "inbound" : "outbound", eth_sec->spi,
993 : : eth_sec->sa_idx, eth_sec->inl_dev);
994 : : /*
995 : : * Update fast path info in priv area.
996 : : */
997 : 0 : sess->fast_mdata = sess_priv.u64;
998 : :
999 : 0 : return 0;
1000 : 0 : err:
1001 [ # # ]: 0 : if (inbound && inl_dev)
1002 : 0 : roc_nix_inl_dev_unlock();
1003 : : rte_spinlock_unlock(lock);
1004 : :
1005 [ # # ]: 0 : if (rc)
1006 : 0 : plt_err("%s", tbuf);
1007 : : return rc;
1008 : : }
1009 : :
1010 : : static int
1011 : 0 : cn10k_eth_sec_session_destroy(void *device, struct rte_security_session *sess)
1012 : : {
1013 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
1014 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1015 : : struct cnxk_macsec_sess *macsec_sess;
1016 : : struct cnxk_eth_sec_sess *eth_sec;
1017 : : rte_spinlock_t *lock;
1018 : : void *sa_dptr;
1019 : :
1020 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
1021 [ # # ]: 0 : if (!eth_sec) {
1022 : 0 : macsec_sess = cnxk_eth_macsec_sess_get_by_sess(dev, sess);
1023 [ # # ]: 0 : if (macsec_sess)
1024 : 0 : return cnxk_eth_macsec_session_destroy(dev, sess);
1025 : : return -ENOENT;
1026 : : }
1027 : :
1028 [ # # ]: 0 : lock = eth_sec->inb ? &dev->inb.lock : &dev->outb.lock;
1029 : : rte_spinlock_lock(lock);
1030 : :
1031 [ # # ]: 0 : if (eth_sec->inl_dev)
1032 : 0 : roc_nix_inl_dev_lock();
1033 : :
1034 [ # # ]: 0 : if (eth_sec->inb) {
1035 : : /* Disable SA */
1036 : 0 : sa_dptr = dev->inb.sa_dptr;
1037 : 0 : roc_ot_ipsec_inb_sa_init(sa_dptr, true);
1038 : :
1039 : 0 : roc_nix_inl_ctx_write(&dev->nix, sa_dptr, eth_sec->sa,
1040 : 0 : eth_sec->inb,
1041 : : sizeof(struct roc_ot_ipsec_inb_sa));
1042 [ # # ]: 0 : TAILQ_REMOVE(&dev->inb.list, eth_sec, entry);
1043 : 0 : dev->inb.nb_sess--;
1044 [ # # ]: 0 : if (eth_sec->inb_oop)
1045 : 0 : dev->inb.nb_oop--;
1046 : :
1047 : : /* Clear offload flags if was used by OOP */
1048 [ # # # # ]: 0 : if (!dev->inb.nb_oop && !dev->inb.reass_en &&
1049 [ # # ]: 0 : dev->rx_offload_flags & NIX_RX_REAS_F) {
1050 : 0 : dev->rx_offload_flags &= ~NIX_RX_REAS_F;
1051 : 0 : cn10k_eth_set_rx_function(eth_dev);
1052 : : }
1053 : : } else {
1054 : : /* Disable SA */
1055 : 0 : sa_dptr = dev->outb.sa_dptr;
1056 : 0 : roc_ot_ipsec_outb_sa_init(sa_dptr);
1057 : :
1058 : 0 : roc_nix_inl_ctx_write(&dev->nix, sa_dptr, eth_sec->sa,
1059 : 0 : eth_sec->inb,
1060 : : sizeof(struct roc_ot_ipsec_outb_sa));
1061 : : /* Release Outbound SA index */
1062 : 0 : cnxk_eth_outb_sa_idx_put(dev, eth_sec->sa_idx);
1063 [ # # ]: 0 : TAILQ_REMOVE(&dev->outb.list, eth_sec, entry);
1064 : 0 : dev->outb.nb_sess--;
1065 : : }
1066 [ # # ]: 0 : if (eth_sec->inl_dev)
1067 : 0 : roc_nix_inl_dev_unlock();
1068 : :
1069 : : rte_spinlock_unlock(lock);
1070 : :
1071 [ # # ]: 0 : plt_nix_dbg("Destroyed %s session with spi=%u, sa_idx=%u, inl_dev=%u",
1072 : : eth_sec->inb ? "inbound" : "outbound", eth_sec->spi,
1073 : : eth_sec->sa_idx, eth_sec->inl_dev);
1074 : :
1075 : 0 : return 0;
1076 : : }
1077 : :
1078 : : static const struct rte_security_capability *
1079 : 0 : cn10k_eth_sec_capabilities_get(void *device __rte_unused)
1080 : : {
1081 : 0 : return cn10k_eth_sec_capabilities;
1082 : : }
1083 : :
1084 : : static int
1085 [ # # ]: 0 : cn10k_eth_sec_session_update(void *device, struct rte_security_session *sess,
1086 : : struct rte_security_session_conf *conf)
1087 : : {
1088 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
1089 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1090 : : struct roc_ot_ipsec_inb_sa *inb_sa_dptr;
1091 : : struct rte_security_ipsec_xform *ipsec;
1092 : : struct rte_crypto_sym_xform *crypto;
1093 : : struct cnxk_eth_sec_sess *eth_sec;
1094 : : bool inbound;
1095 : : int rc;
1096 : :
1097 [ # # ]: 0 : if (conf->action_type != RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
1098 : : conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC)
1099 : : return -ENOENT;
1100 : :
1101 : 0 : ipsec = &conf->ipsec;
1102 : 0 : crypto = conf->crypto_xform;
1103 : 0 : inbound = !!(ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
1104 : :
1105 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
1106 [ # # ]: 0 : if (!eth_sec)
1107 : : return -ENOENT;
1108 : :
1109 : 0 : eth_sec->spi = conf->ipsec.spi;
1110 : :
1111 [ # # ]: 0 : if (inbound) {
1112 : 0 : inb_sa_dptr = (struct roc_ot_ipsec_inb_sa *)dev->inb.sa_dptr;
1113 : : memset(inb_sa_dptr, 0, sizeof(struct roc_ot_ipsec_inb_sa));
1114 : :
1115 : 0 : rc = cnxk_ot_ipsec_inb_sa_fill(inb_sa_dptr, ipsec, crypto,
1116 : : true);
1117 [ # # ]: 0 : if (rc)
1118 : : return -EINVAL;
1119 : :
1120 : 0 : rc = roc_nix_inl_ctx_write(&dev->nix, inb_sa_dptr, eth_sec->sa,
1121 : 0 : eth_sec->inb,
1122 : : sizeof(struct roc_ot_ipsec_inb_sa));
1123 [ # # ]: 0 : if (rc)
1124 : 0 : return -EINVAL;
1125 : : } else {
1126 : : struct roc_ot_ipsec_outb_sa *outb_sa_dptr;
1127 : :
1128 : 0 : outb_sa_dptr = (struct roc_ot_ipsec_outb_sa *)dev->outb.sa_dptr;
1129 : : memset(outb_sa_dptr, 0, sizeof(struct roc_ot_ipsec_outb_sa));
1130 : :
1131 : 0 : rc = cnxk_ot_ipsec_outb_sa_fill(outb_sa_dptr, ipsec, crypto);
1132 [ # # ]: 0 : if (rc)
1133 : : return -EINVAL;
1134 : 0 : rc = roc_nix_inl_ctx_write(&dev->nix, outb_sa_dptr, eth_sec->sa,
1135 : 0 : eth_sec->inb,
1136 : : sizeof(struct roc_ot_ipsec_outb_sa));
1137 [ # # ]: 0 : if (rc)
1138 : 0 : return -EINVAL;
1139 : : }
1140 : :
1141 : : return 0;
1142 : : }
1143 : :
1144 : : int
1145 : 0 : rte_pmd_cnxk_hw_sa_read(void *device, struct rte_security_session *sess,
1146 : : void *data, uint32_t len)
1147 : : {
1148 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
1149 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1150 : : struct cnxk_eth_sec_sess *eth_sec;
1151 : : int rc;
1152 : :
1153 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
1154 [ # # ]: 0 : if (eth_sec == NULL)
1155 : : return -EINVAL;
1156 : :
1157 : 0 : rc = roc_nix_inl_sa_sync(&dev->nix, eth_sec->sa, eth_sec->inb,
1158 : : ROC_NIX_INL_SA_OP_FLUSH);
1159 [ # # ]: 0 : if (rc)
1160 : : return -EINVAL;
1161 : : rte_delay_ms(1);
1162 : 0 : memcpy(data, eth_sec->sa, len);
1163 : :
1164 : 0 : return 0;
1165 : : }
1166 : :
1167 : : int
1168 : 0 : rte_pmd_cnxk_hw_sa_write(void *device, struct rte_security_session *sess,
1169 : : void *data, uint32_t len)
1170 : : {
1171 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
1172 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1173 : : struct cnxk_eth_sec_sess *eth_sec;
1174 : : int rc = -EINVAL;
1175 : :
1176 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
1177 [ # # ]: 0 : if (eth_sec == NULL)
1178 : : return rc;
1179 : 0 : rc = roc_nix_inl_ctx_write(&dev->nix, data, eth_sec->sa, eth_sec->inb,
1180 : : len);
1181 [ # # ]: 0 : if (rc)
1182 : 0 : return rc;
1183 : :
1184 : : return 0;
1185 : : }
1186 : :
1187 : : void *
1188 : 0 : rte_pmd_cnxk_inl_ipsec_res(struct rte_mbuf *mbuf)
1189 : : {
1190 : : const union nix_rx_parse_u *rx;
1191 : : uint16_t desc_size;
1192 : : uintptr_t wqe;
1193 : :
1194 [ # # # # ]: 0 : if (!mbuf || !(mbuf->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD))
1195 : : return NULL;
1196 : :
1197 : 0 : wqe = (uintptr_t)(mbuf + 1);
1198 : 0 : rx = (const union nix_rx_parse_u *)(wqe + 8);
1199 : 0 : desc_size = (rx->desc_sizem1 + 1) * 16;
1200 : :
1201 : : /* cpt_res_s sits after SG list at 16B aligned address */
1202 : 0 : return (void *)(wqe + 64 + desc_size);
1203 : : }
1204 : :
1205 : : static int
1206 : 0 : cn10k_eth_sec_session_stats_get(void *device, struct rte_security_session *sess,
1207 : : struct rte_security_stats *stats)
1208 : : {
1209 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
1210 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1211 : : struct cnxk_macsec_sess *macsec_sess;
1212 : : struct cnxk_eth_sec_sess *eth_sec;
1213 : : int rc;
1214 : :
1215 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
1216 [ # # ]: 0 : if (eth_sec == NULL) {
1217 : 0 : macsec_sess = cnxk_eth_macsec_sess_get_by_sess(dev, sess);
1218 [ # # ]: 0 : if (macsec_sess)
1219 : 0 : return cnxk_eth_macsec_session_stats_get(dev, macsec_sess, stats);
1220 : : return -EINVAL;
1221 : : }
1222 : :
1223 : 0 : rc = roc_nix_inl_sa_sync(&dev->nix, eth_sec->sa, eth_sec->inb,
1224 : : ROC_NIX_INL_SA_OP_FLUSH);
1225 [ # # ]: 0 : if (rc)
1226 : : return -EINVAL;
1227 : : rte_delay_ms(1);
1228 : :
1229 : 0 : stats->protocol = RTE_SECURITY_PROTOCOL_IPSEC;
1230 : :
1231 [ # # ]: 0 : if (eth_sec->inb) {
1232 : 0 : stats->ipsec.ipackets =
1233 : 0 : ((struct roc_ot_ipsec_inb_sa *)eth_sec->sa)->ctx.mib_pkts;
1234 : 0 : stats->ipsec.ibytes =
1235 : 0 : ((struct roc_ot_ipsec_inb_sa *)eth_sec->sa)->ctx.mib_octs;
1236 : : } else {
1237 : 0 : stats->ipsec.opackets =
1238 : 0 : ((struct roc_ot_ipsec_outb_sa *)eth_sec->sa)->ctx.mib_pkts;
1239 : 0 : stats->ipsec.obytes =
1240 : 0 : ((struct roc_ot_ipsec_outb_sa *)eth_sec->sa)->ctx.mib_octs;
1241 : : }
1242 : :
1243 : : return 0;
1244 : : }
1245 : :
1246 : : static void
1247 : 0 : eth_sec_caps_add(struct rte_security_capability eth_sec_caps[], uint32_t *idx,
1248 : : const struct rte_security_capability *caps, uint32_t nb_caps)
1249 : : {
1250 [ # # ]: 0 : PLT_VERIFY(*idx + nb_caps < SEC_CAPS_LEN);
1251 : :
1252 [ # # ]: 0 : rte_memcpy(ð_sec_caps[*idx], caps, nb_caps * sizeof(caps[0]));
1253 : 0 : *idx += nb_caps;
1254 : 0 : }
1255 : :
1256 : : void
1257 : 0 : cn10k_eth_sec_ops_override(void)
1258 : : {
1259 : : static int init_once;
1260 : 0 : uint32_t idx = 0;
1261 : :
1262 [ # # ]: 0 : if (init_once)
1263 : 0 : return;
1264 [ # # ]: 0 : init_once = 1;
1265 : :
1266 [ # # ]: 0 : if (roc_feature_nix_has_inl_ipsec())
1267 : 0 : eth_sec_caps_add(cn10k_eth_sec_capabilities, &idx,
1268 : : cn10k_eth_sec_ipsec_capabilities,
1269 : : RTE_DIM(cn10k_eth_sec_ipsec_capabilities));
1270 : :
1271 [ # # ]: 0 : if (roc_feature_nix_has_macsec())
1272 : 0 : eth_sec_caps_add(cn10k_eth_sec_capabilities, &idx,
1273 : : cn10k_eth_sec_macsec_capabilities,
1274 : : RTE_DIM(cn10k_eth_sec_macsec_capabilities));
1275 : :
1276 : 0 : cn10k_eth_sec_capabilities[idx].action = RTE_SECURITY_ACTION_TYPE_NONE;
1277 : :
1278 : : /* Update platform specific ops */
1279 : 0 : cnxk_eth_sec_ops.macsec_sa_create = cnxk_eth_macsec_sa_create;
1280 : 0 : cnxk_eth_sec_ops.macsec_sc_create = cnxk_eth_macsec_sc_create;
1281 : 0 : cnxk_eth_sec_ops.macsec_sa_destroy = cnxk_eth_macsec_sa_destroy;
1282 : 0 : cnxk_eth_sec_ops.macsec_sc_destroy = cnxk_eth_macsec_sc_destroy;
1283 : 0 : cnxk_eth_sec_ops.session_create = cn10k_eth_sec_session_create;
1284 : 0 : cnxk_eth_sec_ops.session_destroy = cn10k_eth_sec_session_destroy;
1285 : 0 : cnxk_eth_sec_ops.capabilities_get = cn10k_eth_sec_capabilities_get;
1286 : 0 : cnxk_eth_sec_ops.session_update = cn10k_eth_sec_session_update;
1287 : 0 : cnxk_eth_sec_ops.session_stats_get = cn10k_eth_sec_session_stats_get;
1288 : 0 : cnxk_eth_sec_ops.macsec_sc_stats_get = cnxk_eth_macsec_sc_stats_get;
1289 : 0 : cnxk_eth_sec_ops.macsec_sa_stats_get = cnxk_eth_macsec_sa_stats_get;
1290 : : }
|