FD.io VPP  v18.04-17-g3a0d853
Vector Packet Processing
ipsec.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Intel and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <vnet/vnet.h>
16 #include <vnet/ip/ip.h>
17 #include <vnet/api_errno.h>
18 #include <vnet/ipsec/ipsec.h>
19 #include <vlib/node_funcs.h>
20 
21 #include <dpdk/device/dpdk.h>
22 #include <dpdk/ipsec/ipsec.h>
23 
25 
26 #define EMPTY_STRUCT {0}
27 
28 static void
29 algos_init (u32 n_mains)
30 {
32  crypto_alg_t *a;
33 
35 
36  {
37 #define _(v,f,str) \
38  dcm->cipher_algs[IPSEC_CRYPTO_ALG_##f].name = str; \
39  dcm->cipher_algs[IPSEC_CRYPTO_ALG_##f].disabled = n_mains;
41 #undef _
42  }
43 
44  /* Minimum boundary for ciphers is 4B, required by ESP */
45  a = &dcm->cipher_algs[IPSEC_CRYPTO_ALG_NONE];
46  a->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
47  a->alg = RTE_CRYPTO_CIPHER_NULL;
48  a->boundary = 4; /* 1 */
49  a->key_len = 0;
50  a->iv_len = 0;
51 
52  a = &dcm->cipher_algs[IPSEC_CRYPTO_ALG_AES_CBC_128];
53  a->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
54  a->alg = RTE_CRYPTO_CIPHER_AES_CBC;
55  a->boundary = 16;
56  a->key_len = 16;
57  a->iv_len = 16;
58 
59  a = &dcm->cipher_algs[IPSEC_CRYPTO_ALG_AES_CBC_192];
60  a->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
61  a->alg = RTE_CRYPTO_CIPHER_AES_CBC;
62  a->boundary = 16;
63  a->key_len = 24;
64  a->iv_len = 16;
65 
66  a = &dcm->cipher_algs[IPSEC_CRYPTO_ALG_AES_CBC_256];
67  a->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
68  a->alg = RTE_CRYPTO_CIPHER_AES_CBC;
69  a->boundary = 16;
70  a->key_len = 32;
71  a->iv_len = 16;
72 
73  a = &dcm->cipher_algs[IPSEC_CRYPTO_ALG_AES_CTR_128];
74  a->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
75  a->alg = RTE_CRYPTO_CIPHER_AES_CTR;
76  a->boundary = 4; /* 1 */
77  a->key_len = 16;
78  a->iv_len = 8;
79 
80  a = &dcm->cipher_algs[IPSEC_CRYPTO_ALG_AES_CTR_192];
81  a->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
82  a->alg = RTE_CRYPTO_CIPHER_AES_CTR;
83  a->boundary = 4; /* 1 */
84  a->key_len = 24;
85  a->iv_len = 8;
86 
87  a = &dcm->cipher_algs[IPSEC_CRYPTO_ALG_AES_CTR_256];
88  a->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
89  a->alg = RTE_CRYPTO_CIPHER_AES_CTR;
90  a->boundary = 4; /* 1 */
91  a->key_len = 32;
92  a->iv_len = 8;
93 
94 #define AES_GCM_TYPE RTE_CRYPTO_SYM_XFORM_AEAD
95 #define AES_GCM_ALG RTE_CRYPTO_AEAD_AES_GCM
96 
97  a = &dcm->cipher_algs[IPSEC_CRYPTO_ALG_AES_GCM_128];
98  a->type = AES_GCM_TYPE;
99  a->alg = AES_GCM_ALG;
100  a->boundary = 4; /* 1 */
101  a->key_len = 16;
102  a->iv_len = 8;
103  a->trunc_size = 16;
104 
105  a = &dcm->cipher_algs[IPSEC_CRYPTO_ALG_AES_GCM_192];
106  a->type = AES_GCM_TYPE;
107  a->alg = AES_GCM_ALG;
108  a->boundary = 4; /* 1 */
109  a->key_len = 24;
110  a->iv_len = 8;
111  a->trunc_size = 16;
112 
113  a = &dcm->cipher_algs[IPSEC_CRYPTO_ALG_AES_GCM_256];
114  a->type = AES_GCM_TYPE;
115  a->alg = AES_GCM_ALG;
116  a->boundary = 4; /* 1 */
117  a->key_len = 32;
118  a->iv_len = 8;
119  a->trunc_size = 16;
120 
122 
123  {
124 #define _(v,f,str) \
125  dcm->auth_algs[IPSEC_INTEG_ALG_##f].name = str; \
126  dcm->auth_algs[IPSEC_INTEG_ALG_##f].disabled = n_mains;
128 #undef _
129  }
130 
131  a = &dcm->auth_algs[IPSEC_INTEG_ALG_NONE];
132  a->type = RTE_CRYPTO_SYM_XFORM_AUTH;
133  a->alg = RTE_CRYPTO_AUTH_NULL;
134  a->key_len = 0;
135  a->trunc_size = 0;
136 
137  a = &dcm->auth_algs[IPSEC_INTEG_ALG_MD5_96];
138  a->type = RTE_CRYPTO_SYM_XFORM_AUTH;
139  a->alg = RTE_CRYPTO_AUTH_MD5_HMAC;
140  a->key_len = 16;
141  a->trunc_size = 12;
142 
143  a = &dcm->auth_algs[IPSEC_INTEG_ALG_SHA1_96];
144  a->type = RTE_CRYPTO_SYM_XFORM_AUTH;
145  a->alg = RTE_CRYPTO_AUTH_SHA1_HMAC;
146  a->key_len = 20;
147  a->trunc_size = 12;
148 
149  a = &dcm->auth_algs[IPSEC_INTEG_ALG_SHA_256_96];
150  a->type = RTE_CRYPTO_SYM_XFORM_AUTH;
151  a->alg = RTE_CRYPTO_AUTH_SHA256_HMAC;
152  a->key_len = 32;
153  a->trunc_size = 12;
154 
155  a = &dcm->auth_algs[IPSEC_INTEG_ALG_SHA_256_128];
156  a->type = RTE_CRYPTO_SYM_XFORM_AUTH;
157  a->alg = RTE_CRYPTO_AUTH_SHA256_HMAC;
158  a->key_len = 32;
159  a->trunc_size = 16;
160 
161  a = &dcm->auth_algs[IPSEC_INTEG_ALG_SHA_384_192];
162  a->type = RTE_CRYPTO_SYM_XFORM_AUTH;
163  a->alg = RTE_CRYPTO_AUTH_SHA384_HMAC;
164  a->key_len = 48;
165  a->trunc_size = 24;
166 
167  a = &dcm->auth_algs[IPSEC_INTEG_ALG_SHA_512_256];
168  a->type = RTE_CRYPTO_SYM_XFORM_AUTH;
169  a->alg = RTE_CRYPTO_AUTH_SHA512_HMAC;
170  a->key_len = 64;
171  a->trunc_size = 32;
172 }
173 
174 static u8
176 {
178 
179  return (alg - dcm->cipher_algs);
180 }
181 
182 static u8
184 {
186 
187  return (alg - dcm->auth_algs);
188 }
189 
190 static crypto_alg_t *
191 cipher_cap_to_alg (const struct rte_cryptodev_capabilities *cap, u8 key_len)
192 {
194  crypto_alg_t *alg;
195 
196  if (cap->op != RTE_CRYPTO_OP_TYPE_SYMMETRIC)
197  return NULL;
198 
199  /* *INDENT-OFF* */
200  vec_foreach (alg, dcm->cipher_algs)
201  {
202  if ((cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_CIPHER) &&
203  (alg->type == RTE_CRYPTO_SYM_XFORM_CIPHER) &&
204  (cap->sym.cipher.algo == alg->alg) &&
205  (alg->key_len == key_len))
206  return alg;
207  if ((cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_AEAD) &&
208  (alg->type == RTE_CRYPTO_SYM_XFORM_AEAD) &&
209  (cap->sym.aead.algo == alg->alg) &&
210  (alg->key_len == key_len))
211  return alg;
212  }
213  /* *INDENT-ON* */
214 
215  return NULL;
216 }
217 
218 static crypto_alg_t *
219 auth_cap_to_alg (const struct rte_cryptodev_capabilities *cap, u8 trunc_size)
220 {
222  crypto_alg_t *alg;
223 
224  if ((cap->op != RTE_CRYPTO_OP_TYPE_SYMMETRIC) ||
225  (cap->sym.xform_type != RTE_CRYPTO_SYM_XFORM_AUTH))
226  return NULL;
227 
228  /* *INDENT-OFF* */
229  vec_foreach (alg, dcm->auth_algs)
230  {
231  if ((cap->sym.auth.algo == alg->alg) &&
232  (alg->trunc_size == trunc_size))
233  return alg;
234  }
235  /* *INDENT-ON* */
236 
237  return NULL;
238 }
239 
240 static void
241 crypto_set_aead_xform (struct rte_crypto_sym_xform *xform,
242  ipsec_sa_t * sa, u8 is_outbound)
243 {
245  crypto_alg_t *c;
246 
247  c = vec_elt_at_index (dcm->cipher_algs, sa->crypto_alg);
248 
249  ASSERT (c->type == RTE_CRYPTO_SYM_XFORM_AEAD);
250 
251  xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
252  xform->aead.algo = c->alg;
253  xform->aead.key.data = sa->crypto_key;
254  xform->aead.key.length = c->key_len;
255  xform->aead.iv.offset =
256  crypto_op_get_priv_offset () + offsetof (dpdk_op_priv_t, cb);
257  xform->aead.iv.length = 12;
258  xform->aead.digest_length = c->trunc_size;
259  xform->aead.aad_length = sa->use_esn ? 12 : 8;
260  xform->next = NULL;
261 
262  if (is_outbound)
263  xform->aead.op = RTE_CRYPTO_AEAD_OP_ENCRYPT;
264  else
265  xform->aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
266 }
267 
268 static void
269 crypto_set_cipher_xform (struct rte_crypto_sym_xform *xform,
270  ipsec_sa_t * sa, u8 is_outbound)
271 {
273  crypto_alg_t *c;
274 
275  c = vec_elt_at_index (dcm->cipher_algs, sa->crypto_alg);
276 
277  ASSERT (c->type == RTE_CRYPTO_SYM_XFORM_CIPHER);
278 
279  xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
280  xform->cipher.algo = c->alg;
281  xform->cipher.key.data = sa->crypto_key;
282  xform->cipher.key.length = c->key_len;
283  xform->cipher.iv.offset =
284  crypto_op_get_priv_offset () + offsetof (dpdk_op_priv_t, cb);
285  xform->cipher.iv.length = c->iv_len;
286  xform->next = NULL;
287 
288  if (is_outbound)
289  xform->cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
290  else
291  xform->cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
292 }
293 
294 static void
295 crypto_set_auth_xform (struct rte_crypto_sym_xform *xform,
296  ipsec_sa_t * sa, u8 is_outbound)
297 {
299  crypto_alg_t *a;
300 
301  a = vec_elt_at_index (dcm->auth_algs, sa->integ_alg);
302 
303  ASSERT (a->type == RTE_CRYPTO_SYM_XFORM_AUTH);
304 
305  xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
306  xform->auth.algo = a->alg;
307  xform->auth.key.data = sa->integ_key;
308  xform->auth.key.length = a->key_len;
309  xform->auth.digest_length = a->trunc_size;
310  xform->next = NULL;
311 
312  if (is_outbound)
313  xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
314  else
315  xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
316 }
317 
318 clib_error_t *
319 create_sym_session (struct rte_cryptodev_sym_session **session,
320  u32 sa_idx,
321  crypto_resource_t * res,
322  crypto_worker_main_t * cwm, u8 is_outbound)
323 {
325  ipsec_main_t *im = &ipsec_main;
326  crypto_data_t *data;
327  ipsec_sa_t *sa;
328  struct rte_crypto_sym_xform cipher_xform = { 0 };
329  struct rte_crypto_sym_xform auth_xform = { 0 };
330  struct rte_crypto_sym_xform *xfs;
331  struct rte_cryptodev_sym_session **s;
332  crypto_session_key_t key = { 0 };
333  clib_error_t *erorr = 0;
334 
335  key.drv_id = res->drv_id;
336  key.sa_idx = sa_idx;
337 
338  sa = pool_elt_at_index (im->sad, sa_idx);
339 
340  if ((sa->crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128) |
341  (sa->crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_192) |
342  (sa->crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_256))
343  {
344  crypto_set_aead_xform (&cipher_xform, sa, is_outbound);
345  xfs = &cipher_xform;
346  }
347  else
348  {
349  crypto_set_cipher_xform (&cipher_xform, sa, is_outbound);
350  crypto_set_auth_xform (&auth_xform, sa, is_outbound);
351 
352  if (is_outbound)
353  {
354  cipher_xform.next = &auth_xform;
355  xfs = &cipher_xform;
356  }
357  else
358  {
359  auth_xform.next = &cipher_xform;
360  xfs = &auth_xform;
361  }
362  }
363 
364  data = vec_elt_at_index (dcm->data, res->numa);
366 
367  /*
368  * DPDK_VER >= 1708:
369  * Multiple worker/threads share the session for an SA
370  * Single session per SA, initialized for each device driver
371  */
372  s = (void *) hash_get (data->session_by_sa_index, sa_idx);
373 
374  if (!s)
375  {
376  session[0] = rte_cryptodev_sym_session_create (data->session_h);
377  if (!session[0])
378  {
379  data->session_h_failed += 1;
380  erorr = clib_error_return (0, "failed to create session header");
381  goto done;
382  }
383  hash_set (data->session_by_sa_index, sa_idx, session[0]);
384  }
385  else
386  session[0] = s[0];
387 
388  struct rte_mempool **mp;
389  mp = vec_elt_at_index (data->session_drv, res->drv_id);
390  ASSERT (mp[0] != NULL);
391 
392  i32 ret =
393  rte_cryptodev_sym_session_init (res->dev_id, session[0], xfs, mp[0]);
394  if (ret)
395  {
396  data->session_drv_failed[res->drv_id] += 1;
397  erorr = clib_error_return (0, "failed to init session for drv %u",
398  res->drv_id);
399  goto done;
400  }
401 
402  hash_set (data->session_by_drv_id_and_sa_index, key.val, session[0]);
403 
404 done:
406  return erorr;
407 }
408 
409 static void __attribute__ ((unused)) clear_and_free_obj (void *obj)
410 {
411  struct rte_mempool *mp = rte_mempool_from_obj (obj);
412 
413  memset (obj, 0, mp->elt_size);
414 
415  rte_mempool_put (mp, obj);
416 }
417 
418 /* This is from rte_cryptodev_pmd.h */
419 static inline void *
420 get_session_private_data (const struct rte_cryptodev_sym_session *sess,
421  uint8_t driver_id)
422 {
423  return sess->sess_private_data[driver_id];
424 }
425 
426 /* This is from rte_cryptodev_pmd.h */
427 static inline void
428 set_session_private_data (struct rte_cryptodev_sym_session *sess,
429  uint8_t driver_id, void *private_data)
430 {
431  sess->sess_private_data[driver_id] = private_data;
432 }
433 
434 static clib_error_t *
436 {
439  void *drv_session;
440  u32 drv_id;
441  i32 ret;
442 
443  /* *INDENT-OFF* */
444  vec_foreach (s, v)
445  {
446  /* ordered vector by timestamp */
447  if (!(s->ts + dcm->session_timeout < ts))
448  break;
449 
450  vec_foreach_index (drv_id, dcm->drv)
451  {
452  drv_session = get_session_private_data (s->session, drv_id);
453  if (!drv_session)
454  continue;
455 
456  /*
457  * Custom clear to avoid finding a dev_id for drv_id:
458  * ret = rte_cryptodev_sym_session_clear (dev_id, drv_session);
459  * ASSERT (!ret);
460  */
461  clear_and_free_obj (drv_session);
462 
463  set_session_private_data (s->session, drv_id, NULL);
464  }
465 
466  if (rte_mempool_from_obj(s->session))
467  {
468  ret = rte_cryptodev_sym_session_free (s->session);
469  ASSERT (!ret);
470  }
471  }
472  /* *INDENT-ON* */
473 
474  if (s < vec_end (v))
475  vec_delete (v, s - v, 0);
476  else
477  vec_reset_length (v);
478 
479  return 0;
480 }
481 
482 static clib_error_t *
483 add_del_sa_session (u32 sa_index, u8 is_add)
484 {
485  ipsec_main_t *im = &ipsec_main;
487  crypto_data_t *data;
488  struct rte_cryptodev_sym_session *s;
489  crypto_session_key_t key = { 0 };
490  uword *val;
491  u32 drv_id;
492 
493  if (is_add)
494  {
495 #if 1
496  ipsec_sa_t *sa = pool_elt_at_index (im->sad, sa_index);
497  u32 seed;
498  switch (sa->crypto_alg)
499  {
500  case IPSEC_CRYPTO_ALG_AES_GCM_128:
501  case IPSEC_CRYPTO_ALG_AES_GCM_192:
502  case IPSEC_CRYPTO_ALG_AES_GCM_256:
503  clib_memcpy (&sa->salt, &sa->crypto_key[sa->crypto_key_len - 4], 4);
504  break;
505  default:
506  seed = (u32) clib_cpu_time_now ();
507  sa->salt = random_u32 (&seed);
508  }
509 #endif
510  return 0;
511  }
512 
513  key.sa_idx = sa_index;
514 
515  /* *INDENT-OFF* */
516  vec_foreach (data, dcm->data)
517  {
519  val = hash_get (data->session_by_sa_index, sa_index);
520  s = (struct rte_cryptodev_sym_session *) val;
521  if (s)
522  {
523  vec_foreach_index (drv_id, dcm->drv)
524  {
525  key.drv_id = drv_id;
526  val = hash_get (data->session_by_drv_id_and_sa_index, key.val);
527  s = (struct rte_cryptodev_sym_session *) val;
528  if (s)
530  }
531 
532  hash_unset (data->session_by_sa_index, sa_index);
533 
534  u64 ts = unix_time_now_nsec ();
536 
538  sd.ts = ts;
539  sd.session = s;
540 
541  vec_add1 (data->session_disposal, sd);
542  }
544  }
545  /* *INDENT-ON* */
546 
547  return 0;
548 }
549 
550 static clib_error_t *
552 {
554 
555  if (sa->integ_alg == IPSEC_INTEG_ALG_NONE)
556  switch (sa->crypto_alg)
557  {
558  case IPSEC_CRYPTO_ALG_AES_GCM_128:
559  case IPSEC_CRYPTO_ALG_AES_GCM_192:
560  case IPSEC_CRYPTO_ALG_AES_GCM_256:
561  break;
562  default:
563  return clib_error_return (0, "unsupported integ-alg %U crypto-alg %U",
566  }
567 
568  /* XXX do we need the NONE check? */
569  if (sa->crypto_alg != IPSEC_CRYPTO_ALG_NONE &&
570  dcm->cipher_algs[sa->crypto_alg].disabled)
571  return clib_error_return (0, "disabled crypto-alg %U",
573 
574  /* XXX do we need the NONE check? */
575  if (sa->integ_alg != IPSEC_INTEG_ALG_NONE &&
576  dcm->auth_algs[sa->integ_alg].disabled)
577  return clib_error_return (0, "disabled integ-alg %U",
579  return NULL;
580 }
581 
582 static void
584  const struct rte_cryptodev_capabilities *cap,
585  u32 n_mains)
586 {
588  crypto_alg_t *alg;
589  u8 len, inc;
590 
591  for (; cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED; cap++)
592  {
593  /* A single capability maps to multiple cipher/auth algorithms */
594  switch (cap->sym.xform_type)
595  {
596  case RTE_CRYPTO_SYM_XFORM_AEAD:
597  case RTE_CRYPTO_SYM_XFORM_CIPHER:
598  inc = cap->sym.cipher.key_size.increment;
599  inc = inc ? inc : 1;
600  for (len = cap->sym.cipher.key_size.min;
601  len <= cap->sym.cipher.key_size.max; len += inc)
602  {
603  alg = cipher_cap_to_alg (cap, len);
604  if (!alg)
605  continue;
606  dev->cipher_support[cipher_alg_index (alg)] = 1;
607  alg->resources += vec_len (dev->free_resources);
608  /* At least enough resources to support one algo */
609  dcm->enabled |= (alg->resources >= n_mains);
610  }
611  break;
612  case RTE_CRYPTO_SYM_XFORM_AUTH:
613  inc = cap->sym.auth.digest_size.increment;
614  inc = inc ? inc : 1;
615  for (len = cap->sym.auth.digest_size.min;
616  len <= cap->sym.auth.digest_size.max; len += inc)
617  {
618  alg = auth_cap_to_alg (cap, len);
619  if (!alg)
620  continue;
621  dev->auth_support[auth_alg_index (alg)] = 1;
622  alg->resources += vec_len (dev->free_resources);
623  /* At least enough resources to support one algo */
624  dcm->enabled |= (alg->resources >= n_mains);
625  }
626  break;
627  default:
628  ;
629  }
630  }
631 }
632 
633 #define DPDK_CRYPTO_N_QUEUE_DESC 2048
634 #define DPDK_CRYPTO_NB_SESS_OBJS 20000
635 
636 static clib_error_t *
637 crypto_dev_conf (u8 dev, u16 n_qp, u8 numa)
638 {
639  struct rte_cryptodev_config dev_conf;
640  struct rte_cryptodev_qp_conf qp_conf;
641  i32 ret;
642  u16 qp;
643  i8 *error_str;
644 
645  dev_conf.socket_id = numa;
646  dev_conf.nb_queue_pairs = n_qp;
647 
648  error_str = "failed to configure crypto device %u";
649  ret = rte_cryptodev_configure (dev, &dev_conf);
650  if (ret < 0)
651  return clib_error_return (0, error_str, dev);
652 
653  error_str = "failed to setup crypto device %u queue pair %u";
654  qp_conf.nb_descriptors = DPDK_CRYPTO_N_QUEUE_DESC;
655  for (qp = 0; qp < n_qp; qp++)
656  {
657  ret = rte_cryptodev_queue_pair_setup (dev, qp, &qp_conf, numa, NULL);
658  if (ret < 0)
659  return clib_error_return (0, error_str, dev, qp);
660  }
661 
662  return 0;
663 }
664 
665 static void
667 {
669  struct rte_cryptodev *cryptodev;
670  struct rte_cryptodev_info info;
671  crypto_dev_t *dev;
672  crypto_resource_t *res;
673  clib_error_t *error;
674  u32 i;
675  u16 max_res_idx, res_idx, j;
676  u8 drv_id;
677 
678  vec_validate_init_empty (dcm->dev, rte_cryptodev_count () - 1,
680 
681  for (i = 0; i < rte_cryptodev_count (); i++)
682  {
683  dev = vec_elt_at_index (dcm->dev, i);
684 
685  cryptodev = &rte_cryptodevs[i];
686  rte_cryptodev_info_get (i, &info);
687 
688  dev->id = i;
689  dev->name = cryptodev->data->name;
690  dev->numa = rte_cryptodev_socket_id (i);
691  dev->features = info.feature_flags;
692  dev->max_qp = info.max_nb_queue_pairs;
693  drv_id = info.driver_id;
694  if (drv_id >= vec_len (dcm->drv))
695  vec_validate_init_empty (dcm->drv, drv_id,
696  (crypto_drv_t) EMPTY_STRUCT);
697  vec_elt_at_index (dcm->drv, drv_id)->name = info.driver_name;
698  dev->drv_id = drv_id;
699  vec_add1 (vec_elt_at_index (dcm->drv, drv_id)->devs, i);
700 
701  if (!(info.feature_flags & RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING))
702  continue;
703 
704  if ((error = crypto_dev_conf (i, dev->max_qp, dev->numa)))
705  {
706  clib_error_report (error);
707  continue;
708  }
709 
710  max_res_idx = (dev->max_qp / 2) - 1;
711 
712  vec_validate (dev->free_resources, max_res_idx);
713 
714  res_idx = vec_len (dcm->resource);
715  vec_validate_init_empty_aligned (dcm->resource, res_idx + max_res_idx,
716  (crypto_resource_t) EMPTY_STRUCT,
718 
719  for (j = 0; j <= max_res_idx; j++, res_idx++)
720  {
721  vec_elt (dev->free_resources, max_res_idx - j) = res_idx;
722  res = &dcm->resource[res_idx];
723  res->dev_id = i;
724  res->drv_id = drv_id;
725  res->qp_id = j * 2;
726  res->numa = dev->numa;
727  res->thread_idx = (u16) ~ 0;
728  }
729 
730  crypto_parse_capabilities (dev, info.capabilities, n_mains);
731  }
732 }
733 
734 void
736 {
738  crypto_resource_t *res;
740  crypto_dev_t *dev;
741  u32 thread_idx, skip_master;
742  u16 res_idx, *idx;
743  u8 used;
744  u16 i;
745 
746  skip_master = vlib_num_workers () > 0;
747 
748  /* *INDENT-OFF* */
749  vec_foreach (dev, dcm->dev)
750  {
751  vec_foreach_index (thread_idx, dcm->workers_main)
752  {
753  if (vec_len (dev->free_resources) == 0)
754  break;
755 
756  if (thread_idx < skip_master)
757  continue;
758 
759  /* Check thread is not already using the device */
760  vec_foreach (idx, dev->used_resources)
761  if (dcm->resource[idx[0]].thread_idx == thread_idx)
762  continue;
763 
764  cwm = vec_elt_at_index (dcm->workers_main, thread_idx);
765 
766  used = 0;
767  res_idx = vec_pop (dev->free_resources);
768 
769  /* Set device only for supported algos */
770  for (i = 0; i < IPSEC_CRYPTO_N_ALG; i++)
771  if (dev->cipher_support[i] &&
772  cwm->cipher_resource_idx[i] == (u16) ~0)
773  {
774  dcm->cipher_algs[i].disabled--;
775  cwm->cipher_resource_idx[i] = res_idx;
776  used = 1;
777  }
778 
779  for (i = 0; i < IPSEC_INTEG_N_ALG; i++)
780  if (dev->auth_support[i] &&
781  cwm->auth_resource_idx[i] == (u16) ~0)
782  {
783  dcm->auth_algs[i].disabled--;
784  cwm->auth_resource_idx[i] = res_idx;
785  used = 1;
786  }
787 
788  if (!used)
789  {
790  vec_add1 (dev->free_resources, res_idx);
791  continue;
792  }
793 
794  vec_add1 (dev->used_resources, res_idx);
795 
796  res = vec_elt_at_index (dcm->resource, res_idx);
797 
798  ASSERT (res->thread_idx == (u16) ~0);
799  res->thread_idx = thread_idx;
800 
801  /* Add device to vector of polling resources */
802  vec_add1 (cwm->resource_idx, res_idx);
803  }
804  }
805  /* *INDENT-ON* */
806 }
807 
808 static void
809 crypto_op_init (struct rte_mempool *mempool,
810  void *_arg __attribute__ ((unused)),
811  void *_obj, unsigned i __attribute__ ((unused)))
812 {
813  struct rte_crypto_op *op = _obj;
814 
815  op->sess_type = RTE_CRYPTO_OP_WITH_SESSION;
816  op->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
817  op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
818  op->phys_addr = rte_mempool_virt2iova (_obj);
819  op->mempool = mempool;
820 }
821 
822 static clib_error_t *
824 {
827  crypto_data_t *data;
828  u8 *pool_name;
829  u32 pool_priv_size = sizeof (struct rte_crypto_op_pool_private);
830  struct rte_crypto_op_pool_private *priv;
831  struct rte_mempool *mp;
832  clib_error_t *error = NULL;
834 
835  data = vec_elt_at_index (dcm->data, numa);
836 
837  /* Already allocated */
838  if (data->crypto_op)
839  return NULL;
840 
841  pool_name = format (0, "crypto_pool_numa%u%c", numa, 0);
842 
843  error =
844  dpdk_pool_create (vm, pool_name, crypto_op_len (), conf->num_mbufs,
845  pool_priv_size, 512, numa, &mp, &pri);
846 
847  vec_free (pool_name);
848 
849  if (error)
850  return error;
851 
852  /* Initialize mempool private data */
853  priv = rte_mempool_get_priv (mp);
854  priv->priv_size = pool_priv_size;
855  priv->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
856 
857  /* call the object initializers */
858  rte_mempool_obj_iter (mp, crypto_op_init, 0);
859 
860  data->crypto_op = mp;
861 
862  return NULL;
863 }
864 
865 static clib_error_t *
867 {
869  crypto_data_t *data;
870  u8 *pool_name;
871  struct rte_mempool *mp;
872  clib_error_t *error = NULL;
874  u32 elt_size;
875 
876  data = vec_elt_at_index (dcm->data, numa);
877 
878  if (data->session_h)
879  return NULL;
880 
881  pool_name = format (0, "session_h_pool_numa%u%c", numa, 0);
882 
883  elt_size = rte_cryptodev_get_header_session_size ();
884 
885  error =
886  dpdk_pool_create (vm, pool_name, elt_size, DPDK_CRYPTO_NB_SESS_OBJS,
887  0, 512, numa, &mp, &pri);
888 
889  vec_free (pool_name);
890 
891  if (error)
892  return error;
893 
894  data->session_h = mp;
895 
896  return NULL;
897 }
898 
899 static clib_error_t *
901 {
903  crypto_data_t *data;
904  u8 *pool_name;
905  struct rte_mempool *mp;
906  clib_error_t *error = NULL;
908  u32 elt_size;
909  u8 numa = dev->numa;
910 
911  data = vec_elt_at_index (dcm->data, numa);
912 
913  vec_validate (data->session_drv, dev->drv_id);
914  vec_validate (data->session_drv_failed, dev->drv_id);
915 
916  if (data->session_drv[dev->drv_id])
917  return NULL;
918 
919  pool_name = format (0, "session_drv%u_pool_numa%u%c", dev->drv_id, numa, 0);
920  elt_size = rte_cryptodev_get_private_session_size (dev->id);
921 
922  error =
923  dpdk_pool_create (vm, pool_name, elt_size, DPDK_CRYPTO_NB_SESS_OBJS,
924  0, 512, numa, &mp, &pri);
925 
926  vec_free (pool_name);
927 
928  if (error)
929  return error;
930 
931  data->session_drv[dev->drv_id] = mp;
932  clib_spinlock_init (&data->lockp);
933 
934  return NULL;
935 }
936 
937 static clib_error_t *
939 {
941  clib_error_t *error = NULL;
942  crypto_dev_t *dev;
943 
944  /* *INDENT-OFF* */
945  vec_foreach (dev, dcm->dev)
946  {
948 
949  error = crypto_create_crypto_op_pool (vm, dev->numa);
950  if (error)
951  return error;
952 
953  error = crypto_create_session_h_pool (vm, dev->numa);
954  if (error)
955  return error;
956 
957  error = crypto_create_session_drv_pool (vm, dev);
958  if (error)
959  return error;
960  }
961  /* *INDENT-ON* */
962 
963  return NULL;
964 }
965 
966 static void
968 {
970  crypto_data_t *data;
971  u8 i;
972 
973  dcm->enabled = 0;
974 
975  /* *INDENT-OFF* */
976  vec_foreach (data, dcm->data)
977  {
978  rte_mempool_free (data->crypto_op);
979  rte_mempool_free (data->session_h);
980 
981  vec_foreach_index (i, data->session_drv)
982  rte_mempool_free (data->session_drv[i]);
983 
984  vec_free (data->session_drv);
985  clib_spinlock_free (&data->lockp);
986  }
987  /* *INDENT-ON* */
988 
989  vec_free (dcm->data);
990  vec_free (dcm->workers_main);
991  vec_free (dcm->sa_session);
992  vec_free (dcm->dev);
993  vec_free (dcm->resource);
994  vec_free (dcm->cipher_algs);
995  vec_free (dcm->auth_algs);
996 }
997 
998 static uword
1000  vlib_frame_t * f)
1001 {
1002  ipsec_main_t *im = &ipsec_main;
1005  crypto_worker_main_t *cwm;
1006  clib_error_t *error = NULL;
1007  u32 i, skip_master, n_mains;
1008 
1009  n_mains = tm->n_vlib_mains;
1010  skip_master = vlib_num_workers () > 0;
1011 
1012  algos_init (n_mains - skip_master);
1013 
1014  crypto_scan_devs (n_mains - skip_master);
1015 
1016  if (!(dcm->enabled))
1017  {
1018  clib_warning ("not enough DPDK crypto resources, default to OpenSSL");
1019  crypto_disable ();
1020  return 0;
1021  }
1022 
1023  dcm->session_timeout = 10e9;
1024 
1025  vec_validate_init_empty_aligned (dcm->workers_main, n_mains - 1,
1028 
1029  /* *INDENT-OFF* */
1030  vec_foreach (cwm, dcm->workers_main)
1031  {
1034  memset (cwm->cipher_resource_idx, ~0,
1035  IPSEC_CRYPTO_N_ALG * sizeof(*cwm->cipher_resource_idx));
1036  memset (cwm->auth_resource_idx, ~0,
1037  IPSEC_INTEG_N_ALG * sizeof(*cwm->auth_resource_idx));
1038  }
1039  /* *INDENT-ON* */
1040 
1042 
1043  error = crypto_create_pools (vm);
1044  if (error)
1045  {
1046  clib_error_report (error);
1047  crypto_disable ();
1048  return 0;
1049  }
1050 
1051  /* Add new next node and set it as default */
1052  vlib_node_t *node, *next_node;
1053 
1054  next_node = vlib_get_node_by_name (vm, (u8 *) "dpdk-esp-encrypt");
1055  ASSERT (next_node);
1056  node = vlib_get_node_by_name (vm, (u8 *) "ipsec-output-ip4");
1057  ASSERT (node);
1058  im->esp_encrypt_node_index = next_node->index;
1060  vlib_node_add_next (vm, node->index, next_node->index);
1061 
1062  next_node = vlib_get_node_by_name (vm, (u8 *) "dpdk-esp-decrypt");
1063  ASSERT (next_node);
1064  node = vlib_get_node_by_name (vm, (u8 *) "ipsec-input-ip4");
1065  ASSERT (node);
1066  im->esp_decrypt_node_index = next_node->index;
1068  vlib_node_add_next (vm, node->index, next_node->index);
1069 
1072 
1073  node = vlib_get_node_by_name (vm, (u8 *) "dpdk-crypto-input");
1074  ASSERT (node);
1075  for (i = skip_master; i < n_mains; i++)
1076  vlib_node_set_state (vlib_mains[i], node->index, VLIB_NODE_STATE_POLLING);
1077  return 0;
1078 }
1079 
1080 /* *INDENT-OFF* */
1081 VLIB_REGISTER_NODE (dpdk_ipsec_process_node,static) = {
1082  .function = dpdk_ipsec_process,
1083  .type = VLIB_NODE_TYPE_PROCESS,
1084  .name = "dpdk-ipsec-process",
1085  .process_log2_n_stack_bytes = 17,
1086 };
1087 /* *INDENT-ON* */
1088 
1089 /*
1090  * fd.io coding-style-patch-verification: ON
1091  *
1092  * Local Variables:
1093  * eval: (c-set-style "gnu")
1094  * End:
1095  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:434
u32 alg
Definition: ipsec.h:77
#define vec_foreach_index(var, v)
Iterate over vector indices.
#define hash_set(h, key, value)
Definition: hash.h:254
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
u8 numa
Definition: ipsec.h:93
static u8 cipher_alg_index(const crypto_alg_t *alg)
Definition: ipsec.c:175
#define NULL
Definition: clib.h:55
u32 index
Definition: node.h:237
u64 session_h_failed
Definition: ipsec.h:138
#define DPDK_CRYPTO_NB_SESS_OBJS
Definition: ipsec.c:634
static_always_inline void clib_spinlock_unlock_if_init(clib_spinlock_t *p)
Definition: lock.h:98
ipsec_integ_alg_t integ_alg
Definition: ipsec.h:121
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:520
static clib_error_t * crypto_create_session_drv_pool(vlib_main_t *vm, crypto_dev_t *dev)
Definition: ipsec.c:900
static u64 clib_cpu_time_now(void)
Definition: time.h:73
#define EMPTY_STRUCT
Definition: ipsec.c:26
static_always_inline u32 crypto_op_get_priv_offset(void)
Definition: ipsec.h:179
int i
struct rte_cryptodev_sym_session * session
Definition: ipsec.h:124
u8 disabled
Definition: ipsec.h:82
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:445
static void crypto_set_cipher_xform(struct rte_crypto_sym_xform *xform, ipsec_sa_t *sa, u8 is_outbound)
Definition: ipsec.c:269
vlib_main_t ** vlib_mains
Definition: buffer.c:303
static clib_error_t * crypto_create_session_h_pool(vlib_main_t *vm, u8 numa)
Definition: ipsec.c:866
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1110
#define vec_pop(V)
Returns last element of a vector and decrements its length.
Definition: vec.h:614
u8 crypto_key[128]
Definition: ipsec.h:119
static crypto_alg_t * cipher_cap_to_alg(const struct rte_cryptodev_capabilities *cap, u8 key_len)
Definition: ipsec.c:191
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static void clib_spinlock_free(clib_spinlock_t *p)
Definition: lock.h:64
static clib_error_t * add_del_sa_session(u32 sa_index, u8 is_add)
Definition: ipsec.c:483
u16 * resource_idx
Definition: ipsec.h:67
#define AES_GCM_TYPE
u8 integ_key[128]
Definition: ipsec.h:123
u16 cipher_resource_idx[IPSEC_CRYPTO_N_ALG]
Definition: ipsec.h:69
u32 esp_encrypt_next_index
Definition: ipsec.h:290
static void algos_init(u32 n_mains)
Definition: ipsec.c:29
dpdk_crypto_main_t dpdk_crypto_main
Definition: ipsec.c:24
dpdk_config_main_t dpdk_config_main
Definition: init.c:40
ipsec_main_t ipsec_main
Definition: ipsec.c:28
u8 resources
Definition: ipsec.h:83
u8 use_esn
Definition: ipsec.h:125
int i32
Definition: types.h:81
crypto_drv_t * drv
Definition: ipsec.h:152
char i8
Definition: types.h:45
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
u8 drv_id
Definition: ipsec.h:92
#define clib_error_return(e, args...)
Definition: error.h:99
static void crypto_parse_capabilities(crypto_dev_t *dev, const struct rte_cryptodev_capabilities *cap, u32 n_mains)
Definition: ipsec.c:583
ipsec_main_callbacks_t cb
Definition: ipsec.h:296
unsigned long u64
Definition: types.h:89
u16 * free_resources
Definition: ipsec.h:88
#define vec_end(v)
End (last data address) of vector.
crypto_alg_t * auth_algs
Definition: ipsec.h:150
#define VLIB_FRAME_SIZE
Definition: node.h:328
u8 * format_ipsec_crypto_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:58
static clib_error_t * crypto_dev_conf(u8 dev, u16 n_qp, u8 numa)
Definition: ipsec.c:637
u8 trunc_size
Definition: ipsec.h:80
static void crypto_disable(void)
Definition: ipsec.c:967
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:57
clib_spinlock_t lockp
Definition: ipsec.h:140
static void * get_session_private_data(const struct rte_cryptodev_sym_session *sess, uint8_t driver_id)
Definition: ipsec.c:420
u16 * used_resources
Definition: ipsec.h:89
#define hash_get(h, key)
Definition: hash.h:248
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:461
crypto_alg_t * cipher_algs
Definition: ipsec.h:149
clib_error_t *(* check_support_cb)(ipsec_sa_t *sa)
Definition: ipsec.h:253
u32 salt
Definition: ipsec.h:133
#define v
Definition: acl.c:495
u64 session_timeout
Definition: ipsec.h:153
static_always_inline u32 crypto_op_len(void)
Definition: ipsec.h:169
#define AES_GCM_ALG
#define foreach_ipsec_integ_alg
Definition: ipsec.h:88
static clib_error_t * crypto_create_crypto_op_pool(vlib_main_t *vm, u8 numa)
Definition: ipsec.c:823
static u8 auth_alg_index(const crypto_alg_t *alg)
Definition: ipsec.c:183
struct rte_mempool ** session_drv
Definition: ipsec.h:133
clib_error_t * dpdk_pool_create(vlib_main_t *vm, u8 *pool_name, u32 elt_size, u32 num_elts, u32 pool_priv_size, u16 cache_size, u8 numa, struct rte_mempool **_mp, vlib_physmem_region_index_t *pri)
Definition: buffer.c:483
vlib node functions
#define foreach_ipsec_crypto_alg
Definition: ipsec.h:66
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
svmdb_client_t * c
vlib_main_t * vm
Definition: buffer.c:294
u32 esp_encrypt_node_index
Definition: ipsec.h:285
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
u32 esp_decrypt_next_index
Definition: ipsec.h:291
#define clib_warning(format, args...)
Definition: error.h:59
#define clib_memcpy(a, b, c)
Definition: string.h:75
static u64 unix_time_now_nsec(void)
Definition: time.h:236
crypto_session_disposal_t * session_disposal
Definition: ipsec.h:134
static void crypto_set_aead_xform(struct rte_crypto_sym_xform *xform, ipsec_sa_t *sa, u8 is_outbound)
Definition: ipsec.c:241
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
u16 id
Definition: ipsec.h:94
static void set_session_private_data(struct rte_cryptodev_sym_session *sess, uint8_t driver_id, void *private_data)
Definition: ipsec.c:428
u8 iv_len
Definition: ipsec.h:79
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:783
struct rte_mempool * crypto_op
Definition: ipsec.h:131
ipsec_sa_t * sad
Definition: ipsec.h:260
static clib_error_t * dpdk_crypto_session_disposal(crypto_session_disposal_t *v, u64 ts)
Definition: ipsec.c:435
crypto_worker_main_t * workers_main
Definition: ipsec.h:145
#define clib_error_report(e)
Definition: error.h:113
static void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Set node dispatch state.
Definition: node_funcs.h:147
crypto_resource_t * resource
Definition: ipsec.h:148
u64 uword
Definition: types.h:112
#define vec_elt(v, i)
Get vector value at index i.
u8 * format_ipsec_integ_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:90
u8 crypto_key_len
Definition: ipsec.h:118
static clib_error_t * crypto_create_pools(vlib_main_t *vm)
Definition: ipsec.c:938
struct rte_mempool * session_h
Definition: ipsec.h:132
unsigned short u16
Definition: types.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
void crypto_auto_placement(void)
Definition: ipsec.c:735
unsigned char u8
Definition: types.h:56
u64 * session_drv_failed
Definition: ipsec.h:139
uword * session_by_sa_index
Definition: ipsec.h:135
static void crypto_scan_devs(u32 n_mains)
Definition: ipsec.c:666
static void crypto_op_init(struct rte_mempool *mempool, void *_arg, void *_obj, unsigned i)
Definition: ipsec.c:809
struct rte_crypto_op ** ops
Definition: ipsec.h:68
clib_error_t * create_sym_session(struct rte_cryptodev_sym_session **session, u32 sa_idx, crypto_resource_t *res, crypto_worker_main_t *cwm, u8 is_outbound)
Definition: ipsec.c:319
crypto_dev_t * dev
Definition: ipsec.h:147
enum rte_crypto_sym_xform_type type
Definition: ipsec.h:76
#define DPDK_CRYPTO_N_QUEUE_DESC
Definition: ipsec.c:633
crypto_data_t * data
Definition: ipsec.h:151
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
ipsec_crypto_alg_t crypto_alg
Definition: ipsec.h:117
uword * session_by_drv_id_and_sa_index
Definition: ipsec.h:136
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
static u32 vlib_num_workers()
Definition: threads.h:368
static uword dpdk_ipsec_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: ipsec.c:999
u16 auth_resource_idx[IPSEC_INTEG_N_ALG]
Definition: ipsec.h:70
u8 auth_support[IPSEC_INTEG_N_ALG]
Definition: ipsec.h:91
#define vec_validate_init_empty_aligned(V, I, INIT, A)
Make sure vector is long enough for given index and initialize empty space (no header, alignment alignment)
Definition: vec.h:496
#define vec_foreach(var, vec)
Vector iterator.
clib_error_t *(* add_del_sa_sess_cb)(u32 sa_index, u8 is_add)
Definition: ipsec.h:252
u8 key_len
Definition: ipsec.h:78
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:483
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
u8 vlib_physmem_region_index_t
Definition: physmem.h:43
struct rte_cryptodev_sym_session ** sa_session
Definition: ipsec.h:146
static_always_inline void clib_spinlock_lock_if_init(clib_spinlock_t *p)
Definition: lock.h:82
static void crypto_set_auth_xform(struct rte_crypto_sym_xform *xform, ipsec_sa_t *sa, u8 is_outbound)
Definition: ipsec.c:295
static clib_error_t * dpdk_ipsec_check_support(ipsec_sa_t *sa)
Definition: ipsec.c:551
u32 esp_decrypt_node_index
Definition: ipsec.h:286
u8 cipher_support[IPSEC_CRYPTO_N_ALG]
Definition: ipsec.h:90
static void clear_and_free_obj(void *obj)
Definition: ipsec.c:409
static crypto_alg_t * auth_cap_to_alg(const struct rte_cryptodev_capabilities *cap, u8 trunc_size)
Definition: ipsec.c:219