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