ipsec: change the way unprocessed mbufs are accounted
[dpdk.git] / lib / librte_ipsec / sa.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 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 "pad.h"
16
17 #define MBUF_MAX_L2_LEN         RTE_LEN2MASK(RTE_MBUF_L2_LEN_BITS, uint64_t)
18 #define MBUF_MAX_L3_LEN         RTE_LEN2MASK(RTE_MBUF_L3_LEN_BITS, uint64_t)
19
20 /* some helper structures */
21 struct crypto_xform {
22         struct rte_crypto_auth_xform *auth;
23         struct rte_crypto_cipher_xform *cipher;
24         struct rte_crypto_aead_xform *aead;
25 };
26
27 /*
28  * helper routine, fills internal crypto_xform structure.
29  */
30 static int
31 fill_crypto_xform(struct crypto_xform *xform, uint64_t type,
32         const struct rte_ipsec_sa_prm *prm)
33 {
34         struct rte_crypto_sym_xform *xf, *xfn;
35
36         memset(xform, 0, sizeof(*xform));
37
38         xf = prm->crypto_xform;
39         if (xf == NULL)
40                 return -EINVAL;
41
42         xfn = xf->next;
43
44         /* for AEAD just one xform required */
45         if (xf->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
46                 if (xfn != NULL)
47                         return -EINVAL;
48                 xform->aead = &xf->aead;
49         /*
50          * CIPHER+AUTH xforms are expected in strict order,
51          * depending on SA direction:
52          * inbound: AUTH+CIPHER
53          * outbound: CIPHER+AUTH
54          */
55         } else if ((type & RTE_IPSEC_SATP_DIR_MASK) == RTE_IPSEC_SATP_DIR_IB) {
56
57                 /* wrong order or no cipher */
58                 if (xfn == NULL || xf->type != RTE_CRYPTO_SYM_XFORM_AUTH ||
59                                 xfn->type != RTE_CRYPTO_SYM_XFORM_CIPHER)
60                         return -EINVAL;
61
62                 xform->auth = &xf->auth;
63                 xform->cipher = &xfn->cipher;
64
65         } else {
66
67                 /* wrong order or no auth */
68                 if (xfn == NULL || xf->type != RTE_CRYPTO_SYM_XFORM_CIPHER ||
69                                 xfn->type != RTE_CRYPTO_SYM_XFORM_AUTH)
70                         return -EINVAL;
71
72                 xform->cipher = &xf->cipher;
73                 xform->auth = &xfn->auth;
74         }
75
76         return 0;
77 }
78
79 uint64_t __rte_experimental
80 rte_ipsec_sa_type(const struct rte_ipsec_sa *sa)
81 {
82         return sa->type;
83 }
84
85 static int32_t
86 ipsec_sa_size(uint64_t type, uint32_t *wnd_sz, uint32_t *nb_bucket)
87 {
88         uint32_t n, sz, wsz;
89
90         wsz = *wnd_sz;
91         n = 0;
92
93         if ((type & RTE_IPSEC_SATP_DIR_MASK) == RTE_IPSEC_SATP_DIR_IB) {
94
95                 /*
96                  * RFC 4303 recommends 64 as minimum window size.
97                  * there is no point to use ESN mode without SQN window,
98                  * so make sure we have at least 64 window when ESN is enalbed.
99                  */
100                 wsz = ((type & RTE_IPSEC_SATP_ESN_MASK) ==
101                         RTE_IPSEC_SATP_ESN_DISABLE) ?
102                         wsz : RTE_MAX(wsz, (uint32_t)WINDOW_BUCKET_SIZE);
103                 if (wsz != 0)
104                         n = replay_num_bucket(wsz);
105         }
106
107         if (n > WINDOW_BUCKET_MAX)
108                 return -EINVAL;
109
110         *wnd_sz = wsz;
111         *nb_bucket = n;
112
113         sz = rsn_size(n);
114         if ((type & RTE_IPSEC_SATP_SQN_MASK) == RTE_IPSEC_SATP_SQN_ATOM)
115                 sz *= REPLAY_SQN_NUM;
116
117         sz += sizeof(struct rte_ipsec_sa);
118         return sz;
119 }
120
121 void __rte_experimental
122 rte_ipsec_sa_fini(struct rte_ipsec_sa *sa)
123 {
124         memset(sa, 0, sa->size);
125 }
126
127 /*
128  * Determine expected SA type based on input parameters.
129  */
130 static int
131 fill_sa_type(const struct rte_ipsec_sa_prm *prm, uint64_t *type)
132 {
133         uint64_t tp;
134
135         tp = 0;
136
137         if (prm->ipsec_xform.proto == RTE_SECURITY_IPSEC_SA_PROTO_AH)
138                 tp |= RTE_IPSEC_SATP_PROTO_AH;
139         else if (prm->ipsec_xform.proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP)
140                 tp |= RTE_IPSEC_SATP_PROTO_ESP;
141         else
142                 return -EINVAL;
143
144         if (prm->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
145                 tp |= RTE_IPSEC_SATP_DIR_OB;
146         else if (prm->ipsec_xform.direction ==
147                         RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
148                 tp |= RTE_IPSEC_SATP_DIR_IB;
149         else
150                 return -EINVAL;
151
152         if (prm->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
153                 if (prm->ipsec_xform.tunnel.type ==
154                                 RTE_SECURITY_IPSEC_TUNNEL_IPV4)
155                         tp |= RTE_IPSEC_SATP_MODE_TUNLV4;
156                 else if (prm->ipsec_xform.tunnel.type ==
157                                 RTE_SECURITY_IPSEC_TUNNEL_IPV6)
158                         tp |= RTE_IPSEC_SATP_MODE_TUNLV6;
159                 else
160                         return -EINVAL;
161
162                 if (prm->tun.next_proto == IPPROTO_IPIP)
163                         tp |= RTE_IPSEC_SATP_IPV4;
164                 else if (prm->tun.next_proto == IPPROTO_IPV6)
165                         tp |= RTE_IPSEC_SATP_IPV6;
166                 else
167                         return -EINVAL;
168         } else if (prm->ipsec_xform.mode ==
169                         RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) {
170                 tp |= RTE_IPSEC_SATP_MODE_TRANS;
171                 if (prm->trs.proto == IPPROTO_IPIP)
172                         tp |= RTE_IPSEC_SATP_IPV4;
173                 else if (prm->trs.proto == IPPROTO_IPV6)
174                         tp |= RTE_IPSEC_SATP_IPV6;
175                 else
176                         return -EINVAL;
177         } else
178                 return -EINVAL;
179
180         /* check for ESN flag */
181         if (prm->ipsec_xform.options.esn == 0)
182                 tp |= RTE_IPSEC_SATP_ESN_DISABLE;
183         else
184                 tp |= RTE_IPSEC_SATP_ESN_ENABLE;
185
186         /* interpret flags */
187         if (prm->flags & RTE_IPSEC_SAFLAG_SQN_ATOM)
188                 tp |= RTE_IPSEC_SATP_SQN_ATOM;
189         else
190                 tp |= RTE_IPSEC_SATP_SQN_RAW;
191
192         *type = tp;
193         return 0;
194 }
195
196 /*
197  * Init ESP inbound specific things.
198  */
199 static void
200 esp_inb_init(struct rte_ipsec_sa *sa)
201 {
202         /* these params may differ with new algorithms support */
203         sa->ctp.auth.offset = 0;
204         sa->ctp.auth.length = sa->icv_len - sa->sqh_len;
205         sa->ctp.cipher.offset = sizeof(struct esp_hdr) + sa->iv_len;
206         sa->ctp.cipher.length = sa->icv_len + sa->ctp.cipher.offset;
207 }
208
209 /*
210  * Init ESP inbound tunnel specific things.
211  */
212 static void
213 esp_inb_tun_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm)
214 {
215         sa->proto = prm->tun.next_proto;
216         esp_inb_init(sa);
217 }
218
219 /*
220  * Init ESP outbound specific things.
221  */
222 static void
223 esp_outb_init(struct rte_ipsec_sa *sa, uint32_t hlen)
224 {
225         uint8_t algo_type;
226
227         sa->sqn.outb.raw = 1;
228
229         /* these params may differ with new algorithms support */
230         sa->ctp.auth.offset = hlen;
231         sa->ctp.auth.length = sizeof(struct esp_hdr) + sa->iv_len + sa->sqh_len;
232
233         algo_type = sa->algo_type;
234
235         switch (algo_type) {
236         case ALGO_TYPE_AES_GCM:
237         case ALGO_TYPE_AES_CTR:
238         case ALGO_TYPE_NULL:
239                 sa->ctp.cipher.offset = hlen + sizeof(struct esp_hdr) +
240                         sa->iv_len;
241                 sa->ctp.cipher.length = 0;
242                 break;
243         case ALGO_TYPE_AES_CBC:
244         case ALGO_TYPE_3DES_CBC:
245                 sa->ctp.cipher.offset = sa->hdr_len + sizeof(struct esp_hdr);
246                 sa->ctp.cipher.length = sa->iv_len;
247                 break;
248         }
249 }
250
251 /*
252  * Init ESP outbound tunnel specific things.
253  */
254 static void
255 esp_outb_tun_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm)
256 {
257         sa->proto = prm->tun.next_proto;
258         sa->hdr_len = prm->tun.hdr_len;
259         sa->hdr_l3_off = prm->tun.hdr_l3_off;
260
261         /* update l2_len and l3_len fields for outbound mbuf */
262         sa->tx_offload.val = rte_mbuf_tx_offload(sa->hdr_l3_off,
263                 sa->hdr_len - sa->hdr_l3_off, 0, 0, 0, 0, 0);
264
265         memcpy(sa->hdr, prm->tun.hdr, sa->hdr_len);
266
267         esp_outb_init(sa, sa->hdr_len);
268 }
269
270 /*
271  * helper function, init SA structure.
272  */
273 static int
274 esp_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm,
275         const struct crypto_xform *cxf)
276 {
277         static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK |
278                                 RTE_IPSEC_SATP_MODE_MASK;
279
280         if (cxf->aead != NULL) {
281                 switch (cxf->aead->algo) {
282                 case RTE_CRYPTO_AEAD_AES_GCM:
283                         /* RFC 4106 */
284                         sa->aad_len = sizeof(struct aead_gcm_aad);
285                         sa->icv_len = cxf->aead->digest_length;
286                         sa->iv_ofs = cxf->aead->iv.offset;
287                         sa->iv_len = sizeof(uint64_t);
288                         sa->pad_align = IPSEC_PAD_AES_GCM;
289                         sa->algo_type = ALGO_TYPE_AES_GCM;
290                         break;
291                 default:
292                         return -EINVAL;
293                 }
294         } else {
295                 sa->icv_len = cxf->auth->digest_length;
296                 sa->iv_ofs = cxf->cipher->iv.offset;
297                 sa->sqh_len = IS_ESN(sa) ? sizeof(uint32_t) : 0;
298
299                 switch (cxf->cipher->algo) {
300                 case RTE_CRYPTO_CIPHER_NULL:
301                         sa->pad_align = IPSEC_PAD_NULL;
302                         sa->iv_len = 0;
303                         sa->algo_type = ALGO_TYPE_NULL;
304                         break;
305
306                 case RTE_CRYPTO_CIPHER_AES_CBC:
307                         sa->pad_align = IPSEC_PAD_AES_CBC;
308                         sa->iv_len = IPSEC_MAX_IV_SIZE;
309                         sa->algo_type = ALGO_TYPE_AES_CBC;
310                         break;
311
312                 case RTE_CRYPTO_CIPHER_AES_CTR:
313                         /* RFC 3686 */
314                         sa->pad_align = IPSEC_PAD_AES_CTR;
315                         sa->iv_len = IPSEC_AES_CTR_IV_SIZE;
316                         sa->algo_type = ALGO_TYPE_AES_CTR;
317                         break;
318
319                 case RTE_CRYPTO_CIPHER_3DES_CBC:
320                         /* RFC 1851 */
321                         sa->pad_align = IPSEC_PAD_3DES_CBC;
322                         sa->iv_len = IPSEC_3DES_IV_SIZE;
323                         sa->algo_type = ALGO_TYPE_3DES_CBC;
324                         break;
325
326                 default:
327                         return -EINVAL;
328                 }
329         }
330
331         sa->udata = prm->userdata;
332         sa->spi = rte_cpu_to_be_32(prm->ipsec_xform.spi);
333         sa->salt = prm->ipsec_xform.salt;
334
335         /* preserve all values except l2_len and l3_len */
336         sa->tx_offload.msk =
337                 ~rte_mbuf_tx_offload(MBUF_MAX_L2_LEN, MBUF_MAX_L3_LEN,
338                                 0, 0, 0, 0, 0);
339
340         switch (sa->type & msk) {
341         case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4):
342         case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6):
343                 esp_inb_tun_init(sa, prm);
344                 break;
345         case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS):
346                 esp_inb_init(sa);
347                 break;
348         case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4):
349         case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6):
350                 esp_outb_tun_init(sa, prm);
351                 break;
352         case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS):
353                 esp_outb_init(sa, 0);
354                 break;
355         }
356
357         return 0;
358 }
359
360 /*
361  * helper function, init SA replay structure.
362  */
363 static void
364 fill_sa_replay(struct rte_ipsec_sa *sa, uint32_t wnd_sz, uint32_t nb_bucket)
365 {
366         sa->replay.win_sz = wnd_sz;
367         sa->replay.nb_bucket = nb_bucket;
368         sa->replay.bucket_index_mask = nb_bucket - 1;
369         sa->sqn.inb.rsn[0] = (struct replay_sqn *)(sa + 1);
370         if ((sa->type & RTE_IPSEC_SATP_SQN_MASK) == RTE_IPSEC_SATP_SQN_ATOM)
371                 sa->sqn.inb.rsn[1] = (struct replay_sqn *)
372                         ((uintptr_t)sa->sqn.inb.rsn[0] + rsn_size(nb_bucket));
373 }
374
375 int __rte_experimental
376 rte_ipsec_sa_size(const struct rte_ipsec_sa_prm *prm)
377 {
378         uint64_t type;
379         uint32_t nb, wsz;
380         int32_t rc;
381
382         if (prm == NULL)
383                 return -EINVAL;
384
385         /* determine SA type */
386         rc = fill_sa_type(prm, &type);
387         if (rc != 0)
388                 return rc;
389
390         /* determine required size */
391         wsz = prm->replay_win_sz;
392         return ipsec_sa_size(type, &wsz, &nb);
393 }
394
395 int __rte_experimental
396 rte_ipsec_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm,
397         uint32_t size)
398 {
399         int32_t rc, sz;
400         uint32_t nb, wsz;
401         uint64_t type;
402         struct crypto_xform cxf;
403
404         if (sa == NULL || prm == NULL)
405                 return -EINVAL;
406
407         /* determine SA type */
408         rc = fill_sa_type(prm, &type);
409         if (rc != 0)
410                 return rc;
411
412         /* determine required size */
413         wsz = prm->replay_win_sz;
414         sz = ipsec_sa_size(type, &wsz, &nb);
415         if (sz < 0)
416                 return sz;
417         else if (size < (uint32_t)sz)
418                 return -ENOSPC;
419
420         /* only esp is supported right now */
421         if (prm->ipsec_xform.proto != RTE_SECURITY_IPSEC_SA_PROTO_ESP)
422                 return -EINVAL;
423
424         if (prm->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL &&
425                         prm->tun.hdr_len > sizeof(sa->hdr))
426                 return -EINVAL;
427
428         rc = fill_crypto_xform(&cxf, type, prm);
429         if (rc != 0)
430                 return rc;
431
432         /* initialize SA */
433
434         memset(sa, 0, sz);
435         sa->type = type;
436         sa->size = sz;
437
438         /* check for ESN flag */
439         sa->sqn_mask = (prm->ipsec_xform.options.esn == 0) ?
440                 UINT32_MAX : UINT64_MAX;
441
442         rc = esp_sa_init(sa, prm, &cxf);
443         if (rc != 0)
444                 rte_ipsec_sa_fini(sa);
445
446         /* fill replay window related fields */
447         if (nb != 0)
448                 fill_sa_replay(sa, wsz, nb);
449
450         return sz;
451 }
452
453 /*
454  * Move bad (unprocessed) mbufs beyond the good (processed) ones.
455  * bad_idx[] contains the indexes of bad mbufs inside the mb[].
456  */
457 static inline void
458 move_bad_mbufs(struct rte_mbuf *mb[], const uint32_t bad_idx[], uint32_t nb_mb,
459         uint32_t nb_bad)
460 {
461         uint32_t i, j, k;
462         struct rte_mbuf *drb[nb_bad];
463
464         j = 0;
465         k = 0;
466
467         /* copy bad ones into a temp place */
468         for (i = 0; i != nb_mb; i++) {
469                 if (j != nb_bad && i == bad_idx[j])
470                         drb[j++] = mb[i];
471                 else
472                         mb[k++] = mb[i];
473         }
474
475         /* copy bad ones after the good ones */
476         for (i = 0; i != nb_bad; i++)
477                 mb[k + i] = drb[i];
478 }
479
480 /*
481  * setup crypto ops for LOOKASIDE_NONE (pure crypto) type of devices.
482  */
483 static inline void
484 lksd_none_cop_prepare(struct rte_crypto_op *cop,
485         struct rte_cryptodev_sym_session *cs, struct rte_mbuf *mb)
486 {
487         struct rte_crypto_sym_op *sop;
488
489         sop = cop->sym;
490         cop->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
491         cop->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
492         cop->sess_type = RTE_CRYPTO_OP_WITH_SESSION;
493         sop->m_src = mb;
494         __rte_crypto_sym_op_attach_sym_session(sop, cs);
495 }
496
497 /*
498  * setup crypto op and crypto sym op for ESP outbound packet.
499  */
500 static inline void
501 esp_outb_cop_prepare(struct rte_crypto_op *cop,
502         const struct rte_ipsec_sa *sa, const uint64_t ivp[IPSEC_MAX_IV_QWORD],
503         const union sym_op_data *icv, uint32_t hlen, uint32_t plen)
504 {
505         struct rte_crypto_sym_op *sop;
506         struct aead_gcm_iv *gcm;
507         struct aesctr_cnt_blk *ctr;
508         uint8_t algo_type = sa->algo_type;
509
510         /* fill sym op fields */
511         sop = cop->sym;
512
513         switch (algo_type) {
514         case ALGO_TYPE_AES_CBC:
515                 /* Cipher-Auth (AES-CBC *) case */
516         case ALGO_TYPE_3DES_CBC:
517                 /* Cipher-Auth (3DES-CBC *) case */
518         case ALGO_TYPE_NULL:
519                 /* NULL case */
520                 sop->cipher.data.offset = sa->ctp.cipher.offset + hlen;
521                 sop->cipher.data.length = sa->ctp.cipher.length + plen;
522                 sop->auth.data.offset = sa->ctp.auth.offset + hlen;
523                 sop->auth.data.length = sa->ctp.auth.length + plen;
524                 sop->auth.digest.data = icv->va;
525                 sop->auth.digest.phys_addr = icv->pa;
526                 break;
527         case ALGO_TYPE_AES_GCM:
528                 /* AEAD (AES_GCM) case */
529                 sop->aead.data.offset = sa->ctp.cipher.offset + hlen;
530                 sop->aead.data.length = sa->ctp.cipher.length + plen;
531                 sop->aead.digest.data = icv->va;
532                 sop->aead.digest.phys_addr = icv->pa;
533                 sop->aead.aad.data = icv->va + sa->icv_len;
534                 sop->aead.aad.phys_addr = icv->pa + sa->icv_len;
535
536                 /* fill AAD IV (located inside crypto op) */
537                 gcm = rte_crypto_op_ctod_offset(cop, struct aead_gcm_iv *,
538                         sa->iv_ofs);
539                 aead_gcm_iv_fill(gcm, ivp[0], sa->salt);
540                 break;
541         case ALGO_TYPE_AES_CTR:
542                 /* Cipher-Auth (AES-CTR *) case */
543                 sop->cipher.data.offset = sa->ctp.cipher.offset + hlen;
544                 sop->cipher.data.length = sa->ctp.cipher.length + plen;
545                 sop->auth.data.offset = sa->ctp.auth.offset + hlen;
546                 sop->auth.data.length = sa->ctp.auth.length + plen;
547                 sop->auth.digest.data = icv->va;
548                 sop->auth.digest.phys_addr = icv->pa;
549
550                 ctr = rte_crypto_op_ctod_offset(cop, struct aesctr_cnt_blk *,
551                         sa->iv_ofs);
552                 aes_ctr_cnt_blk_fill(ctr, ivp[0], sa->salt);
553                 break;
554         default:
555                 break;
556         }
557 }
558
559 /*
560  * setup/update packet data and metadata for ESP outbound tunnel case.
561  */
562 static inline int32_t
563 esp_outb_tun_pkt_prepare(struct rte_ipsec_sa *sa, rte_be64_t sqc,
564         const uint64_t ivp[IPSEC_MAX_IV_QWORD], struct rte_mbuf *mb,
565         union sym_op_data *icv)
566 {
567         uint32_t clen, hlen, l2len, pdlen, pdofs, plen, tlen;
568         struct rte_mbuf *ml;
569         struct esp_hdr *esph;
570         struct esp_tail *espt;
571         char *ph, *pt;
572         uint64_t *iv;
573
574         /* calculate extra header space required */
575         hlen = sa->hdr_len + sa->iv_len + sizeof(*esph);
576
577         /* size of ipsec protected data */
578         l2len = mb->l2_len;
579         plen = mb->pkt_len - l2len;
580
581         /* number of bytes to encrypt */
582         clen = plen + sizeof(*espt);
583         clen = RTE_ALIGN_CEIL(clen, sa->pad_align);
584
585         /* pad length + esp tail */
586         pdlen = clen - plen;
587         tlen = pdlen + sa->icv_len;
588
589         /* do append and prepend */
590         ml = rte_pktmbuf_lastseg(mb);
591         if (tlen + sa->sqh_len + sa->aad_len > rte_pktmbuf_tailroom(ml))
592                 return -ENOSPC;
593
594         /* prepend header */
595         ph = rte_pktmbuf_prepend(mb, hlen - l2len);
596         if (ph == NULL)
597                 return -ENOSPC;
598
599         /* append tail */
600         pdofs = ml->data_len;
601         ml->data_len += tlen;
602         mb->pkt_len += tlen;
603         pt = rte_pktmbuf_mtod_offset(ml, typeof(pt), pdofs);
604
605         /* update pkt l2/l3 len */
606         mb->tx_offload = (mb->tx_offload & sa->tx_offload.msk) |
607                 sa->tx_offload.val;
608
609         /* copy tunnel pkt header */
610         rte_memcpy(ph, sa->hdr, sa->hdr_len);
611
612         /* update original and new ip header fields */
613         update_tun_l3hdr(sa, ph + sa->hdr_l3_off, mb->pkt_len, sa->hdr_l3_off,
614                         sqn_low16(sqc));
615
616         /* update spi, seqn and iv */
617         esph = (struct esp_hdr *)(ph + sa->hdr_len);
618         iv = (uint64_t *)(esph + 1);
619         copy_iv(iv, ivp, sa->iv_len);
620
621         esph->spi = sa->spi;
622         esph->seq = sqn_low32(sqc);
623
624         /* offset for ICV */
625         pdofs += pdlen + sa->sqh_len;
626
627         /* pad length */
628         pdlen -= sizeof(*espt);
629
630         /* copy padding data */
631         rte_memcpy(pt, esp_pad_bytes, pdlen);
632
633         /* update esp trailer */
634         espt = (struct esp_tail *)(pt + pdlen);
635         espt->pad_len = pdlen;
636         espt->next_proto = sa->proto;
637
638         icv->va = rte_pktmbuf_mtod_offset(ml, void *, pdofs);
639         icv->pa = rte_pktmbuf_iova_offset(ml, pdofs);
640
641         return clen;
642 }
643
644 /*
645  * for pure cryptodev (lookaside none) depending on SA settings,
646  * we might have to write some extra data to the packet.
647  */
648 static inline void
649 outb_pkt_xprepare(const struct rte_ipsec_sa *sa, rte_be64_t sqc,
650         const union sym_op_data *icv)
651 {
652         uint32_t *psqh;
653         struct aead_gcm_aad *aad;
654         uint8_t algo_type = sa->algo_type;
655
656         /* insert SQN.hi between ESP trailer and ICV */
657         if (sa->sqh_len != 0) {
658                 psqh = (uint32_t *)(icv->va - sa->sqh_len);
659                 psqh[0] = sqn_hi32(sqc);
660         }
661
662         /*
663          * fill IV and AAD fields, if any (aad fields are placed after icv),
664          * right now we support only one AEAD algorithm: AES-GCM .
665          */
666         if (algo_type == ALGO_TYPE_AES_GCM) {
667                 aad = (struct aead_gcm_aad *)(icv->va + sa->icv_len);
668                 aead_gcm_aad_fill(aad, sa->spi, sqc, IS_ESN(sa));
669         }
670 }
671
672 /*
673  * setup/update packets and crypto ops for ESP outbound tunnel case.
674  */
675 static uint16_t
676 outb_tun_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
677         struct rte_crypto_op *cop[], uint16_t num)
678 {
679         int32_t rc;
680         uint32_t i, k, n;
681         uint64_t sqn;
682         rte_be64_t sqc;
683         struct rte_ipsec_sa *sa;
684         struct rte_cryptodev_sym_session *cs;
685         union sym_op_data icv;
686         uint64_t iv[IPSEC_MAX_IV_QWORD];
687         uint32_t dr[num];
688
689         sa = ss->sa;
690         cs = ss->crypto.ses;
691
692         n = num;
693         sqn = esn_outb_update_sqn(sa, &n);
694         if (n != num)
695                 rte_errno = EOVERFLOW;
696
697         k = 0;
698         for (i = 0; i != n; i++) {
699
700                 sqc = rte_cpu_to_be_64(sqn + i);
701                 gen_iv(iv, sqc);
702
703                 /* try to update the packet itself */
704                 rc = esp_outb_tun_pkt_prepare(sa, sqc, iv, mb[i], &icv);
705
706                 /* success, setup crypto op */
707                 if (rc >= 0) {
708                         outb_pkt_xprepare(sa, sqc, &icv);
709                         lksd_none_cop_prepare(cop[k], cs, mb[i]);
710                         esp_outb_cop_prepare(cop[k], sa, iv, &icv, 0, rc);
711                         k++;
712                 /* failure, put packet into the death-row */
713                 } else {
714                         dr[i - k] = i;
715                         rte_errno = -rc;
716                 }
717         }
718
719          /* copy not prepared mbufs beyond good ones */
720         if (k != n && k != 0)
721                 move_bad_mbufs(mb, dr, n, n - k);
722
723         return k;
724 }
725
726 /*
727  * setup/update packet data and metadata for ESP outbound transport case.
728  */
729 static inline int32_t
730 esp_outb_trs_pkt_prepare(struct rte_ipsec_sa *sa, rte_be64_t sqc,
731         const uint64_t ivp[IPSEC_MAX_IV_QWORD], struct rte_mbuf *mb,
732         uint32_t l2len, uint32_t l3len, union sym_op_data *icv)
733 {
734         uint8_t np;
735         uint32_t clen, hlen, pdlen, pdofs, plen, tlen, uhlen;
736         struct rte_mbuf *ml;
737         struct esp_hdr *esph;
738         struct esp_tail *espt;
739         char *ph, *pt;
740         uint64_t *iv;
741
742         uhlen = l2len + l3len;
743         plen = mb->pkt_len - uhlen;
744
745         /* calculate extra header space required */
746         hlen = sa->iv_len + sizeof(*esph);
747
748         /* number of bytes to encrypt */
749         clen = plen + sizeof(*espt);
750         clen = RTE_ALIGN_CEIL(clen, sa->pad_align);
751
752         /* pad length + esp tail */
753         pdlen = clen - plen;
754         tlen = pdlen + sa->icv_len;
755
756         /* do append and insert */
757         ml = rte_pktmbuf_lastseg(mb);
758         if (tlen + sa->sqh_len + sa->aad_len > rte_pktmbuf_tailroom(ml))
759                 return -ENOSPC;
760
761         /* prepend space for ESP header */
762         ph = rte_pktmbuf_prepend(mb, hlen);
763         if (ph == NULL)
764                 return -ENOSPC;
765
766         /* append tail */
767         pdofs = ml->data_len;
768         ml->data_len += tlen;
769         mb->pkt_len += tlen;
770         pt = rte_pktmbuf_mtod_offset(ml, typeof(pt), pdofs);
771
772         /* shift L2/L3 headers */
773         insert_esph(ph, ph + hlen, uhlen);
774
775         /* update ip  header fields */
776         np = update_trs_l3hdr(sa, ph + l2len, mb->pkt_len, l2len, l3len,
777                         IPPROTO_ESP);
778
779         /* update spi, seqn and iv */
780         esph = (struct esp_hdr *)(ph + uhlen);
781         iv = (uint64_t *)(esph + 1);
782         copy_iv(iv, ivp, sa->iv_len);
783
784         esph->spi = sa->spi;
785         esph->seq = sqn_low32(sqc);
786
787         /* offset for ICV */
788         pdofs += pdlen + sa->sqh_len;
789
790         /* pad length */
791         pdlen -= sizeof(*espt);
792
793         /* copy padding data */
794         rte_memcpy(pt, esp_pad_bytes, pdlen);
795
796         /* update esp trailer */
797         espt = (struct esp_tail *)(pt + pdlen);
798         espt->pad_len = pdlen;
799         espt->next_proto = np;
800
801         icv->va = rte_pktmbuf_mtod_offset(ml, void *, pdofs);
802         icv->pa = rte_pktmbuf_iova_offset(ml, pdofs);
803
804         return clen;
805 }
806
807 /*
808  * setup/update packets and crypto ops for ESP outbound transport case.
809  */
810 static uint16_t
811 outb_trs_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
812         struct rte_crypto_op *cop[], uint16_t num)
813 {
814         int32_t rc;
815         uint32_t i, k, n, l2, l3;
816         uint64_t sqn;
817         rte_be64_t sqc;
818         struct rte_ipsec_sa *sa;
819         struct rte_cryptodev_sym_session *cs;
820         union sym_op_data icv;
821         uint64_t iv[IPSEC_MAX_IV_QWORD];
822         uint32_t dr[num];
823
824         sa = ss->sa;
825         cs = ss->crypto.ses;
826
827         n = num;
828         sqn = esn_outb_update_sqn(sa, &n);
829         if (n != num)
830                 rte_errno = EOVERFLOW;
831
832         k = 0;
833         for (i = 0; i != n; i++) {
834
835                 l2 = mb[i]->l2_len;
836                 l3 = mb[i]->l3_len;
837
838                 sqc = rte_cpu_to_be_64(sqn + i);
839                 gen_iv(iv, sqc);
840
841                 /* try to update the packet itself */
842                 rc = esp_outb_trs_pkt_prepare(sa, sqc, iv, mb[i],
843                                 l2, l3, &icv);
844
845                 /* success, setup crypto op */
846                 if (rc >= 0) {
847                         outb_pkt_xprepare(sa, sqc, &icv);
848                         lksd_none_cop_prepare(cop[k], cs, mb[i]);
849                         esp_outb_cop_prepare(cop[k], sa, iv, &icv, l2 + l3, rc);
850                         k++;
851                 /* failure, put packet into the death-row */
852                 } else {
853                         dr[i - k] = i;
854                         rte_errno = -rc;
855                 }
856         }
857
858         /* copy not prepared mbufs beyond good ones */
859         if (k != n && k != 0)
860                 move_bad_mbufs(mb, dr, n, n - k);
861
862         return k;
863 }
864
865 /*
866  * setup crypto op and crypto sym op for ESP inbound tunnel packet.
867  */
868 static inline int32_t
869 esp_inb_tun_cop_prepare(struct rte_crypto_op *cop,
870         const struct rte_ipsec_sa *sa, struct rte_mbuf *mb,
871         const union sym_op_data *icv, uint32_t pofs, uint32_t plen)
872 {
873         struct rte_crypto_sym_op *sop;
874         struct aead_gcm_iv *gcm;
875         struct aesctr_cnt_blk *ctr;
876         uint64_t *ivc, *ivp;
877         uint32_t clen;
878         uint8_t algo_type = sa->algo_type;
879
880         clen = plen - sa->ctp.cipher.length;
881         if ((int32_t)clen < 0 || (clen & (sa->pad_align - 1)) != 0)
882                 return -EINVAL;
883
884         /* fill sym op fields */
885         sop = cop->sym;
886
887         switch (algo_type) {
888         case ALGO_TYPE_AES_GCM:
889                 sop->aead.data.offset = pofs + sa->ctp.cipher.offset;
890                 sop->aead.data.length = clen;
891                 sop->aead.digest.data = icv->va;
892                 sop->aead.digest.phys_addr = icv->pa;
893                 sop->aead.aad.data = icv->va + sa->icv_len;
894                 sop->aead.aad.phys_addr = icv->pa + sa->icv_len;
895
896                 /* fill AAD IV (located inside crypto op) */
897                 gcm = rte_crypto_op_ctod_offset(cop, struct aead_gcm_iv *,
898                         sa->iv_ofs);
899                 ivp = rte_pktmbuf_mtod_offset(mb, uint64_t *,
900                         pofs + sizeof(struct esp_hdr));
901                 aead_gcm_iv_fill(gcm, ivp[0], sa->salt);
902                 break;
903         case ALGO_TYPE_AES_CBC:
904         case ALGO_TYPE_3DES_CBC:
905                 sop->cipher.data.offset = pofs + sa->ctp.cipher.offset;
906                 sop->cipher.data.length = clen;
907                 sop->auth.data.offset = pofs + sa->ctp.auth.offset;
908                 sop->auth.data.length = plen - sa->ctp.auth.length;
909                 sop->auth.digest.data = icv->va;
910                 sop->auth.digest.phys_addr = icv->pa;
911
912                 /* copy iv from the input packet to the cop */
913                 ivc = rte_crypto_op_ctod_offset(cop, uint64_t *, sa->iv_ofs);
914                 ivp = rte_pktmbuf_mtod_offset(mb, uint64_t *,
915                         pofs + sizeof(struct esp_hdr));
916                 copy_iv(ivc, ivp, sa->iv_len);
917                 break;
918         case ALGO_TYPE_AES_CTR:
919                 sop->cipher.data.offset = pofs + sa->ctp.cipher.offset;
920                 sop->cipher.data.length = clen;
921                 sop->auth.data.offset = pofs + sa->ctp.auth.offset;
922                 sop->auth.data.length = plen - sa->ctp.auth.length;
923                 sop->auth.digest.data = icv->va;
924                 sop->auth.digest.phys_addr = icv->pa;
925
926                 /* copy iv from the input packet to the cop */
927                 ctr = rte_crypto_op_ctod_offset(cop, struct aesctr_cnt_blk *,
928                         sa->iv_ofs);
929                 ivp = rte_pktmbuf_mtod_offset(mb, uint64_t *,
930                         pofs + sizeof(struct esp_hdr));
931                 aes_ctr_cnt_blk_fill(ctr, ivp[0], sa->salt);
932                 break;
933         case ALGO_TYPE_NULL:
934                 sop->cipher.data.offset = pofs + sa->ctp.cipher.offset;
935                 sop->cipher.data.length = clen;
936                 sop->auth.data.offset = pofs + sa->ctp.auth.offset;
937                 sop->auth.data.length = plen - sa->ctp.auth.length;
938                 sop->auth.digest.data = icv->va;
939                 sop->auth.digest.phys_addr = icv->pa;
940                 break;
941
942         default:
943                 return -EINVAL;
944         }
945
946         return 0;
947 }
948
949 /*
950  * for pure cryptodev (lookaside none) depending on SA settings,
951  * we might have to write some extra data to the packet.
952  */
953 static inline void
954 inb_pkt_xprepare(const struct rte_ipsec_sa *sa, rte_be64_t sqc,
955         const union sym_op_data *icv)
956 {
957         struct aead_gcm_aad *aad;
958
959         /* insert SQN.hi between ESP trailer and ICV */
960         if (sa->sqh_len != 0)
961                 insert_sqh(sqn_hi32(sqc), icv->va, sa->icv_len);
962
963         /*
964          * fill AAD fields, if any (aad fields are placed after icv),
965          * right now we support only one AEAD algorithm: AES-GCM.
966          */
967         if (sa->aad_len != 0) {
968                 aad = (struct aead_gcm_aad *)(icv->va + sa->icv_len);
969                 aead_gcm_aad_fill(aad, sa->spi, sqc, IS_ESN(sa));
970         }
971 }
972
973 /*
974  * setup/update packet data and metadata for ESP inbound tunnel case.
975  */
976 static inline int32_t
977 esp_inb_tun_pkt_prepare(const struct rte_ipsec_sa *sa,
978         const struct replay_sqn *rsn, struct rte_mbuf *mb,
979         uint32_t hlen, union sym_op_data *icv)
980 {
981         int32_t rc;
982         uint64_t sqn;
983         uint32_t icv_ofs, plen;
984         struct rte_mbuf *ml;
985         struct esp_hdr *esph;
986
987         esph = rte_pktmbuf_mtod_offset(mb, struct esp_hdr *, hlen);
988
989         /*
990          * retrieve and reconstruct SQN, then check it, then
991          * convert it back into network byte order.
992          */
993         sqn = rte_be_to_cpu_32(esph->seq);
994         if (IS_ESN(sa))
995                 sqn = reconstruct_esn(rsn->sqn, sqn, sa->replay.win_sz);
996
997         rc = esn_inb_check_sqn(rsn, sa, sqn);
998         if (rc != 0)
999                 return rc;
1000
1001         sqn = rte_cpu_to_be_64(sqn);
1002
1003         /* start packet manipulation */
1004         plen = mb->pkt_len;
1005         plen = plen - hlen;
1006
1007         ml = rte_pktmbuf_lastseg(mb);
1008         icv_ofs = ml->data_len - sa->icv_len + sa->sqh_len;
1009
1010         /* we have to allocate space for AAD somewhere,
1011          * right now - just use free trailing space at the last segment.
1012          * Would probably be more convenient to reserve space for AAD
1013          * inside rte_crypto_op itself
1014          * (again for IV space is already reserved inside cop).
1015          */
1016         if (sa->aad_len + sa->sqh_len > rte_pktmbuf_tailroom(ml))
1017                 return -ENOSPC;
1018
1019         icv->va = rte_pktmbuf_mtod_offset(ml, void *, icv_ofs);
1020         icv->pa = rte_pktmbuf_iova_offset(ml, icv_ofs);
1021
1022         inb_pkt_xprepare(sa, sqn, icv);
1023         return plen;
1024 }
1025
1026 /*
1027  * setup/update packets and crypto ops for ESP inbound case.
1028  */
1029 static uint16_t
1030 inb_pkt_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
1031         struct rte_crypto_op *cop[], uint16_t num)
1032 {
1033         int32_t rc;
1034         uint32_t i, k, hl;
1035         struct rte_ipsec_sa *sa;
1036         struct rte_cryptodev_sym_session *cs;
1037         struct replay_sqn *rsn;
1038         union sym_op_data icv;
1039         uint32_t dr[num];
1040
1041         sa = ss->sa;
1042         cs = ss->crypto.ses;
1043         rsn = rsn_acquire(sa);
1044
1045         k = 0;
1046         for (i = 0; i != num; i++) {
1047
1048                 hl = mb[i]->l2_len + mb[i]->l3_len;
1049                 rc = esp_inb_tun_pkt_prepare(sa, rsn, mb[i], hl, &icv);
1050                 if (rc >= 0) {
1051                         lksd_none_cop_prepare(cop[k], cs, mb[i]);
1052                         rc = esp_inb_tun_cop_prepare(cop[k], sa, mb[i], &icv,
1053                                 hl, rc);
1054                 }
1055
1056                 k += (rc == 0);
1057                 if (rc != 0) {
1058                         dr[i - k] = i;
1059                         rte_errno = -rc;
1060                 }
1061         }
1062
1063         rsn_release(sa, rsn);
1064
1065         /* copy not prepared mbufs beyond good ones */
1066         if (k != num && k != 0)
1067                 move_bad_mbufs(mb, dr, num, num - k);
1068
1069         return k;
1070 }
1071
1072 /*
1073  *  setup crypto ops for LOOKASIDE_PROTO type of devices.
1074  */
1075 static inline void
1076 lksd_proto_cop_prepare(const struct rte_ipsec_session *ss,
1077         struct rte_mbuf *mb[], struct rte_crypto_op *cop[], uint16_t num)
1078 {
1079         uint32_t i;
1080         struct rte_crypto_sym_op *sop;
1081
1082         for (i = 0; i != num; i++) {
1083                 sop = cop[i]->sym;
1084                 cop[i]->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
1085                 cop[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
1086                 cop[i]->sess_type = RTE_CRYPTO_OP_SECURITY_SESSION;
1087                 sop->m_src = mb[i];
1088                 __rte_security_attach_session(sop, ss->security.ses);
1089         }
1090 }
1091
1092 /*
1093  *  setup packets and crypto ops for LOOKASIDE_PROTO type of devices.
1094  *  Note that for LOOKASIDE_PROTO all packet modifications will be
1095  *  performed by PMD/HW.
1096  *  SW has only to prepare crypto op.
1097  */
1098 static uint16_t
1099 lksd_proto_prepare(const struct rte_ipsec_session *ss,
1100         struct rte_mbuf *mb[], struct rte_crypto_op *cop[], uint16_t num)
1101 {
1102         lksd_proto_cop_prepare(ss, mb, cop, num);
1103         return num;
1104 }
1105
1106 /*
1107  * process ESP inbound tunnel packet.
1108  */
1109 static inline int
1110 esp_inb_tun_single_pkt_process(struct rte_ipsec_sa *sa, struct rte_mbuf *mb,
1111         uint32_t *sqn)
1112 {
1113         uint32_t hlen, icv_len, tlen;
1114         struct esp_hdr *esph;
1115         struct esp_tail *espt;
1116         struct rte_mbuf *ml;
1117         char *pd;
1118
1119         if (mb->ol_flags & PKT_RX_SEC_OFFLOAD_FAILED)
1120                 return -EBADMSG;
1121
1122         icv_len = sa->icv_len;
1123
1124         ml = rte_pktmbuf_lastseg(mb);
1125         espt = rte_pktmbuf_mtod_offset(ml, struct esp_tail *,
1126                 ml->data_len - icv_len - sizeof(*espt));
1127
1128         /*
1129          * check padding and next proto.
1130          * return an error if something is wrong.
1131          */
1132         pd = (char *)espt - espt->pad_len;
1133         if (espt->next_proto != sa->proto ||
1134                         memcmp(pd, esp_pad_bytes, espt->pad_len))
1135                 return -EINVAL;
1136
1137         /* cut of ICV, ESP tail and padding bytes */
1138         tlen = icv_len + sizeof(*espt) + espt->pad_len;
1139         ml->data_len -= tlen;
1140         mb->pkt_len -= tlen;
1141
1142         /* cut of L2/L3 headers, ESP header and IV */
1143         hlen = mb->l2_len + mb->l3_len;
1144         esph = rte_pktmbuf_mtod_offset(mb, struct esp_hdr *, hlen);
1145         rte_pktmbuf_adj(mb, hlen + sa->ctp.cipher.offset);
1146
1147         /* retrieve SQN for later check */
1148         *sqn = rte_be_to_cpu_32(esph->seq);
1149
1150         /* reset mbuf metatdata: L2/L3 len, packet type */
1151         mb->packet_type = RTE_PTYPE_UNKNOWN;
1152         mb->tx_offload = (mb->tx_offload & sa->tx_offload.msk) |
1153                 sa->tx_offload.val;
1154
1155         /* clear the PKT_RX_SEC_OFFLOAD flag if set */
1156         mb->ol_flags &= ~(mb->ol_flags & PKT_RX_SEC_OFFLOAD);
1157         return 0;
1158 }
1159
1160 /*
1161  * process ESP inbound transport packet.
1162  */
1163 static inline int
1164 esp_inb_trs_single_pkt_process(struct rte_ipsec_sa *sa, struct rte_mbuf *mb,
1165         uint32_t *sqn)
1166 {
1167         uint32_t hlen, icv_len, l2len, l3len, tlen;
1168         struct esp_hdr *esph;
1169         struct esp_tail *espt;
1170         struct rte_mbuf *ml;
1171         char *np, *op, *pd;
1172
1173         if (mb->ol_flags & PKT_RX_SEC_OFFLOAD_FAILED)
1174                 return -EBADMSG;
1175
1176         icv_len = sa->icv_len;
1177
1178         ml = rte_pktmbuf_lastseg(mb);
1179         espt = rte_pktmbuf_mtod_offset(ml, struct esp_tail *,
1180                 ml->data_len - icv_len - sizeof(*espt));
1181
1182         /* check padding, return an error if something is wrong. */
1183         pd = (char *)espt - espt->pad_len;
1184         if (memcmp(pd, esp_pad_bytes, espt->pad_len))
1185                 return -EINVAL;
1186
1187         /* cut of ICV, ESP tail and padding bytes */
1188         tlen = icv_len + sizeof(*espt) + espt->pad_len;
1189         ml->data_len -= tlen;
1190         mb->pkt_len -= tlen;
1191
1192         /* retrieve SQN for later check */
1193         l2len = mb->l2_len;
1194         l3len = mb->l3_len;
1195         hlen = l2len + l3len;
1196         op = rte_pktmbuf_mtod(mb, char *);
1197         esph = (struct esp_hdr *)(op + hlen);
1198         *sqn = rte_be_to_cpu_32(esph->seq);
1199
1200         /* cut off ESP header and IV, update L3 header */
1201         np = rte_pktmbuf_adj(mb, sa->ctp.cipher.offset);
1202         remove_esph(np, op, hlen);
1203         update_trs_l3hdr(sa, np + l2len, mb->pkt_len, l2len, l3len,
1204                         espt->next_proto);
1205
1206         /* reset mbuf packet type */
1207         mb->packet_type &= (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
1208
1209         /* clear the PKT_RX_SEC_OFFLOAD flag if set */
1210         mb->ol_flags &= ~(mb->ol_flags & PKT_RX_SEC_OFFLOAD);
1211         return 0;
1212 }
1213
1214 /*
1215  * for group of ESP inbound packets perform SQN check and update.
1216  */
1217 static inline uint16_t
1218 esp_inb_rsn_update(struct rte_ipsec_sa *sa, const uint32_t sqn[],
1219         uint32_t dr[], uint16_t num)
1220 {
1221         uint32_t i, k;
1222         struct replay_sqn *rsn;
1223
1224         rsn = rsn_update_start(sa);
1225
1226         k = 0;
1227         for (i = 0; i != num; i++) {
1228                 if (esn_inb_update_sqn(rsn, sa, sqn[i]) == 0)
1229                         k++;
1230                 else
1231                         dr[i - k] = i;
1232         }
1233
1234         rsn_update_finish(sa, rsn);
1235         return k;
1236 }
1237
1238 /*
1239  * process group of ESP inbound tunnel packets.
1240  */
1241 static uint16_t
1242 inb_tun_pkt_process(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
1243         uint16_t num)
1244 {
1245         uint32_t i, k, n;
1246         struct rte_ipsec_sa *sa;
1247         uint32_t sqn[num];
1248         uint32_t dr[num];
1249
1250         sa = ss->sa;
1251
1252         /* process packets, extract seq numbers */
1253
1254         k = 0;
1255         for (i = 0; i != num; i++) {
1256                 /* good packet */
1257                 if (esp_inb_tun_single_pkt_process(sa, mb[i], sqn + k) == 0)
1258                         k++;
1259                 /* bad packet, will drop from furhter processing */
1260                 else
1261                         dr[i - k] = i;
1262         }
1263
1264         /* handle unprocessed mbufs */
1265         if (k != num && k != 0)
1266                 move_bad_mbufs(mb, dr, num, num - k);
1267
1268         /* update SQN and replay winow */
1269         n = esp_inb_rsn_update(sa, sqn, dr, k);
1270
1271         /* handle mbufs with wrong SQN */
1272         if (n != k && n != 0)
1273                 move_bad_mbufs(mb, dr, k, k - n);
1274
1275         if (n != num)
1276                 rte_errno = EBADMSG;
1277
1278         return n;
1279 }
1280
1281 /*
1282  * process group of ESP inbound transport packets.
1283  */
1284 static uint16_t
1285 inb_trs_pkt_process(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
1286         uint16_t num)
1287 {
1288         uint32_t i, k, n;
1289         uint32_t sqn[num];
1290         struct rte_ipsec_sa *sa;
1291         uint32_t dr[num];
1292
1293         sa = ss->sa;
1294
1295         /* process packets, extract seq numbers */
1296
1297         k = 0;
1298         for (i = 0; i != num; i++) {
1299                 /* good packet */
1300                 if (esp_inb_trs_single_pkt_process(sa, mb[i], sqn + k) == 0)
1301                         k++;
1302                 /* bad packet, will drop from furhter processing */
1303                 else
1304                         dr[i - k] = i;
1305         }
1306
1307         /* handle unprocessed mbufs */
1308         if (k != num && k != 0)
1309                 move_bad_mbufs(mb, dr, num, num - k);
1310
1311         /* update SQN and replay winow */
1312         n = esp_inb_rsn_update(sa, sqn, dr, k);
1313
1314         /* handle mbufs with wrong SQN */
1315         if (n != k && n != 0)
1316                 move_bad_mbufs(mb, dr, k, k - n);
1317
1318         if (n != num)
1319                 rte_errno = EBADMSG;
1320
1321         return n;
1322 }
1323
1324 /*
1325  * process outbound packets for SA with ESN support,
1326  * for algorithms that require SQN.hibits to be implictly included
1327  * into digest computation.
1328  * In that case we have to move ICV bytes back to their proper place.
1329  */
1330 static uint16_t
1331 outb_sqh_process(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
1332         uint16_t num)
1333 {
1334         uint32_t i, k, icv_len, *icv;
1335         struct rte_mbuf *ml;
1336         struct rte_ipsec_sa *sa;
1337         uint32_t dr[num];
1338
1339         sa = ss->sa;
1340
1341         k = 0;
1342         icv_len = sa->icv_len;
1343
1344         for (i = 0; i != num; i++) {
1345                 if ((mb[i]->ol_flags & PKT_RX_SEC_OFFLOAD_FAILED) == 0) {
1346                         ml = rte_pktmbuf_lastseg(mb[i]);
1347                         icv = rte_pktmbuf_mtod_offset(ml, void *,
1348                                 ml->data_len - icv_len);
1349                         remove_sqh(icv, icv_len);
1350                         k++;
1351                 } else
1352                         dr[i - k] = i;
1353         }
1354
1355         /* handle unprocessed mbufs */
1356         if (k != num) {
1357                 rte_errno = EBADMSG;
1358                 if (k != 0)
1359                         move_bad_mbufs(mb, dr, num, num - k);
1360         }
1361
1362         return k;
1363 }
1364
1365 /*
1366  * simplest pkt process routine:
1367  * all actual processing is already done by HW/PMD,
1368  * just check mbuf ol_flags.
1369  * used for:
1370  * - inbound for RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL
1371  * - inbound/outbound for RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL
1372  * - outbound for RTE_SECURITY_ACTION_TYPE_NONE when ESN is disabled
1373  */
1374 static uint16_t
1375 pkt_flag_process(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
1376         uint16_t num)
1377 {
1378         uint32_t i, k;
1379         uint32_t dr[num];
1380
1381         RTE_SET_USED(ss);
1382
1383         k = 0;
1384         for (i = 0; i != num; i++) {
1385                 if ((mb[i]->ol_flags & PKT_RX_SEC_OFFLOAD_FAILED) == 0)
1386                         k++;
1387                 else
1388                         dr[i - k] = i;
1389         }
1390
1391         /* handle unprocessed mbufs */
1392         if (k != num) {
1393                 rte_errno = EBADMSG;
1394                 if (k != 0)
1395                         move_bad_mbufs(mb, dr, num, num - k);
1396         }
1397
1398         return k;
1399 }
1400
1401 /*
1402  * prepare packets for inline ipsec processing:
1403  * set ol_flags and attach metadata.
1404  */
1405 static inline void
1406 inline_outb_mbuf_prepare(const struct rte_ipsec_session *ss,
1407         struct rte_mbuf *mb[], uint16_t num)
1408 {
1409         uint32_t i, ol_flags;
1410
1411         ol_flags = ss->security.ol_flags & RTE_SECURITY_TX_OLOAD_NEED_MDATA;
1412         for (i = 0; i != num; i++) {
1413
1414                 mb[i]->ol_flags |= PKT_TX_SEC_OFFLOAD;
1415                 if (ol_flags != 0)
1416                         rte_security_set_pkt_metadata(ss->security.ctx,
1417                                 ss->security.ses, mb[i], NULL);
1418         }
1419 }
1420
1421 /*
1422  * process group of ESP outbound tunnel packets destined for
1423  * INLINE_CRYPTO type of device.
1424  */
1425 static uint16_t
1426 inline_outb_tun_pkt_process(const struct rte_ipsec_session *ss,
1427         struct rte_mbuf *mb[], uint16_t num)
1428 {
1429         int32_t rc;
1430         uint32_t i, k, n;
1431         uint64_t sqn;
1432         rte_be64_t sqc;
1433         struct rte_ipsec_sa *sa;
1434         union sym_op_data icv;
1435         uint64_t iv[IPSEC_MAX_IV_QWORD];
1436         uint32_t dr[num];
1437
1438         sa = ss->sa;
1439
1440         n = num;
1441         sqn = esn_outb_update_sqn(sa, &n);
1442         if (n != num)
1443                 rte_errno = EOVERFLOW;
1444
1445         k = 0;
1446         for (i = 0; i != n; i++) {
1447
1448                 sqc = rte_cpu_to_be_64(sqn + i);
1449                 gen_iv(iv, sqc);
1450
1451                 /* try to update the packet itself */
1452                 rc = esp_outb_tun_pkt_prepare(sa, sqc, iv, mb[i], &icv);
1453
1454                 k += (rc >= 0);
1455
1456                 /* failure, put packet into the death-row */
1457                 if (rc < 0) {
1458                         dr[i - k] = i;
1459                         rte_errno = -rc;
1460                 }
1461         }
1462
1463         /* copy not processed mbufs beyond good ones */
1464         if (k != n && k != 0)
1465                 move_bad_mbufs(mb, dr, n, n - k);
1466
1467         inline_outb_mbuf_prepare(ss, mb, k);
1468         return k;
1469 }
1470
1471 /*
1472  * process group of ESP outbound transport packets destined for
1473  * INLINE_CRYPTO type of device.
1474  */
1475 static uint16_t
1476 inline_outb_trs_pkt_process(const struct rte_ipsec_session *ss,
1477         struct rte_mbuf *mb[], uint16_t num)
1478 {
1479         int32_t rc;
1480         uint32_t i, k, n, l2, l3;
1481         uint64_t sqn;
1482         rte_be64_t sqc;
1483         struct rte_ipsec_sa *sa;
1484         union sym_op_data icv;
1485         uint64_t iv[IPSEC_MAX_IV_QWORD];
1486         uint32_t dr[num];
1487
1488         sa = ss->sa;
1489
1490         n = num;
1491         sqn = esn_outb_update_sqn(sa, &n);
1492         if (n != num)
1493                 rte_errno = EOVERFLOW;
1494
1495         k = 0;
1496         for (i = 0; i != n; i++) {
1497
1498                 l2 = mb[i]->l2_len;
1499                 l3 = mb[i]->l3_len;
1500
1501                 sqc = rte_cpu_to_be_64(sqn + i);
1502                 gen_iv(iv, sqc);
1503
1504                 /* try to update the packet itself */
1505                 rc = esp_outb_trs_pkt_prepare(sa, sqc, iv, mb[i],
1506                                 l2, l3, &icv);
1507
1508                 k += (rc >= 0);
1509
1510                 /* failure, put packet into the death-row */
1511                 if (rc < 0) {
1512                         dr[i - k] = i;
1513                         rte_errno = -rc;
1514                 }
1515         }
1516
1517         /* copy not processed mbufs beyond good ones */
1518         if (k != n && k != 0)
1519                 move_bad_mbufs(mb, dr, n, n - k);
1520
1521         inline_outb_mbuf_prepare(ss, mb, k);
1522         return k;
1523 }
1524
1525 /*
1526  * outbound for RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:
1527  * actual processing is done by HW/PMD, just set flags and metadata.
1528  */
1529 static uint16_t
1530 outb_inline_proto_process(const struct rte_ipsec_session *ss,
1531                 struct rte_mbuf *mb[], uint16_t num)
1532 {
1533         inline_outb_mbuf_prepare(ss, mb, num);
1534         return num;
1535 }
1536
1537 /*
1538  * Select packet processing function for session on LOOKASIDE_NONE
1539  * type of device.
1540  */
1541 static int
1542 lksd_none_pkt_func_select(const struct rte_ipsec_sa *sa,
1543                 struct rte_ipsec_sa_pkt_func *pf)
1544 {
1545         int32_t rc;
1546
1547         static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK |
1548                         RTE_IPSEC_SATP_MODE_MASK;
1549
1550         rc = 0;
1551         switch (sa->type & msk) {
1552         case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4):
1553         case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6):
1554                 pf->prepare = inb_pkt_prepare;
1555                 pf->process = inb_tun_pkt_process;
1556                 break;
1557         case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS):
1558                 pf->prepare = inb_pkt_prepare;
1559                 pf->process = inb_trs_pkt_process;
1560                 break;
1561         case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4):
1562         case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6):
1563                 pf->prepare = outb_tun_prepare;
1564                 pf->process = (sa->sqh_len != 0) ?
1565                         outb_sqh_process : pkt_flag_process;
1566                 break;
1567         case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS):
1568                 pf->prepare = outb_trs_prepare;
1569                 pf->process = (sa->sqh_len != 0) ?
1570                         outb_sqh_process : pkt_flag_process;
1571                 break;
1572         default:
1573                 rc = -ENOTSUP;
1574         }
1575
1576         return rc;
1577 }
1578
1579 /*
1580  * Select packet processing function for session on INLINE_CRYPTO
1581  * type of device.
1582  */
1583 static int
1584 inline_crypto_pkt_func_select(const struct rte_ipsec_sa *sa,
1585                 struct rte_ipsec_sa_pkt_func *pf)
1586 {
1587         int32_t rc;
1588
1589         static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK |
1590                         RTE_IPSEC_SATP_MODE_MASK;
1591
1592         rc = 0;
1593         switch (sa->type & msk) {
1594         case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4):
1595         case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6):
1596                 pf->process = inb_tun_pkt_process;
1597                 break;
1598         case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS):
1599                 pf->process = inb_trs_pkt_process;
1600                 break;
1601         case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4):
1602         case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6):
1603                 pf->process = inline_outb_tun_pkt_process;
1604                 break;
1605         case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS):
1606                 pf->process = inline_outb_trs_pkt_process;
1607                 break;
1608         default:
1609                 rc = -ENOTSUP;
1610         }
1611
1612         return rc;
1613 }
1614
1615 /*
1616  * Select packet processing function for given session based on SA parameters
1617  * and type of associated with the session device.
1618  */
1619 int
1620 ipsec_sa_pkt_func_select(const struct rte_ipsec_session *ss,
1621         const struct rte_ipsec_sa *sa, struct rte_ipsec_sa_pkt_func *pf)
1622 {
1623         int32_t rc;
1624
1625         rc = 0;
1626         pf[0] = (struct rte_ipsec_sa_pkt_func) { 0 };
1627
1628         switch (ss->type) {
1629         case RTE_SECURITY_ACTION_TYPE_NONE:
1630                 rc = lksd_none_pkt_func_select(sa, pf);
1631                 break;
1632         case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
1633                 rc = inline_crypto_pkt_func_select(sa, pf);
1634                 break;
1635         case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:
1636                 if ((sa->type & RTE_IPSEC_SATP_DIR_MASK) ==
1637                                 RTE_IPSEC_SATP_DIR_IB)
1638                         pf->process = pkt_flag_process;
1639                 else
1640                         pf->process = outb_inline_proto_process;
1641                 break;
1642         case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL:
1643                 pf->prepare = lksd_proto_prepare;
1644                 pf->process = pkt_flag_process;
1645                 break;
1646         default:
1647                 rc = -ENOTSUP;
1648         }
1649
1650         return rc;
1651 }