lib: remove unneeded header includes
[dpdk.git] / lib / ipsec / esp_inb.c
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_errno.h>
8 #include <rte_cryptodev.h>
9
10 #include "sa.h"
11 #include "ipsec_sqn.h"
12 #include "crypto.h"
13 #include "iph.h"
14 #include "misc.h"
15 #include "pad.h"
16
17 typedef uint16_t (*esp_inb_process_t)(struct rte_ipsec_sa *sa,
18         struct rte_mbuf *mb[], uint32_t sqn[], uint32_t dr[], uint16_t num,
19         uint8_t sqh_len);
20
21 /*
22  * helper function to fill crypto_sym op for cipher+auth algorithms.
23  * used by inb_cop_prepare(), see below.
24  */
25 static inline void
26 sop_ciph_auth_prepare(struct rte_crypto_sym_op *sop,
27         const struct rte_ipsec_sa *sa, const union sym_op_data *icv,
28         uint32_t pofs, uint32_t plen)
29 {
30         sop->cipher.data.offset = pofs + sa->ctp.cipher.offset;
31         sop->cipher.data.length = plen - sa->ctp.cipher.length;
32         sop->auth.data.offset = pofs + sa->ctp.auth.offset;
33         sop->auth.data.length = plen - sa->ctp.auth.length;
34         sop->auth.digest.data = icv->va;
35         sop->auth.digest.phys_addr = icv->pa;
36 }
37
38 /*
39  * helper function to fill crypto_sym op for aead algorithms
40  * used by inb_cop_prepare(), see below.
41  */
42 static inline void
43 sop_aead_prepare(struct rte_crypto_sym_op *sop,
44         const struct rte_ipsec_sa *sa, const union sym_op_data *icv,
45         uint32_t pofs, uint32_t plen)
46 {
47         sop->aead.data.offset = pofs + sa->ctp.cipher.offset;
48         sop->aead.data.length = plen - sa->ctp.cipher.length;
49         sop->aead.digest.data = icv->va;
50         sop->aead.digest.phys_addr = icv->pa;
51         sop->aead.aad.data = icv->va + sa->icv_len;
52         sop->aead.aad.phys_addr = icv->pa + sa->icv_len;
53 }
54
55 /*
56  * setup crypto op and crypto sym op for ESP inbound packet.
57  */
58 static inline void
59 inb_cop_prepare(struct rte_crypto_op *cop,
60         const struct rte_ipsec_sa *sa, struct rte_mbuf *mb,
61         const union sym_op_data *icv, uint32_t pofs, uint32_t plen)
62 {
63         struct rte_crypto_sym_op *sop;
64         struct aead_gcm_iv *gcm;
65         struct aead_ccm_iv *ccm;
66         struct aead_chacha20_poly1305_iv *chacha20_poly1305;
67         struct aesctr_cnt_blk *ctr;
68         uint64_t *ivc, *ivp;
69         uint32_t algo;
70
71         algo = sa->algo_type;
72         ivp = rte_pktmbuf_mtod_offset(mb, uint64_t *,
73                 pofs + sizeof(struct rte_esp_hdr));
74
75         /* fill sym op fields */
76         sop = cop->sym;
77
78         switch (algo) {
79         case ALGO_TYPE_AES_GCM:
80                 sop_aead_prepare(sop, sa, icv, pofs, plen);
81
82                 /* fill AAD IV (located inside crypto op) */
83                 gcm = rte_crypto_op_ctod_offset(cop, struct aead_gcm_iv *,
84                         sa->iv_ofs);
85                 aead_gcm_iv_fill(gcm, ivp[0], sa->salt);
86                 break;
87         case ALGO_TYPE_AES_CCM:
88                 sop_aead_prepare(sop, sa, icv, pofs, plen);
89
90                 /* fill AAD IV (located inside crypto op) */
91                 ccm = rte_crypto_op_ctod_offset(cop, struct aead_ccm_iv *,
92                         sa->iv_ofs);
93                 aead_ccm_iv_fill(ccm, ivp[0], sa->salt);
94                 break;
95         case ALGO_TYPE_CHACHA20_POLY1305:
96                 sop_aead_prepare(sop, sa, icv, pofs, plen);
97
98                 /* fill AAD IV (located inside crypto op) */
99                 chacha20_poly1305 = rte_crypto_op_ctod_offset(cop,
100                                 struct aead_chacha20_poly1305_iv *,
101                                 sa->iv_ofs);
102                 aead_chacha20_poly1305_iv_fill(chacha20_poly1305,
103                                                ivp[0], sa->salt);
104                 break;
105         case ALGO_TYPE_AES_CBC:
106         case ALGO_TYPE_3DES_CBC:
107                 sop_ciph_auth_prepare(sop, sa, icv, pofs, plen);
108
109                 /* copy iv from the input packet to the cop */
110                 ivc = rte_crypto_op_ctod_offset(cop, uint64_t *, sa->iv_ofs);
111                 copy_iv(ivc, ivp, sa->iv_len);
112                 break;
113         case ALGO_TYPE_AES_GMAC:
114                 sop_ciph_auth_prepare(sop, sa, icv, pofs, plen);
115
116                 /* fill AAD IV (located inside crypto op) */
117                 gcm = rte_crypto_op_ctod_offset(cop, struct aead_gcm_iv *,
118                         sa->iv_ofs);
119                 aead_gcm_iv_fill(gcm, ivp[0], sa->salt);
120                 break;
121         case ALGO_TYPE_AES_CTR:
122                 sop_ciph_auth_prepare(sop, sa, icv, pofs, plen);
123
124                 /* fill CTR block (located inside crypto op) */
125                 ctr = rte_crypto_op_ctod_offset(cop, struct aesctr_cnt_blk *,
126                         sa->iv_ofs);
127                 aes_ctr_cnt_blk_fill(ctr, ivp[0], sa->salt);
128                 break;
129         case ALGO_TYPE_NULL:
130                 sop_ciph_auth_prepare(sop, sa, icv, pofs, plen);
131                 break;
132         }
133 }
134
135 static inline uint32_t
136 inb_cpu_crypto_prepare(const struct rte_ipsec_sa *sa, struct rte_mbuf *mb,
137         uint32_t *pofs, uint32_t plen, void *iv)
138 {
139         struct aead_gcm_iv *gcm;
140         struct aead_ccm_iv *ccm;
141         struct aead_chacha20_poly1305_iv *chacha20_poly1305;
142         struct aesctr_cnt_blk *ctr;
143         uint64_t *ivp;
144         uint32_t clen;
145
146         ivp = rte_pktmbuf_mtod_offset(mb, uint64_t *,
147                 *pofs + sizeof(struct rte_esp_hdr));
148         clen = 0;
149
150         switch (sa->algo_type) {
151         case ALGO_TYPE_AES_GCM:
152         case ALGO_TYPE_AES_GMAC:
153                 gcm = (struct aead_gcm_iv *)iv;
154                 aead_gcm_iv_fill(gcm, ivp[0], sa->salt);
155                 break;
156         case ALGO_TYPE_AES_CCM:
157                 ccm = (struct aead_ccm_iv *)iv;
158                 aead_ccm_iv_fill(ccm, ivp[0], sa->salt);
159                 break;
160         case ALGO_TYPE_CHACHA20_POLY1305:
161                 chacha20_poly1305 = (struct aead_chacha20_poly1305_iv *)iv;
162                 aead_chacha20_poly1305_iv_fill(chacha20_poly1305,
163                                                ivp[0], sa->salt);
164                 break;
165         case ALGO_TYPE_AES_CBC:
166         case ALGO_TYPE_3DES_CBC:
167                 copy_iv(iv, ivp, sa->iv_len);
168                 break;
169         case ALGO_TYPE_AES_CTR:
170                 ctr = (struct aesctr_cnt_blk *)iv;
171                 aes_ctr_cnt_blk_fill(ctr, ivp[0], sa->salt);
172                 break;
173         }
174
175         *pofs += sa->ctp.auth.offset;
176         clen = plen - sa->ctp.auth.length;
177         return clen;
178 }
179
180 /*
181  * Helper function for prepare() to deal with situation when
182  * ICV is spread by two segments. Tries to move ICV completely into the
183  * last segment.
184  */
185 static struct rte_mbuf *
186 move_icv(struct rte_mbuf *ml, uint32_t ofs)
187 {
188         uint32_t n;
189         struct rte_mbuf *ms;
190         const void *prev;
191         void *new;
192
193         ms = ml->next;
194         n = ml->data_len - ofs;
195
196         prev = rte_pktmbuf_mtod_offset(ml, const void *, ofs);
197         new = rte_pktmbuf_prepend(ms, n);
198         if (new == NULL)
199                 return NULL;
200
201         /* move n ICV bytes from ml into ms */
202         rte_memcpy(new, prev, n);
203         ml->data_len -= n;
204
205         return ms;
206 }
207
208 /*
209  * for pure cryptodev (lookaside none) depending on SA settings,
210  * we might have to write some extra data to the packet.
211  */
212 static inline void
213 inb_pkt_xprepare(const struct rte_ipsec_sa *sa, rte_be64_t sqc,
214         const union sym_op_data *icv)
215 {
216         struct aead_gcm_aad *aad;
217         struct aead_ccm_aad *caad;
218         struct aead_chacha20_poly1305_aad *chacha_aad;
219
220         /* insert SQN.hi between ESP trailer and ICV */
221         if (sa->sqh_len != 0)
222                 insert_sqh(sqn_hi32(sqc), icv->va, sa->icv_len);
223
224         /*
225          * fill AAD fields, if any (aad fields are placed after icv),
226          * right now we support only one AEAD algorithm: AES-GCM.
227          */
228         switch (sa->algo_type) {
229         case ALGO_TYPE_AES_GCM:
230                 if (sa->aad_len != 0) {
231                         aad = (struct aead_gcm_aad *)(icv->va + sa->icv_len);
232                         aead_gcm_aad_fill(aad, sa->spi, sqc, IS_ESN(sa));
233                 }
234                 break;
235         case ALGO_TYPE_AES_CCM:
236                 if (sa->aad_len != 0) {
237                         caad = (struct aead_ccm_aad *)(icv->va + sa->icv_len);
238                         aead_ccm_aad_fill(caad, sa->spi, sqc, IS_ESN(sa));
239                 }
240                 break;
241         case ALGO_TYPE_CHACHA20_POLY1305:
242                 if (sa->aad_len != 0) {
243                         chacha_aad = (struct aead_chacha20_poly1305_aad *)
244                             (icv->va + sa->icv_len);
245                         aead_chacha20_poly1305_aad_fill(chacha_aad,
246                                                 sa->spi, sqc, IS_ESN(sa));
247                 }
248                 break;
249         }
250 }
251
252 static inline int
253 inb_get_sqn(const struct rte_ipsec_sa *sa, const struct replay_sqn *rsn,
254         struct rte_mbuf *mb, uint32_t hlen, rte_be64_t *sqc)
255 {
256         int32_t rc;
257         uint64_t sqn;
258         struct rte_esp_hdr *esph;
259
260         esph = rte_pktmbuf_mtod_offset(mb, struct rte_esp_hdr *, hlen);
261
262         /*
263          * retrieve and reconstruct SQN, then check it, then
264          * convert it back into network byte order.
265          */
266         sqn = rte_be_to_cpu_32(esph->seq);
267         if (IS_ESN(sa))
268                 sqn = reconstruct_esn(rsn->sqn, sqn, sa->replay.win_sz);
269         *sqc = rte_cpu_to_be_64(sqn);
270
271         /* check IPsec window */
272         rc = esn_inb_check_sqn(rsn, sa, sqn);
273
274         return rc;
275 }
276
277 /* prepare packet for upcoming processing */
278 static inline int32_t
279 inb_prepare(const struct rte_ipsec_sa *sa, struct rte_mbuf *mb,
280         uint32_t hlen, union sym_op_data *icv)
281 {
282         uint32_t clen, icv_len, icv_ofs, plen;
283         struct rte_mbuf *ml;
284
285         /* start packet manipulation */
286         plen = mb->pkt_len;
287         plen = plen - hlen;
288
289         /* check that packet has a valid length */
290         clen = plen - sa->ctp.cipher.length;
291         if ((int32_t)clen < 0 || (clen & (sa->pad_align - 1)) != 0)
292                 return -EBADMSG;
293
294         /* find ICV location */
295         icv_len = sa->icv_len;
296         icv_ofs = mb->pkt_len - icv_len;
297
298         ml = mbuf_get_seg_ofs(mb, &icv_ofs);
299
300         /*
301          * if ICV is spread by two segments, then try to
302          * move ICV completely into the last segment.
303          */
304         if (ml->data_len < icv_ofs + icv_len) {
305
306                 ml = move_icv(ml, icv_ofs);
307                 if (ml == NULL)
308                         return -ENOSPC;
309
310                 /* new ICV location */
311                 icv_ofs = 0;
312         }
313
314         icv_ofs += sa->sqh_len;
315
316         /*
317          * we have to allocate space for AAD somewhere,
318          * right now - just use free trailing space at the last segment.
319          * Would probably be more convenient to reserve space for AAD
320          * inside rte_crypto_op itself
321          * (again for IV space is already reserved inside cop).
322          */
323         if (sa->aad_len + sa->sqh_len > rte_pktmbuf_tailroom(ml))
324                 return -ENOSPC;
325
326         icv->va = rte_pktmbuf_mtod_offset(ml, void *, icv_ofs);
327         icv->pa = rte_pktmbuf_iova_offset(ml, icv_ofs);
328
329         /*
330          * if esn is used then high-order 32 bits are also used in ICV
331          * calculation but are not transmitted, update packet length
332          * to be consistent with auth data length and offset, this will
333          * be subtracted from packet length in post crypto processing
334          */
335         mb->pkt_len += sa->sqh_len;
336         ml->data_len += sa->sqh_len;
337
338         return plen;
339 }
340
341 static inline int32_t
342 inb_pkt_prepare(const struct rte_ipsec_sa *sa, const struct replay_sqn *rsn,
343         struct rte_mbuf *mb, uint32_t hlen, union sym_op_data *icv)
344 {
345         int rc;
346         rte_be64_t sqn;
347
348         rc = inb_get_sqn(sa, rsn, mb, hlen, &sqn);
349         if (rc != 0)
350                 return rc;
351
352         rc = inb_prepare(sa, mb, hlen, icv);
353         if (rc < 0)
354                 return rc;
355
356         inb_pkt_xprepare(sa, sqn, icv);
357         return rc;
358 }
359
360 /*
361  * setup/update packets and crypto ops for ESP inbound case.
362  */
363 uint16_t
364 esp_inb_pkt_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
365         struct rte_crypto_op *cop[], uint16_t num)
366 {
367         int32_t rc;
368         uint32_t i, k, hl;
369         struct rte_ipsec_sa *sa;
370         struct rte_cryptodev_sym_session *cs;
371         struct replay_sqn *rsn;
372         union sym_op_data icv;
373         uint32_t dr[num];
374
375         sa = ss->sa;
376         cs = ss->crypto.ses;
377         rsn = rsn_acquire(sa);
378
379         k = 0;
380         for (i = 0; i != num; i++) {
381
382                 hl = mb[i]->l2_len + mb[i]->l3_len;
383                 rc = inb_pkt_prepare(sa, rsn, mb[i], hl, &icv);
384                 if (rc >= 0) {
385                         lksd_none_cop_prepare(cop[k], cs, mb[i]);
386                         inb_cop_prepare(cop[k], sa, mb[i], &icv, hl, rc);
387                         k++;
388                 } else {
389                         dr[i - k] = i;
390                         rte_errno = -rc;
391                 }
392         }
393
394         rsn_release(sa, rsn);
395
396         /* copy not prepared mbufs beyond good ones */
397         if (k != num && k != 0)
398                 move_bad_mbufs(mb, dr, num, num - k);
399
400         return k;
401 }
402
403 /*
404  * Start with processing inbound packet.
405  * This is common part for both tunnel and transport mode.
406  * Extract information that will be needed later from mbuf metadata and
407  * actual packet data:
408  * - mbuf for packet's last segment
409  * - length of the L2/L3 headers
410  * - esp tail structure
411  */
412 static inline void
413 process_step1(struct rte_mbuf *mb, uint32_t tlen, struct rte_mbuf **ml,
414         struct rte_esp_tail *espt, uint32_t *hlen, uint32_t *tofs)
415 {
416         const struct rte_esp_tail *pt;
417         uint32_t ofs;
418
419         ofs = mb->pkt_len - tlen;
420         hlen[0] = mb->l2_len + mb->l3_len;
421         ml[0] = mbuf_get_seg_ofs(mb, &ofs);
422         pt = rte_pktmbuf_mtod_offset(ml[0], const struct rte_esp_tail *, ofs);
423         tofs[0] = ofs;
424         espt[0] = pt[0];
425 }
426
427 /*
428  * Helper function to check pad bytes values.
429  * Note that pad bytes can be spread across multiple segments.
430  */
431 static inline int
432 check_pad_bytes(struct rte_mbuf *mb, uint32_t ofs, uint32_t len)
433 {
434         const uint8_t *pd;
435         uint32_t k, n;
436
437         for (n = 0; n != len; n += k, mb = mb->next) {
438                 k = mb->data_len - ofs;
439                 k = RTE_MIN(k, len - n);
440                 pd = rte_pktmbuf_mtod_offset(mb, const uint8_t *, ofs);
441                 if (memcmp(pd, esp_pad_bytes + n, k) != 0)
442                         break;
443                 ofs = 0;
444         }
445
446         return len - n;
447 }
448
449 /*
450  * packet checks for transport mode:
451  * - no reported IPsec related failures in ol_flags
452  * - tail and header lengths are valid
453  * - padding bytes are valid
454  * apart from checks, function also updates tail offset (and segment)
455  * by taking into account pad length.
456  */
457 static inline int32_t
458 trs_process_check(struct rte_mbuf *mb, struct rte_mbuf **ml,
459         uint32_t *tofs, struct rte_esp_tail espt, uint32_t hlen, uint32_t tlen)
460 {
461         if ((mb->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED) != 0 ||
462                         tlen + hlen > mb->pkt_len)
463                 return -EBADMSG;
464
465         /* padding bytes are spread over multiple segments */
466         if (tofs[0] < espt.pad_len) {
467                 tofs[0] = mb->pkt_len - tlen;
468                 ml[0] = mbuf_get_seg_ofs(mb, tofs);
469         } else
470                 tofs[0] -= espt.pad_len;
471
472         return check_pad_bytes(ml[0], tofs[0], espt.pad_len);
473 }
474
475 /*
476  * packet checks for tunnel mode:
477  * - same as for transport mode
478  * - esp tail next proto contains expected for that SA value
479  */
480 static inline int32_t
481 tun_process_check(struct rte_mbuf *mb, struct rte_mbuf **ml,
482         uint32_t *tofs, struct rte_esp_tail espt, uint32_t hlen, uint32_t tlen,
483         uint8_t proto)
484 {
485         return (trs_process_check(mb, ml, tofs, espt, hlen, tlen) ||
486                 espt.next_proto != proto);
487 }
488
489 /*
490  * step two for tunnel mode:
491  * - read SQN value (for future use)
492  * - cut of ICV, ESP tail and padding bytes
493  * - cut of ESP header and IV, also if needed - L2/L3 headers
494  *   (controlled by *adj* value)
495  */
496 static inline void *
497 tun_process_step2(struct rte_mbuf *mb, struct rte_mbuf *ml, uint32_t hlen,
498         uint32_t adj, uint32_t tofs, uint32_t tlen, uint32_t *sqn)
499 {
500         const struct rte_esp_hdr *ph;
501
502         /* read SQN value */
503         ph = rte_pktmbuf_mtod_offset(mb, const struct rte_esp_hdr *, hlen);
504         sqn[0] = ph->seq;
505
506         /* cut of ICV, ESP tail and padding bytes */
507         mbuf_cut_seg_ofs(mb, ml, tofs, tlen);
508
509         /* cut of L2/L3 headers, ESP header and IV */
510         return rte_pktmbuf_adj(mb, adj);
511 }
512
513 /*
514  * step two for transport mode:
515  * - read SQN value (for future use)
516  * - cut of ICV, ESP tail and padding bytes
517  * - cut of ESP header and IV
518  * - move L2/L3 header to fill the gap after ESP header removal
519  */
520 static inline void *
521 trs_process_step2(struct rte_mbuf *mb, struct rte_mbuf *ml, uint32_t hlen,
522         uint32_t adj, uint32_t tofs, uint32_t tlen, uint32_t *sqn)
523 {
524         char *np, *op;
525
526         /* get start of the packet before modifications */
527         op = rte_pktmbuf_mtod(mb, char *);
528
529         /* cut off ESP header and IV */
530         np = tun_process_step2(mb, ml, hlen, adj, tofs, tlen, sqn);
531
532         /* move header bytes to fill the gap after ESP header removal */
533         remove_esph(np, op, hlen);
534         return np;
535 }
536
537 /*
538  * step three for transport mode:
539  * update mbuf metadata:
540  * - packet_type
541  * - ol_flags
542  */
543 static inline void
544 trs_process_step3(struct rte_mbuf *mb)
545 {
546         /* reset mbuf packet type */
547         mb->packet_type &= (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
548
549         /* clear the RTE_MBUF_F_RX_SEC_OFFLOAD flag if set */
550         mb->ol_flags &= ~RTE_MBUF_F_RX_SEC_OFFLOAD;
551 }
552
553 /*
554  * step three for tunnel mode:
555  * update mbuf metadata:
556  * - packet_type
557  * - ol_flags
558  * - tx_offload
559  */
560 static inline void
561 tun_process_step3(struct rte_mbuf *mb, uint64_t txof_msk, uint64_t txof_val)
562 {
563         /* reset mbuf metadata: L2/L3 len, packet type */
564         mb->packet_type = RTE_PTYPE_UNKNOWN;
565         mb->tx_offload = (mb->tx_offload & txof_msk) | txof_val;
566
567         /* clear the RTE_MBUF_F_RX_SEC_OFFLOAD flag if set */
568         mb->ol_flags &= ~RTE_MBUF_F_RX_SEC_OFFLOAD;
569 }
570
571 /*
572  * *process* function for tunnel packets
573  */
574 static inline uint16_t
575 tun_process(struct rte_ipsec_sa *sa, struct rte_mbuf *mb[],
576             uint32_t sqn[], uint32_t dr[], uint16_t num, uint8_t sqh_len)
577 {
578         uint32_t adj, i, k, tl, bytes;
579         uint32_t hl[num], to[num];
580         struct rte_esp_tail espt[num];
581         struct rte_mbuf *ml[num];
582         const void *outh;
583         void *inh;
584
585         /*
586          * remove icv, esp trailer and high-order
587          * 32 bits of esn from packet length
588          */
589         const uint32_t tlen = sa->icv_len + sizeof(espt[0]) + sqh_len;
590         const uint32_t cofs = sa->ctp.cipher.offset;
591
592         /*
593          * to minimize stalls due to load latency,
594          * read mbufs metadata and esp tail first.
595          */
596         for (i = 0; i != num; i++)
597                 process_step1(mb[i], tlen, &ml[i], &espt[i], &hl[i], &to[i]);
598
599         k = 0;
600         bytes = 0;
601         for (i = 0; i != num; i++) {
602
603                 adj = hl[i] + cofs;
604                 tl = tlen + espt[i].pad_len;
605
606                 /* check that packet is valid */
607                 if (tun_process_check(mb[i], &ml[i], &to[i], espt[i], adj, tl,
608                                         sa->proto) == 0) {
609
610                         outh = rte_pktmbuf_mtod_offset(mb[i], uint8_t *,
611                                         mb[i]->l2_len);
612
613                         /* modify packet's layout */
614                         inh = tun_process_step2(mb[i], ml[i], hl[i], adj,
615                                         to[i], tl, sqn + k);
616
617                         /* update inner ip header */
618                         update_tun_inb_l3hdr(sa, outh, inh);
619
620                         /* update mbuf's metadata */
621                         tun_process_step3(mb[i], sa->tx_offload.msk,
622                                 sa->tx_offload.val);
623                         k++;
624                         bytes += mb[i]->pkt_len;
625                 } else
626                         dr[i - k] = i;
627         }
628
629         sa->statistics.count += k;
630         sa->statistics.bytes += bytes;
631         return k;
632 }
633
634 /*
635  * *process* function for tunnel packets
636  */
637 static inline uint16_t
638 trs_process(struct rte_ipsec_sa *sa, struct rte_mbuf *mb[],
639         uint32_t sqn[], uint32_t dr[], uint16_t num, uint8_t sqh_len)
640 {
641         char *np;
642         uint32_t i, k, l2, tl, bytes;
643         uint32_t hl[num], to[num];
644         struct rte_esp_tail espt[num];
645         struct rte_mbuf *ml[num];
646
647         /*
648          * remove icv, esp trailer and high-order
649          * 32 bits of esn from packet length
650          */
651         const uint32_t tlen = sa->icv_len + sizeof(espt[0]) + sqh_len;
652         const uint32_t cofs = sa->ctp.cipher.offset;
653
654         /*
655          * to minimize stalls due to load latency,
656          * read mbufs metadata and esp tail first.
657          */
658         for (i = 0; i != num; i++)
659                 process_step1(mb[i], tlen, &ml[i], &espt[i], &hl[i], &to[i]);
660
661         k = 0;
662         bytes = 0;
663         for (i = 0; i != num; i++) {
664
665                 tl = tlen + espt[i].pad_len;
666                 l2 = mb[i]->l2_len;
667
668                 /* check that packet is valid */
669                 if (trs_process_check(mb[i], &ml[i], &to[i], espt[i],
670                                 hl[i] + cofs, tl) == 0) {
671
672                         /* modify packet's layout */
673                         np = trs_process_step2(mb[i], ml[i], hl[i], cofs,
674                                 to[i], tl, sqn + k);
675                         update_trs_l3hdr(sa, np + l2, mb[i]->pkt_len,
676                                 l2, hl[i] - l2, espt[i].next_proto);
677
678                         /* update mbuf's metadata */
679                         trs_process_step3(mb[i]);
680                         k++;
681                         bytes += mb[i]->pkt_len;
682                 } else
683                         dr[i - k] = i;
684         }
685
686         sa->statistics.count += k;
687         sa->statistics.bytes += bytes;
688         return k;
689 }
690
691 /*
692  * for group of ESP inbound packets perform SQN check and update.
693  */
694 static inline uint16_t
695 esp_inb_rsn_update(struct rte_ipsec_sa *sa, const uint32_t sqn[],
696         uint32_t dr[], uint16_t num)
697 {
698         uint32_t i, k;
699         struct replay_sqn *rsn;
700
701         /* replay not enabled */
702         if (sa->replay.win_sz == 0)
703                 return num;
704
705         rsn = rsn_update_start(sa);
706
707         k = 0;
708         for (i = 0; i != num; i++) {
709                 if (esn_inb_update_sqn(rsn, sa, rte_be_to_cpu_32(sqn[i])) == 0)
710                         k++;
711                 else
712                         dr[i - k] = i;
713         }
714
715         rsn_update_finish(sa, rsn);
716         return k;
717 }
718
719 /*
720  * process group of ESP inbound packets.
721  */
722 static inline uint16_t
723 esp_inb_pkt_process(struct rte_ipsec_sa *sa, struct rte_mbuf *mb[],
724         uint16_t num, uint8_t sqh_len, esp_inb_process_t process)
725 {
726         uint32_t k, n;
727         uint32_t sqn[num];
728         uint32_t dr[num];
729
730         /* process packets, extract seq numbers */
731         k = process(sa, mb, sqn, dr, num, sqh_len);
732
733         /* handle unprocessed mbufs */
734         if (k != num && k != 0)
735                 move_bad_mbufs(mb, dr, num, num - k);
736
737         /* update SQN and replay window */
738         n = esp_inb_rsn_update(sa, sqn, dr, k);
739
740         /* handle mbufs with wrong SQN */
741         if (n != k && n != 0)
742                 move_bad_mbufs(mb, dr, k, k - n);
743
744         if (n != num)
745                 rte_errno = EBADMSG;
746
747         return n;
748 }
749
750 /*
751  * Prepare (plus actual crypto/auth) routine for inbound CPU-CRYPTO
752  * (synchronous mode).
753  */
754 uint16_t
755 cpu_inb_pkt_prepare(const struct rte_ipsec_session *ss,
756         struct rte_mbuf *mb[], uint16_t num)
757 {
758         int32_t rc;
759         uint32_t i, k;
760         struct rte_ipsec_sa *sa;
761         struct replay_sqn *rsn;
762         union sym_op_data icv;
763         struct rte_crypto_va_iova_ptr iv[num];
764         struct rte_crypto_va_iova_ptr aad[num];
765         struct rte_crypto_va_iova_ptr dgst[num];
766         uint32_t dr[num];
767         uint32_t l4ofs[num];
768         uint32_t clen[num];
769         uint64_t ivbuf[num][IPSEC_MAX_IV_QWORD];
770
771         sa = ss->sa;
772
773         /* grab rsn lock */
774         rsn = rsn_acquire(sa);
775
776         /* do preparation for all packets */
777         for (i = 0, k = 0; i != num; i++) {
778
779                 /* calculate ESP header offset */
780                 l4ofs[k] = mb[i]->l2_len + mb[i]->l3_len;
781
782                 /* prepare ESP packet for processing */
783                 rc = inb_pkt_prepare(sa, rsn, mb[i], l4ofs[k], &icv);
784                 if (rc >= 0) {
785                         /* get encrypted data offset and length */
786                         clen[k] = inb_cpu_crypto_prepare(sa, mb[i],
787                                 l4ofs + k, rc, ivbuf[k]);
788
789                         /* fill iv, digest and aad */
790                         iv[k].va = ivbuf[k];
791                         aad[k].va = icv.va + sa->icv_len;
792                         dgst[k++].va = icv.va;
793                 } else {
794                         dr[i - k] = i;
795                         rte_errno = -rc;
796                 }
797         }
798
799         /* release rsn lock */
800         rsn_release(sa, rsn);
801
802         /* copy not prepared mbufs beyond good ones */
803         if (k != num && k != 0)
804                 move_bad_mbufs(mb, dr, num, num - k);
805
806         /* convert mbufs to iovecs and do actual crypto/auth processing */
807         if (k != 0)
808                 cpu_crypto_bulk(ss, sa->cofs, mb, iv, aad, dgst,
809                         l4ofs, clen, k);
810         return k;
811 }
812
813 /*
814  * process group of ESP inbound tunnel packets.
815  */
816 uint16_t
817 esp_inb_tun_pkt_process(const struct rte_ipsec_session *ss,
818         struct rte_mbuf *mb[], uint16_t num)
819 {
820         struct rte_ipsec_sa *sa = ss->sa;
821
822         return esp_inb_pkt_process(sa, mb, num, sa->sqh_len, tun_process);
823 }
824
825 uint16_t
826 inline_inb_tun_pkt_process(const struct rte_ipsec_session *ss,
827         struct rte_mbuf *mb[], uint16_t num)
828 {
829         return esp_inb_pkt_process(ss->sa, mb, num, 0, tun_process);
830 }
831
832 /*
833  * process group of ESP inbound transport packets.
834  */
835 uint16_t
836 esp_inb_trs_pkt_process(const struct rte_ipsec_session *ss,
837         struct rte_mbuf *mb[], uint16_t num)
838 {
839         struct rte_ipsec_sa *sa = ss->sa;
840
841         return esp_inb_pkt_process(sa, mb, num, sa->sqh_len, trs_process);
842 }
843
844 uint16_t
845 inline_inb_trs_pkt_process(const struct rte_ipsec_session *ss,
846         struct rte_mbuf *mb[], uint16_t num)
847 {
848         return esp_inb_pkt_process(ss->sa, mb, num, 0, trs_process);
849 }