1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018-2020 Intel Corporation
3 */
4
5 #include <rte_ipsec.h>
6 #include <rte_esp.h>
7 #include <rte_ip.h>
8 #include <rte_errno.h>
9 #include <rte_cryptodev.h>
10
11 #include "sa.h"
12 #include "ipsec_sqn.h"
13 #include "crypto.h"
14 #include "iph.h"
15 #include "misc.h"
16 #include "pad.h"
17
18 #define MBUF_MAX_L2_LEN RTE_LEN2MASK(RTE_MBUF_L2_LEN_BITS, uint64_t)
19 #define MBUF_MAX_L3_LEN RTE_LEN2MASK(RTE_MBUF_L3_LEN_BITS, uint64_t)
20
21 /* some helper structures */
22 struct crypto_xform {
23 struct rte_crypto_auth_xform *auth;
24 struct rte_crypto_cipher_xform *cipher;
25 struct rte_crypto_aead_xform *aead;
26 };
27
28 /*
29 * helper routine, fills internal crypto_xform structure.
30 */
31 static int
fill_crypto_xform(struct crypto_xform * xform,uint64_t type,const struct rte_ipsec_sa_prm * prm)32 fill_crypto_xform(struct crypto_xform *xform, uint64_t type,
33 const struct rte_ipsec_sa_prm *prm)
34 {
35 struct rte_crypto_sym_xform *xf, *xfn;
36
37 memset(xform, 0, sizeof(*xform));
38
39 xf = prm->crypto_xform;
40 if (xf == NULL)
41 return -EINVAL;
42
43 xfn = xf->next;
44
45 /* for AEAD just one xform required */
46 if (xf->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
47 if (xfn != NULL)
48 return -EINVAL;
49 xform->aead = &xf->aead;
50 /*
51 * CIPHER+AUTH xforms are expected in strict order,
52 * depending on SA direction:
53 * inbound: AUTH+CIPHER
54 * outbound: CIPHER+AUTH
55 */
56 } else if ((type & RTE_IPSEC_SATP_DIR_MASK) == RTE_IPSEC_SATP_DIR_IB) {
57
58 /* wrong order or no cipher */
59 if (xfn == NULL || xf->type != RTE_CRYPTO_SYM_XFORM_AUTH ||
60 xfn->type != RTE_CRYPTO_SYM_XFORM_CIPHER)
61 return -EINVAL;
62
63 xform->auth = &xf->auth;
64 xform->cipher = &xfn->cipher;
65
66 } else {
67
68 /* wrong order or no auth */
69 if (xfn == NULL || xf->type != RTE_CRYPTO_SYM_XFORM_CIPHER ||
70 xfn->type != RTE_CRYPTO_SYM_XFORM_AUTH)
71 return -EINVAL;
72
73 xform->cipher = &xf->cipher;
74 xform->auth = &xfn->auth;
75 }
76
77 return 0;
78 }
79
80 uint64_t
rte_ipsec_sa_type(const struct rte_ipsec_sa * sa)81 rte_ipsec_sa_type(const struct rte_ipsec_sa *sa)
82 {
83 return sa->type;
84 }
85
86 /**
87 * Based on number of buckets calculated required size for the
88 * structure that holds replay window and sequence number (RSN) information.
89 */
90 static size_t
rsn_size(uint32_t nb_bucket)91 rsn_size(uint32_t nb_bucket)
92 {
93 size_t sz;
94 struct replay_sqn *rsn;
95
96 sz = sizeof(*rsn) + nb_bucket * sizeof(rsn->window[0]);
97 sz = RTE_ALIGN_CEIL(sz, RTE_CACHE_LINE_SIZE);
98 return sz;
99 }
100
101 /*
102 * for given size, calculate required number of buckets.
103 */
104 static uint32_t
replay_num_bucket(uint32_t wsz)105 replay_num_bucket(uint32_t wsz)
106 {
107 uint32_t nb;
108
109 nb = rte_align32pow2(RTE_ALIGN_MUL_CEIL(wsz, WINDOW_BUCKET_SIZE) /
110 WINDOW_BUCKET_SIZE);
111 nb = RTE_MAX(nb, (uint32_t)WINDOW_BUCKET_MIN);
112
113 return nb;
114 }
115
116 static int32_t
ipsec_sa_size(uint64_t type,uint32_t * wnd_sz,uint32_t * nb_bucket)117 ipsec_sa_size(uint64_t type, uint32_t *wnd_sz, uint32_t *nb_bucket)
118 {
119 uint32_t n, sz, wsz;
120
121 wsz = *wnd_sz;
122 n = 0;
123
124 if ((type & RTE_IPSEC_SATP_DIR_MASK) == RTE_IPSEC_SATP_DIR_IB) {
125
126 /*
127 * RFC 4303 recommends 64 as minimum window size.
128 * there is no point to use ESN mode without SQN window,
129 * so make sure we have at least 64 window when ESN is enalbed.
130 */
131 wsz = ((type & RTE_IPSEC_SATP_ESN_MASK) ==
132 RTE_IPSEC_SATP_ESN_DISABLE) ?
133 wsz : RTE_MAX(wsz, (uint32_t)WINDOW_BUCKET_SIZE);
134 if (wsz != 0)
135 n = replay_num_bucket(wsz);
136 }
137
138 if (n > WINDOW_BUCKET_MAX)
139 return -EINVAL;
140
141 *wnd_sz = wsz;
142 *nb_bucket = n;
143
144 sz = rsn_size(n);
145 if ((type & RTE_IPSEC_SATP_SQN_MASK) == RTE_IPSEC_SATP_SQN_ATOM)
146 sz *= REPLAY_SQN_NUM;
147
148 sz += sizeof(struct rte_ipsec_sa);
149 return sz;
150 }
151
152 void
rte_ipsec_sa_fini(struct rte_ipsec_sa * sa)153 rte_ipsec_sa_fini(struct rte_ipsec_sa *sa)
154 {
155 memset(sa, 0, sa->size);
156 }
157
158 /*
159 * Determine expected SA type based on input parameters.
160 */
161 static int
fill_sa_type(const struct rte_ipsec_sa_prm * prm,uint64_t * type)162 fill_sa_type(const struct rte_ipsec_sa_prm *prm, uint64_t *type)
163 {
164 uint64_t tp;
165
166 tp = 0;
167
168 if (prm->ipsec_xform.proto == RTE_SECURITY_IPSEC_SA_PROTO_AH)
169 tp |= RTE_IPSEC_SATP_PROTO_AH;
170 else if (prm->ipsec_xform.proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP)
171 tp |= RTE_IPSEC_SATP_PROTO_ESP;
172 else
173 return -EINVAL;
174
175 if (prm->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
176 tp |= RTE_IPSEC_SATP_DIR_OB;
177 else if (prm->ipsec_xform.direction ==
178 RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
179 tp |= RTE_IPSEC_SATP_DIR_IB;
180 else
181 return -EINVAL;
182
183 if (prm->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
184 if (prm->ipsec_xform.tunnel.type ==
185 RTE_SECURITY_IPSEC_TUNNEL_IPV4)
186 tp |= RTE_IPSEC_SATP_MODE_TUNLV4;
187 else if (prm->ipsec_xform.tunnel.type ==
188 RTE_SECURITY_IPSEC_TUNNEL_IPV6)
189 tp |= RTE_IPSEC_SATP_MODE_TUNLV6;
190 else
191 return -EINVAL;
192
193 if (prm->tun.next_proto == IPPROTO_IPIP)
194 tp |= RTE_IPSEC_SATP_IPV4;
195 else if (prm->tun.next_proto == IPPROTO_IPV6)
196 tp |= RTE_IPSEC_SATP_IPV6;
197 else
198 return -EINVAL;
199 } else if (prm->ipsec_xform.mode ==
200 RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) {
201 tp |= RTE_IPSEC_SATP_MODE_TRANS;
202 if (prm->trs.proto == IPPROTO_IPIP)
203 tp |= RTE_IPSEC_SATP_IPV4;
204 else if (prm->trs.proto == IPPROTO_IPV6)
205 tp |= RTE_IPSEC_SATP_IPV6;
206 else
207 return -EINVAL;
208 } else
209 return -EINVAL;
210
211 /* check for ESN flag */
212 if (prm->ipsec_xform.options.esn == 0)
213 tp |= RTE_IPSEC_SATP_ESN_DISABLE;
214 else
215 tp |= RTE_IPSEC_SATP_ESN_ENABLE;
216
217 /* check for ECN flag */
218 if (prm->ipsec_xform.options.ecn == 0)
219 tp |= RTE_IPSEC_SATP_ECN_DISABLE;
220 else
221 tp |= RTE_IPSEC_SATP_ECN_ENABLE;
222
223 /* check for DSCP flag */
224 if (prm->ipsec_xform.options.copy_dscp == 0)
225 tp |= RTE_IPSEC_SATP_DSCP_DISABLE;
226 else
227 tp |= RTE_IPSEC_SATP_DSCP_ENABLE;
228
229 /* interpret flags */
230 if (prm->flags & RTE_IPSEC_SAFLAG_SQN_ATOM)
231 tp |= RTE_IPSEC_SATP_SQN_ATOM;
232 else
233 tp |= RTE_IPSEC_SATP_SQN_RAW;
234
235 *type = tp;
236 return 0;
237 }
238
239 /*
240 * Init ESP inbound specific things.
241 */
242 static void
esp_inb_init(struct rte_ipsec_sa * sa)243 esp_inb_init(struct rte_ipsec_sa *sa)
244 {
245 /* these params may differ with new algorithms support */
246 sa->ctp.cipher.offset = sizeof(struct rte_esp_hdr) + sa->iv_len;
247 sa->ctp.cipher.length = sa->icv_len + sa->ctp.cipher.offset;
248
249 /*
250 * for AEAD and NULL algorithms we can assume that
251 * auth and cipher offsets would be equal.
252 */
253 switch (sa->algo_type) {
254 case ALGO_TYPE_AES_GCM:
255 case ALGO_TYPE_NULL:
256 sa->ctp.auth.raw = sa->ctp.cipher.raw;
257 break;
258 default:
259 sa->ctp.auth.offset = 0;
260 sa->ctp.auth.length = sa->icv_len - sa->sqh_len;
261 sa->cofs.ofs.cipher.tail = sa->sqh_len;
262 break;
263 }
264
265 sa->cofs.ofs.cipher.head = sa->ctp.cipher.offset - sa->ctp.auth.offset;
266 }
267
268 /*
269 * Init ESP inbound tunnel specific things.
270 */
271 static void
esp_inb_tun_init(struct rte_ipsec_sa * sa,const struct rte_ipsec_sa_prm * prm)272 esp_inb_tun_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm)
273 {
274 sa->proto = prm->tun.next_proto;
275 esp_inb_init(sa);
276 }
277
278 /*
279 * Init ESP outbound specific things.
280 */
281 static void
esp_outb_init(struct rte_ipsec_sa * sa,uint32_t hlen)282 esp_outb_init(struct rte_ipsec_sa *sa, uint32_t hlen)
283 {
284 uint8_t algo_type;
285
286 sa->sqn.outb = 1;
287
288 algo_type = sa->algo_type;
289
290 /*
291 * Setup auth and cipher length and offset.
292 * these params may differ with new algorithms support
293 */
294
295 switch (algo_type) {
296 case ALGO_TYPE_AES_GCM:
297 case ALGO_TYPE_AES_CTR:
298 case ALGO_TYPE_NULL:
299 sa->ctp.cipher.offset = hlen + sizeof(struct rte_esp_hdr) +
300 sa->iv_len;
301 sa->ctp.cipher.length = 0;
302 break;
303 case ALGO_TYPE_AES_CBC:
304 case ALGO_TYPE_3DES_CBC:
305 sa->ctp.cipher.offset = hlen + sizeof(struct rte_esp_hdr);
306 sa->ctp.cipher.length = sa->iv_len;
307 break;
308 }
309
310 /*
311 * for AEAD and NULL algorithms we can assume that
312 * auth and cipher offsets would be equal.
313 */
314 switch (algo_type) {
315 case ALGO_TYPE_AES_GCM:
316 case ALGO_TYPE_NULL:
317 sa->ctp.auth.raw = sa->ctp.cipher.raw;
318 break;
319 default:
320 sa->ctp.auth.offset = hlen;
321 sa->ctp.auth.length = sizeof(struct rte_esp_hdr) +
322 sa->iv_len + sa->sqh_len;
323 break;
324 }
325
326 sa->cofs.ofs.cipher.head = sa->ctp.cipher.offset - sa->ctp.auth.offset;
327 sa->cofs.ofs.cipher.tail = (sa->ctp.auth.offset + sa->ctp.auth.length) -
328 (sa->ctp.cipher.offset + sa->ctp.cipher.length);
329 }
330
331 /*
332 * Init ESP outbound tunnel specific things.
333 */
334 static void
esp_outb_tun_init(struct rte_ipsec_sa * sa,const struct rte_ipsec_sa_prm * prm)335 esp_outb_tun_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm)
336 {
337 sa->proto = prm->tun.next_proto;
338 sa->hdr_len = prm->tun.hdr_len;
339 sa->hdr_l3_off = prm->tun.hdr_l3_off;
340
341 /* update l2_len and l3_len fields for outbound mbuf */
342 sa->tx_offload.val = rte_mbuf_tx_offload(sa->hdr_l3_off,
343 sa->hdr_len - sa->hdr_l3_off, 0, 0, 0, 0, 0);
344
345 memcpy(sa->hdr, prm->tun.hdr, sa->hdr_len);
346
347 esp_outb_init(sa, sa->hdr_len);
348 }
349
350 /*
351 * helper function, init SA structure.
352 */
353 static int
esp_sa_init(struct rte_ipsec_sa * sa,const struct rte_ipsec_sa_prm * prm,const struct crypto_xform * cxf)354 esp_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm,
355 const struct crypto_xform *cxf)
356 {
357 static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK |
358 RTE_IPSEC_SATP_MODE_MASK;
359
360 if (prm->ipsec_xform.options.ecn)
361 sa->tos_mask |= RTE_IPV4_HDR_ECN_MASK;
362
363 if (prm->ipsec_xform.options.copy_dscp)
364 sa->tos_mask |= RTE_IPV4_HDR_DSCP_MASK;
365
366 if (cxf->aead != NULL) {
367 switch (cxf->aead->algo) {
368 case RTE_CRYPTO_AEAD_AES_GCM:
369 /* RFC 4106 */
370 sa->aad_len = sizeof(struct aead_gcm_aad);
371 sa->icv_len = cxf->aead->digest_length;
372 sa->iv_ofs = cxf->aead->iv.offset;
373 sa->iv_len = sizeof(uint64_t);
374 sa->pad_align = IPSEC_PAD_AES_GCM;
375 sa->algo_type = ALGO_TYPE_AES_GCM;
376 break;
377 default:
378 return -EINVAL;
379 }
380 } else {
381 sa->icv_len = cxf->auth->digest_length;
382 sa->iv_ofs = cxf->cipher->iv.offset;
383 sa->sqh_len = IS_ESN(sa) ? sizeof(uint32_t) : 0;
384
385 switch (cxf->cipher->algo) {
386 case RTE_CRYPTO_CIPHER_NULL:
387 sa->pad_align = IPSEC_PAD_NULL;
388 sa->iv_len = 0;
389 sa->algo_type = ALGO_TYPE_NULL;
390 break;
391
392 case RTE_CRYPTO_CIPHER_AES_CBC:
393 sa->pad_align = IPSEC_PAD_AES_CBC;
394 sa->iv_len = IPSEC_MAX_IV_SIZE;
395 sa->algo_type = ALGO_TYPE_AES_CBC;
396 break;
397
398 case RTE_CRYPTO_CIPHER_AES_CTR:
399 /* RFC 3686 */
400 sa->pad_align = IPSEC_PAD_AES_CTR;
401 sa->iv_len = IPSEC_AES_CTR_IV_SIZE;
402 sa->algo_type = ALGO_TYPE_AES_CTR;
403 break;
404
405 case RTE_CRYPTO_CIPHER_3DES_CBC:
406 /* RFC 1851 */
407 sa->pad_align = IPSEC_PAD_3DES_CBC;
408 sa->iv_len = IPSEC_3DES_IV_SIZE;
409 sa->algo_type = ALGO_TYPE_3DES_CBC;
410 break;
411
412 default:
413 return -EINVAL;
414 }
415 }
416
417 sa->udata = prm->userdata;
418 sa->spi = rte_cpu_to_be_32(prm->ipsec_xform.spi);
419 sa->salt = prm->ipsec_xform.salt;
420
421 /* preserve all values except l2_len and l3_len */
422 sa->tx_offload.msk =
423 ~rte_mbuf_tx_offload(MBUF_MAX_L2_LEN, MBUF_MAX_L3_LEN,
424 0, 0, 0, 0, 0);
425
426 switch (sa->type & msk) {
427 case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4):
428 case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6):
429 esp_inb_tun_init(sa, prm);
430 break;
431 case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS):
432 esp_inb_init(sa);
433 break;
434 case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4):
435 case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6):
436 esp_outb_tun_init(sa, prm);
437 break;
438 case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS):
439 esp_outb_init(sa, 0);
440 break;
441 }
442
443 return 0;
444 }
445
446 /*
447 * helper function, init SA replay structure.
448 */
449 static void
fill_sa_replay(struct rte_ipsec_sa * sa,uint32_t wnd_sz,uint32_t nb_bucket)450 fill_sa_replay(struct rte_ipsec_sa *sa, uint32_t wnd_sz, uint32_t nb_bucket)
451 {
452 sa->replay.win_sz = wnd_sz;
453 sa->replay.nb_bucket = nb_bucket;
454 sa->replay.bucket_index_mask = nb_bucket - 1;
455 sa->sqn.inb.rsn[0] = (struct replay_sqn *)(sa + 1);
456 if ((sa->type & RTE_IPSEC_SATP_SQN_MASK) == RTE_IPSEC_SATP_SQN_ATOM)
457 sa->sqn.inb.rsn[1] = (struct replay_sqn *)
458 ((uintptr_t)sa->sqn.inb.rsn[0] + rsn_size(nb_bucket));
459 }
460
461 int
rte_ipsec_sa_size(const struct rte_ipsec_sa_prm * prm)462 rte_ipsec_sa_size(const struct rte_ipsec_sa_prm *prm)
463 {
464 uint64_t type;
465 uint32_t nb, wsz;
466 int32_t rc;
467
468 if (prm == NULL)
469 return -EINVAL;
470
471 /* determine SA type */
472 rc = fill_sa_type(prm, &type);
473 if (rc != 0)
474 return rc;
475
476 /* determine required size */
477 wsz = prm->ipsec_xform.replay_win_sz;
478 return ipsec_sa_size(type, &wsz, &nb);
479 }
480
481 int
rte_ipsec_sa_init(struct rte_ipsec_sa * sa,const struct rte_ipsec_sa_prm * prm,uint32_t size)482 rte_ipsec_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm,
483 uint32_t size)
484 {
485 int32_t rc, sz;
486 uint32_t nb, wsz;
487 uint64_t type;
488 struct crypto_xform cxf;
489
490 if (sa == NULL || prm == NULL)
491 return -EINVAL;
492
493 /* determine SA type */
494 rc = fill_sa_type(prm, &type);
495 if (rc != 0)
496 return rc;
497
498 /* determine required size */
499 wsz = prm->ipsec_xform.replay_win_sz;
500 sz = ipsec_sa_size(type, &wsz, &nb);
501 if (sz < 0)
502 return sz;
503 else if (size < (uint32_t)sz)
504 return -ENOSPC;
505
506 /* only esp is supported right now */
507 if (prm->ipsec_xform.proto != RTE_SECURITY_IPSEC_SA_PROTO_ESP)
508 return -EINVAL;
509
510 if (prm->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL &&
511 prm->tun.hdr_len > sizeof(sa->hdr))
512 return -EINVAL;
513
514 rc = fill_crypto_xform(&cxf, type, prm);
515 if (rc != 0)
516 return rc;
517
518 /* initialize SA */
519
520 memset(sa, 0, sz);
521 sa->type = type;
522 sa->size = sz;
523
524 /* check for ESN flag */
525 sa->sqn_mask = (prm->ipsec_xform.options.esn == 0) ?
526 UINT32_MAX : UINT64_MAX;
527
528 rc = esp_sa_init(sa, prm, &cxf);
529 if (rc != 0)
530 rte_ipsec_sa_fini(sa);
531
532 /* fill replay window related fields */
533 if (nb != 0)
534 fill_sa_replay(sa, wsz, nb);
535
536 return sz;
537 }
538
539 /*
540 * setup crypto ops for LOOKASIDE_PROTO type of devices.
541 */
542 static inline void
lksd_proto_cop_prepare(const struct rte_ipsec_session * ss,struct rte_mbuf * mb[],struct rte_crypto_op * cop[],uint16_t num)543 lksd_proto_cop_prepare(const struct rte_ipsec_session *ss,
544 struct rte_mbuf *mb[], struct rte_crypto_op *cop[], uint16_t num)
545 {
546 uint32_t i;
547 struct rte_crypto_sym_op *sop;
548
549 for (i = 0; i != num; i++) {
550 sop = cop[i]->sym;
551 cop[i]->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
552 cop[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
553 cop[i]->sess_type = RTE_CRYPTO_OP_SECURITY_SESSION;
554 sop->m_src = mb[i];
555 __rte_security_attach_session(sop, ss->security.ses);
556 }
557 }
558
559 /*
560 * setup packets and crypto ops for LOOKASIDE_PROTO type of devices.
561 * Note that for LOOKASIDE_PROTO all packet modifications will be
562 * performed by PMD/HW.
563 * SW has only to prepare crypto op.
564 */
565 static uint16_t
lksd_proto_prepare(const struct rte_ipsec_session * ss,struct rte_mbuf * mb[],struct rte_crypto_op * cop[],uint16_t num)566 lksd_proto_prepare(const struct rte_ipsec_session *ss,
567 struct rte_mbuf *mb[], struct rte_crypto_op *cop[], uint16_t num)
568 {
569 lksd_proto_cop_prepare(ss, mb, cop, num);
570 return num;
571 }
572
573 /*
574 * simplest pkt process routine:
575 * all actual processing is already done by HW/PMD,
576 * just check mbuf ol_flags.
577 * used for:
578 * - inbound for RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL
579 * - inbound/outbound for RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL
580 * - outbound for RTE_SECURITY_ACTION_TYPE_NONE when ESN is disabled
581 */
582 uint16_t
pkt_flag_process(const struct rte_ipsec_session * ss,struct rte_mbuf * mb[],uint16_t num)583 pkt_flag_process(const struct rte_ipsec_session *ss,
584 struct rte_mbuf *mb[], uint16_t num)
585 {
586 uint32_t i, k;
587 uint32_t dr[num];
588
589 RTE_SET_USED(ss);
590
591 k = 0;
592 for (i = 0; i != num; i++) {
593 if ((mb[i]->ol_flags & PKT_RX_SEC_OFFLOAD_FAILED) == 0)
594 k++;
595 else
596 dr[i - k] = i;
597 }
598
599 /* handle unprocessed mbufs */
600 if (k != num) {
601 rte_errno = EBADMSG;
602 if (k != 0)
603 move_bad_mbufs(mb, dr, num, num - k);
604 }
605
606 return k;
607 }
608
609 /*
610 * Select packet processing function for session on LOOKASIDE_NONE
611 * type of device.
612 */
613 static int
lksd_none_pkt_func_select(const struct rte_ipsec_sa * sa,struct rte_ipsec_sa_pkt_func * pf)614 lksd_none_pkt_func_select(const struct rte_ipsec_sa *sa,
615 struct rte_ipsec_sa_pkt_func *pf)
616 {
617 int32_t rc;
618
619 static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK |
620 RTE_IPSEC_SATP_MODE_MASK;
621
622 rc = 0;
623 switch (sa->type & msk) {
624 case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4):
625 case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6):
626 pf->prepare.async = esp_inb_pkt_prepare;
627 pf->process = esp_inb_tun_pkt_process;
628 break;
629 case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS):
630 pf->prepare.async = esp_inb_pkt_prepare;
631 pf->process = esp_inb_trs_pkt_process;
632 break;
633 case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4):
634 case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6):
635 pf->prepare.async = esp_outb_tun_prepare;
636 pf->process = (sa->sqh_len != 0) ?
637 esp_outb_sqh_process : pkt_flag_process;
638 break;
639 case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS):
640 pf->prepare.async = esp_outb_trs_prepare;
641 pf->process = (sa->sqh_len != 0) ?
642 esp_outb_sqh_process : pkt_flag_process;
643 break;
644 default:
645 rc = -ENOTSUP;
646 }
647
648 return rc;
649 }
650
651 static int
cpu_crypto_pkt_func_select(const struct rte_ipsec_sa * sa,struct rte_ipsec_sa_pkt_func * pf)652 cpu_crypto_pkt_func_select(const struct rte_ipsec_sa *sa,
653 struct rte_ipsec_sa_pkt_func *pf)
654 {
655 int32_t rc;
656
657 static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK |
658 RTE_IPSEC_SATP_MODE_MASK;
659
660 rc = 0;
661 switch (sa->type & msk) {
662 case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4):
663 case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6):
664 pf->prepare.sync = cpu_inb_pkt_prepare;
665 pf->process = esp_inb_tun_pkt_process;
666 break;
667 case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS):
668 pf->prepare.sync = cpu_inb_pkt_prepare;
669 pf->process = esp_inb_trs_pkt_process;
670 break;
671 case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4):
672 case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6):
673 pf->prepare.sync = cpu_outb_tun_pkt_prepare;
674 pf->process = (sa->sqh_len != 0) ?
675 esp_outb_sqh_process : pkt_flag_process;
676 break;
677 case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS):
678 pf->prepare.sync = cpu_outb_trs_pkt_prepare;
679 pf->process = (sa->sqh_len != 0) ?
680 esp_outb_sqh_process : pkt_flag_process;
681 break;
682 default:
683 rc = -ENOTSUP;
684 }
685
686 return rc;
687 }
688
689 /*
690 * Select packet processing function for session on INLINE_CRYPTO
691 * type of device.
692 */
693 static int
inline_crypto_pkt_func_select(const struct rte_ipsec_sa * sa,struct rte_ipsec_sa_pkt_func * pf)694 inline_crypto_pkt_func_select(const struct rte_ipsec_sa *sa,
695 struct rte_ipsec_sa_pkt_func *pf)
696 {
697 int32_t rc;
698
699 static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK |
700 RTE_IPSEC_SATP_MODE_MASK;
701
702 rc = 0;
703 switch (sa->type & msk) {
704 case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4):
705 case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6):
706 pf->process = inline_inb_tun_pkt_process;
707 break;
708 case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS):
709 pf->process = inline_inb_trs_pkt_process;
710 break;
711 case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4):
712 case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6):
713 pf->process = inline_outb_tun_pkt_process;
714 break;
715 case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS):
716 pf->process = inline_outb_trs_pkt_process;
717 break;
718 default:
719 rc = -ENOTSUP;
720 }
721
722 return rc;
723 }
724
725 /*
726 * Select packet processing function for given session based on SA parameters
727 * and type of associated with the session device.
728 */
729 int
ipsec_sa_pkt_func_select(const struct rte_ipsec_session * ss,const struct rte_ipsec_sa * sa,struct rte_ipsec_sa_pkt_func * pf)730 ipsec_sa_pkt_func_select(const struct rte_ipsec_session *ss,
731 const struct rte_ipsec_sa *sa, struct rte_ipsec_sa_pkt_func *pf)
732 {
733 int32_t rc;
734
735 rc = 0;
736 pf[0] = (struct rte_ipsec_sa_pkt_func) { {NULL}, NULL };
737
738 switch (ss->type) {
739 case RTE_SECURITY_ACTION_TYPE_NONE:
740 rc = lksd_none_pkt_func_select(sa, pf);
741 break;
742 case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
743 rc = inline_crypto_pkt_func_select(sa, pf);
744 break;
745 case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:
746 if ((sa->type & RTE_IPSEC_SATP_DIR_MASK) ==
747 RTE_IPSEC_SATP_DIR_IB)
748 pf->process = pkt_flag_process;
749 else
750 pf->process = inline_proto_outb_pkt_process;
751 break;
752 case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL:
753 pf->prepare.async = lksd_proto_prepare;
754 pf->process = pkt_flag_process;
755 break;
756 case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO:
757 rc = cpu_crypto_pkt_func_select(sa, pf);
758 break;
759 default:
760 rc = -ENOTSUP;
761 }
762
763 return rc;
764 }
765