API Reference Manual  1.46.0
test/performance/odp_ipsec.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2018 Linaro Limited
3  * Copyright (c) 2022 Marvell
4  * Copyright (c) 2022 Nokia
5  */
6 
15 #ifndef _GNU_SOURCE
16 #define _GNU_SOURCE
17 #endif /* _GNU_SOURCE */
18 
19 #include <stdlib.h>
20 #include <string.h>
21 #include <getopt.h>
22 #include <unistd.h>
23 #include <stdio.h>
24 #include <sys/time.h>
25 #include <sys/resource.h>
26 
27 #include <odp_api.h>
28 #include <odp/helper/odph_api.h>
29 #include <inttypes.h>
30 
34 #define POOL_NUM_PKT 4096
35 
36 #define MAX_DEQUEUE_BURST 16
37 
38 static uint8_t test_salt[16] = "0123456789abcdef";
39 
40 static uint8_t test_key16[16] = { 0x01, 0x02, 0x03, 0x04, 0x05,
41  0x06, 0x07, 0x08, 0x09, 0x0a,
42  0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
43  0x10,
44 };
45 
46 static uint8_t test_key20[20] = { 0x01, 0x02, 0x03, 0x04, 0x05,
47  0x06, 0x07, 0x08, 0x09, 0x0a,
48  0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
49  0x10, 0x11, 0x12, 0x13, 0x14,
50 };
51 
52 static uint8_t test_key24[24] = { 0x01, 0x02, 0x03, 0x04, 0x05,
53  0x06, 0x07, 0x08, 0x09, 0x0a,
54  0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
55  0x10, 0x11, 0x12, 0x13, 0x14,
56  0x15, 0x16, 0x17, 0x18
57 };
58 
59 static uint8_t test_key32[32] = { 0x01, 0x02, 0x03, 0x04, 0x05,
60  0x06, 0x07, 0x08, 0x09, 0x0a,
61  0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
62  0x10, 0x11, 0x12, 0x13, 0x14,
63  0x15, 0x16, 0x17, 0x18, 0x19,
64  0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
65  0x1f, 0x20,
66 };
67 
68 static uint8_t test_key64[64] = { 0x01, 0x02, 0x03, 0x04, 0x05,
69  0x06, 0x07, 0x08, 0x09, 0x0a,
70  0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
71  0x10, 0x11, 0x12, 0x13, 0x14,
72  0x15, 0x16, 0x17, 0x18, 0x19,
73  0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
74  0x1f, 0x20, 0x21, 0x22, 0x23,
75  0x24, 0x25, 0x26, 0x27, 0x28,
76  0x29, 0x2a, 0x4b, 0x2c, 0x2d,
77  0x2e, 0x2f, 0x30, 0x31, 0x32,
78  0x33, 0x34, 0x55, 0x36, 0x37,
79  0x38, 0x39, 0x5a, 0x3b, 0x3c,
80  0x3d, 0x3e, 0x5f, 0x40,
81 };
82 
87 typedef struct {
88  const char *name;
90 } ipsec_alg_config_t;
91 
95 typedef struct {
100  int debug_packets;
101 
108  int in_flight;
109 
115  int packet_count;
116 
121  unsigned int payload_length;
122 
128  ipsec_alg_config_t *alg_config;
129 
134  int schedule;
135 
136  /*
137  * Poll completion queue for crypto completion events.
138  * Specified through -p argument.
139  */
140  int poll;
141 
142  /*
143  * Use tunnel instead of transport mode.
144  * Specified through -t argument.
145  */
146  int tunnel;
147 
148  /*
149  * Use AH transformation.
150  * Specified through -u argument.
151  */
152  int ah;
153 
154  /*
155  * Burst size.
156  * Prepare and submit as many packets for IPsec processing in each
157  * iteration of the loop.
158  */
159  int burst_size;
160 
161  /*
162  * Use vector packet completion from IPsec APIs.
163  * Specified through -v or --vector argument.
164  */
165  uint32_t vec_pkt_size;
166 } ipsec_args_t;
167 
168 /*
169  * Helper structure that holds averages for test of one algorithm
170  * for given payload size.
171  */
172 typedef struct {
176  double elapsed;
177 
183  double rusage_self;
184 
190  double rusage_thread;
191 } ipsec_run_result_t;
192 
196 typedef struct {
197  struct timeval tv;
198  struct rusage ru_self;
199  struct rusage ru_thread;
200 } time_record_t;
201 
205 static unsigned int global_payloads[] = {
206  64,
207  256,
208  1024,
209  8192,
210  16384
211 };
212 
214 static unsigned int global_num_payloads;
215 
219 static ipsec_alg_config_t algs_config[] = {
220  {
221  .name = "3des-cbc-null",
222  .crypto = {
224  .cipher_key = {
225  .data = test_key24,
226  .length = sizeof(test_key24)
227  },
228  .auth_alg = ODP_AUTH_ALG_NULL
229  },
230  },
231  {
232  .name = "3des-cbc-hmac-md5-96",
233  .crypto = {
234  .cipher_alg = ODP_CIPHER_ALG_3DES_CBC,
235  .cipher_key = {
236  .data = test_key24,
237  .length = sizeof(test_key24)
238  },
239  .auth_alg = ODP_AUTH_ALG_MD5_HMAC,
240  .auth_key = {
241  .data = test_key16,
242  .length = sizeof(test_key16)
243  },
244  },
245  },
246  {
247  .name = "null-hmac-md5-96",
248  .crypto = {
249  .cipher_alg = ODP_CIPHER_ALG_NULL,
250  .auth_alg = ODP_AUTH_ALG_MD5_HMAC,
251  .auth_key = {
252  .data = test_key16,
253  .length = sizeof(test_key16)
254  },
255  },
256  },
257  {
258  .name = "aes-cbc-null",
259  .crypto = {
260  .cipher_alg = ODP_CIPHER_ALG_AES_CBC,
261  .cipher_key = {
262  .data = test_key16,
263  .length = sizeof(test_key16)
264  },
265  .auth_alg = ODP_AUTH_ALG_NULL
266  },
267  },
268  {
269  .name = "aes-cbc-hmac-sha1-96",
270  .crypto = {
271  .cipher_alg = ODP_CIPHER_ALG_AES_CBC,
272  .cipher_key = {
273  .data = test_key16,
274  .length = sizeof(test_key16)
275  },
276  .auth_alg = ODP_AUTH_ALG_SHA1_HMAC,
277  .auth_key = {
278  .data = test_key20,
279  .length = sizeof(test_key20)
280  },
281  },
282  },
283  {
284  .name = "aes-ctr-null",
285  .crypto = {
286  .cipher_alg = ODP_CIPHER_ALG_AES_CTR,
287  .cipher_key = {
288  .data = test_key16,
289  .length = sizeof(test_key16)
290  },
291  .cipher_key_extra = {
292  .data = test_salt,
293  .length = 4,
294  },
295  .auth_alg = ODP_AUTH_ALG_NULL
296  },
297  },
298  {
299  .name = "aes-ctr-hmac-sha1-96",
300  .crypto = {
301  .cipher_alg = ODP_CIPHER_ALG_AES_CTR,
302  .cipher_key = {
303  .data = test_key16,
304  .length = sizeof(test_key16)
305  },
306  .cipher_key_extra = {
307  .data = test_salt,
308  .length = 4,
309  },
310  .auth_alg = ODP_AUTH_ALG_SHA1_HMAC,
311  .auth_key = {
312  .data = test_key20,
313  .length = sizeof(test_key20)
314  },
315  },
316  },
317  {
318  .name = "null-hmac-sha1-96",
319  .crypto = {
320  .cipher_alg = ODP_CIPHER_ALG_NULL,
321  .auth_alg = ODP_AUTH_ALG_SHA1_HMAC,
322  .auth_key = {
323  .data = test_key20,
324  .length = sizeof(test_key20)
325  },
326  },
327  },
328  {
329  .name = "null-hmac-sha256-128",
330  .crypto = {
331  .cipher_alg = ODP_CIPHER_ALG_NULL,
332  .auth_alg = ODP_AUTH_ALG_SHA256_HMAC,
333  .auth_key = {
334  .data = test_key32,
335  .length = sizeof(test_key32)
336  },
337  },
338  },
339  {
340  .name = "null-hmac-sha512-256",
341  .crypto = {
342  .cipher_alg = ODP_CIPHER_ALG_NULL,
343  .auth_alg = ODP_AUTH_ALG_SHA512_HMAC,
344  .auth_key = {
345  .data = test_key64,
346  .length = sizeof(test_key64)
347  },
348  },
349  },
350  {
351  .name = "null-aes-gmac",
352  .crypto = {
353  .cipher_alg = ODP_CIPHER_ALG_NULL,
354  .auth_alg = ODP_AUTH_ALG_AES_GMAC,
355  .auth_key = {
356  .data = test_key16,
357  .length = sizeof(test_key16)
358  },
359  .auth_key_extra = {
360  .data = test_salt,
361  .length = 4,
362  },
363  },
364  },
365  {
366  .name = "aes-gcm",
367  .crypto = {
368  .cipher_alg = ODP_CIPHER_ALG_AES_GCM,
369  .cipher_key = {
370  .data = test_key16,
371  .length = sizeof(test_key16)
372  },
373  .cipher_key_extra = {
374  .data = test_salt,
375  .length = 4,
376  },
377  .auth_alg = ODP_AUTH_ALG_AES_GCM,
378  },
379  },
380  {
381  .name = "aes-ccm",
382  .crypto = {
383  .cipher_alg = ODP_CIPHER_ALG_AES_CCM,
384  .cipher_key = {
385  .data = test_key16,
386  .length = sizeof(test_key16)
387  },
388  .cipher_key_extra = {
389  .data = test_salt,
390  .length = 3,
391  },
392  .auth_alg = ODP_AUTH_ALG_AES_CCM,
393  },
394  },
395  {
396  .name = "chacha20-poly1305",
397  .crypto = {
398  .cipher_alg = ODP_CIPHER_ALG_CHACHA20_POLY1305,
399  .cipher_key = {
400  .data = test_key32,
401  .length = sizeof(test_key32)
402  },
403  .cipher_key_extra = {
404  .data = test_salt,
405  .length = 4,
406  },
407  .auth_alg = ODP_AUTH_ALG_CHACHA20_POLY1305,
408  },
409  },
410 };
411 
416 static ipsec_alg_config_t *
417 find_config_by_name(const char *name)
418 {
419  unsigned int i;
420  ipsec_alg_config_t *ret = NULL;
421 
422  for (i = 0; i < ODPH_ARRAY_SIZE(algs_config); i++) {
423  if (strcmp(algs_config[i].name, name) == 0) {
424  ret = algs_config + i;
425  break;
426  }
427  }
428  return ret;
429 }
430 
435 static void
436 print_config_names(const char *prefix)
437 {
438  unsigned int i;
439 
440  for (i = 0; i < ODPH_ARRAY_SIZE(algs_config); i++)
441  printf("%s %s\n", prefix, algs_config[i].name);
442 }
443 
447 static void
448 fill_time_record(time_record_t *rec)
449 {
450  gettimeofday(&rec->tv, NULL);
451  getrusage(RUSAGE_SELF, &rec->ru_self);
452  getrusage(RUSAGE_THREAD, &rec->ru_thread);
453 }
454 
459 static unsigned long long
460 get_rusage_diff(struct rusage *start, struct rusage *end)
461 {
462  unsigned long long rusage_diff;
463  unsigned long long rusage_start;
464  unsigned long long rusage_end;
465 
466  rusage_start = (start->ru_utime.tv_sec * 1000000) +
467  (start->ru_utime.tv_usec);
468  rusage_start += (start->ru_stime.tv_sec * 1000000) +
469  (start->ru_stime.tv_usec);
470 
471  rusage_end = (end->ru_utime.tv_sec * 1000000) +
472  (end->ru_utime.tv_usec);
473  rusage_end += (end->ru_stime.tv_sec * 1000000) +
474  (end->ru_stime.tv_usec);
475 
476  rusage_diff = rusage_end - rusage_start;
477 
478  return rusage_diff;
479 }
480 
485 static unsigned long long
486 get_rusage_self_diff(time_record_t *start, time_record_t *end)
487 {
488  return get_rusage_diff(&start->ru_self, &end->ru_self);
489 }
490 
495 static unsigned long long
496 get_rusage_thread_diff(time_record_t *start, time_record_t *end)
497 {
498  return get_rusage_diff(&start->ru_thread, &end->ru_thread);
499 }
500 
504 static unsigned long long
505 get_elapsed_usec(time_record_t *start, time_record_t *end)
506 {
507  unsigned long long s;
508  unsigned long long e;
509 
510  s = (start->tv.tv_sec * 1000000) + (start->tv.tv_usec);
511  e = (end->tv.tv_sec * 1000000) + (end->tv.tv_usec);
512 
513  return e - s;
514 }
515 
519 static void
520 print_result_header(void)
521 {
522  printf("\n%30.30s %15s %15s %15s %15s %15s %15s\n",
523  "algorithm", "avg over #", "payload (bytes)", "elapsed (us)",
524  "rusg self (us)", "rusg thrd (us)", "throughput (Kb)");
525 }
526 
530 static void
531 print_result(ipsec_args_t *cargs,
532  unsigned int payload_length,
533  ipsec_alg_config_t *config,
534  ipsec_run_result_t *result)
535 {
536  unsigned int throughput;
537 
538  throughput = (1000000.0 / result->elapsed) * payload_length / 1024;
539  printf("%30.30s %15d %15d %15.3f %15.3f %15.3f %15d\n",
540  config->name, cargs->packet_count, payload_length,
541  result->elapsed, result->rusage_self, result->rusage_thread,
542  throughput);
543 }
544 
545 #define IPV4ADDR(a, b, c, d) odp_cpu_to_be_32((a << 24) | \
546  (b << 16) | \
547  (c << 8) | \
548  (d << 0))
549 
553 static odp_ipsec_sa_t
554 create_sa_from_config(ipsec_alg_config_t *config,
555  ipsec_args_t *cargs)
556 {
557  odp_ipsec_sa_param_t param;
558  odp_queue_t out_queue;
559 
560  odp_ipsec_sa_param_init(&param);
561  memcpy(&param.crypto, &config->crypto,
562  sizeof(odp_ipsec_crypto_param_t));
563 
564  param.proto = ODP_IPSEC_ESP;
565  param.dir = ODP_IPSEC_DIR_OUTBOUND;
566 
567  if (cargs->tunnel) {
568  uint32_t src = IPV4ADDR(10, 0, 111, 2);
569  uint32_t dst = IPV4ADDR(10, 0, 222, 2);
571 
572  memset(&tunnel, 0, sizeof(tunnel));
573  tunnel.type = ODP_IPSEC_TUNNEL_IPV4;
574  tunnel.ipv4.src_addr = &src;
575  tunnel.ipv4.dst_addr = &dst;
576  tunnel.ipv4.ttl = 64;
577 
578  param.mode = ODP_IPSEC_MODE_TUNNEL;
579  param.outbound.tunnel = tunnel;
580  } else {
582  }
583 
584  if (cargs->schedule || cargs->poll) {
585  out_queue = odp_queue_lookup("ipsec-out");
586  if (out_queue == ODP_QUEUE_INVALID) {
587  ODPH_ERR("ipsec-out queue not found\n");
588  return ODP_IPSEC_SA_INVALID;
589  }
590  param.dest_queue = out_queue;
591  } else {
593  }
594 
595  return odp_ipsec_sa_create(&param);
596 }
597 
598 static uint8_t test_data[] = {
599  /* IP */
600  0x45, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
601  0x40, 0x01, 0xac, 0x27, 0xc0, 0xa8, 0x6f, 0x02,
602  0xc0, 0xa8, 0xde, 0x02,
603 
604  /* ICMP */
605  0x08, 0x00, 0xfb, 0x37, 0x12, 0x34, 0x00, 0x00
606 };
607 
608 static inline void debug_packets(int debug, odp_packet_t *pkt, int num_pkts)
609 {
610  if (odp_likely(!debug))
611  return;
612  for (int i = 0; i < num_pkts; i++)
613  odp_packet_print_data(pkt[i], 0, odp_packet_len(pkt[i]));
614 }
615 
616 static int
617 make_packet_multi(odp_pool_t pkt_pool, unsigned int payload_length,
618  odp_packet_t pkt[], int num)
619 {
620  int i, ret;
621 
622  ret = odp_packet_alloc_multi(pkt_pool, payload_length, pkt, num);
623  if (ret != num) {
624  ODPH_ERR("Could not allocate buffer\n");
625  if (ret > 0)
626  odp_packet_free_sp(pkt, ret);
627  return -1;
628  }
629 
630  for (i = 0; i < num; i++) {
631  odp_packet_copy_from_mem(pkt[i], 0, sizeof(test_data), test_data);
632  odp_packet_l3_offset_set(pkt[i], 0);
633 
634  uint8_t *mem = odp_packet_data(pkt[i]);
635  ((odph_ipv4hdr_t *)mem)->tot_len = odp_cpu_to_be_16(payload_length);
636  memset(mem + sizeof(test_data), 1, payload_length - sizeof(test_data));
637  }
638 
639  return 0;
640 }
641 
642 static inline void check_ipsec_result(odp_packet_t ipsec_pkt)
643 {
645 
646  if (odp_unlikely(odp_ipsec_result(&result, ipsec_pkt)))
647  ODPH_ERR("odp_ipsec_result() failed\n");
648  else if (odp_unlikely(result.status.error.all))
649  ODPH_ERR("IPsec processing error: %" PRIu32 "\n",
650  result.status.error.all);
651 }
652 
657 static int
658 run_measure_one(ipsec_args_t *cargs,
659  odp_ipsec_sa_t sa,
660  unsigned int payload_length,
661  time_record_t *start,
662  time_record_t *end)
663 {
664  int in_flight, pkts_allowed, num_out, num_pkts, rc = 0;
665  const int max_in_flight = cargs->in_flight;
666  const int burst_size = cargs->burst_size;
667  const int packet_count = cargs->packet_count;
668  const int debug = cargs->debug_packets;
669  odp_ipsec_out_param_t param;
670  odp_pool_t pkt_pool;
671 
672  pkt_pool = odp_pool_lookup("packet_pool");
673  if (pkt_pool == ODP_POOL_INVALID) {
674  ODPH_ERR("pkt_pool not found\n");
675  return -1;
676  }
677 
678  if (payload_length < sizeof(test_data))
679  return -1;
680 
681  int packets_sent = 0;
682  int packets_received = 0;
683 
684  /* Initialize parameters block */
685  memset(&param, 0, sizeof(param));
686  param.num_sa = 1;
687  param.num_opt = 0;
688  param.sa = &sa;
689 
690  fill_time_record(start);
691 
692  while ((packets_sent < packet_count) ||
693  (packets_received < packet_count)) {
694  num_pkts = packet_count - packets_sent;
695 
696  /* Enqueue up to burst size */
697  num_pkts = num_pkts > burst_size ? burst_size : num_pkts;
698 
699  /* Enqueue up to (max in flight - current in flight) */
700  in_flight = packets_sent - packets_received;
701  pkts_allowed = max_in_flight - in_flight;
702 
703  /* Enqueue either a burst of packets or skip */
704  num_pkts = num_pkts > pkts_allowed ? 0 : num_pkts;
705 
706  if (odp_likely(num_pkts)) {
707  odp_packet_t out_pkt[num_pkts];
708  odp_packet_t pkt[num_pkts];
709  int i;
710 
711  if (odp_unlikely(make_packet_multi(pkt_pool,
712  payload_length,
713  pkt,
714  num_pkts)))
715  return -1;
716 
717  debug_packets(debug, pkt, num_pkts);
718  num_out = num_pkts;
719 
720  rc = odp_ipsec_out(pkt, num_pkts,
721  out_pkt, &num_out,
722  &param);
723  if (odp_unlikely(rc <= 0)) {
724  ODPH_ERR("Failed odp_ipsec_out: rc = %d\n", rc);
725  odp_packet_free_sp(pkt, num_pkts);
726  break;
727  }
728 
729  for (i = 0; i < num_out; i++)
730  check_ipsec_result(out_pkt[i]);
731 
732  packets_sent += rc;
733  packets_received += num_out;
734  debug_packets(debug, out_pkt, num_out);
735 
736  if (odp_unlikely(rc != num_pkts))
737  odp_packet_free_sp(&pkt[rc], num_pkts - rc);
738  odp_packet_free_sp(out_pkt, num_out);
739  }
740  }
741 
742  fill_time_record(end);
743 
744  return rc < 0 ? rc : 0;
745 }
746 
747 static uint32_t dequeue_burst(odp_queue_t polled_queue,
748  odp_event_t *events,
749  int max_burst)
750 {
751  int num = 0;
752 
753  if (polled_queue != ODP_QUEUE_INVALID) {
754  int rc = odp_queue_deq_multi(polled_queue,
755  events,
756  max_burst);
757  num = odp_likely(rc >= 0) ? rc : 0;
758  } else {
759  num = odp_schedule_multi(NULL,
761  events,
762  max_burst);
763  }
764  return num;
765 }
766 
767 static inline uint32_t vec_pkt_handle(int debug, odp_event_t ev)
768 {
770  uint32_t vec_size = odp_packet_vector_size(vec);
771  odp_packet_t *pkt_tbl;
772  uint32_t j;
773 
774  odp_packet_vector_tbl(vec, &pkt_tbl);
775 
776  for (j = 0; j < vec_size; j++)
777  check_ipsec_result(pkt_tbl[j]);
778 
779  debug_packets(debug, pkt_tbl, vec_size);
780 
781  odp_packet_free_sp(pkt_tbl, vec_size);
783 
784  return vec_size;
785 }
786 
787 static int
788 run_measure_one_async(ipsec_args_t *cargs,
789  odp_ipsec_sa_t sa,
790  unsigned int payload_length,
791  time_record_t *start,
792  time_record_t *end)
793 {
794  int in_flight, packets_allowed, num_pkts, rc = 0;
795  const int max_in_flight = cargs->in_flight;
796  const int burst_size = cargs->burst_size;
797  const int packet_count = cargs->packet_count;
798  const int debug = cargs->debug_packets;
799  odp_ipsec_out_param_t param;
800  odp_pool_t pkt_pool;
801  odp_queue_t polled_queue = ODP_QUEUE_INVALID;
802 
803  pkt_pool = odp_pool_lookup("packet_pool");
804  if (pkt_pool == ODP_POOL_INVALID) {
805  ODPH_ERR("pkt_pool not found\n");
806  return -1;
807  }
808 
809  if (cargs->poll) {
810  polled_queue = odp_queue_lookup("ipsec-out");
811  if (polled_queue == ODP_QUEUE_INVALID) {
812  ODPH_ERR("ipsec-out queue not found\n");
813  return -1;
814  }
815  }
816 
817  if (payload_length < sizeof(test_data))
818  return -1;
819 
820  int packets_sent = 0;
821  int packets_received = 0;
822 
823  /* Initialize parameters block */
824  memset(&param, 0, sizeof(param));
825  param.num_sa = 1;
826  param.num_opt = 0;
827  param.sa = &sa;
828 
829  fill_time_record(start);
830 
831  while ((packets_sent < packet_count) ||
832  (packets_received < packet_count)) {
833 
834  num_pkts = packet_count - packets_sent;
835 
836  /* Enqueue up to burst size */
837  num_pkts = num_pkts > burst_size ? burst_size : num_pkts;
838 
839  /* Enqueue up to (max in flight - current in flight) */
840  in_flight = packets_sent - packets_received;
841  packets_allowed = max_in_flight - in_flight;
842 
843  if (num_pkts > 0 && num_pkts <= packets_allowed) {
844  odp_packet_t pkt[num_pkts];
845 
846  if (odp_unlikely(make_packet_multi(pkt_pool,
847  payload_length,
848  pkt,
849  num_pkts)))
850  return -1;
851 
852  debug_packets(debug, pkt, num_pkts);
853 
854  rc = odp_ipsec_out_enq(pkt, num_pkts, &param);
855  if (odp_unlikely(rc <= 0)) {
856  ODPH_ERR("Failed odp_ipsec_out_enq: rc = %d\n",
857  rc);
858  odp_packet_free_sp(pkt, num_pkts);
859  break;
860  }
861 
862  if (odp_unlikely(rc != num_pkts))
863  odp_packet_free_sp(&pkt[rc], num_pkts - rc);
864 
865  packets_sent += rc;
866  } else {
867  odp_packet_t pkt_out[max_in_flight];
868  int i = 0;
869 
870  /*
871  * Dequeue packets until we can enqueue the next burst
872  * or until we have received all remaining packets
873  * when there are no more packets to be sent.
874  */
875  while (num_pkts > packets_allowed ||
876  (num_pkts == 0 && packets_received < packet_count)) {
877  odp_event_t events[MAX_DEQUEUE_BURST];
878  uint32_t num;
879 
880  num = dequeue_burst(polled_queue, events, MAX_DEQUEUE_BURST);
881 
882  for (uint32_t n = 0; n < num; n++) {
883  if (odp_event_type(events[n]) == ODP_EVENT_PACKET_VECTOR) {
884  uint32_t vec_size;
885 
886  vec_size = vec_pkt_handle(debug, events[n]);
887  packets_received += vec_size - 1;
888  packets_allowed += vec_size - 1;
889  } else {
890  pkt_out[i] = odp_ipsec_packet_from_event(events[n]);
891  check_ipsec_result(pkt_out[i]);
892  i++;
893  }
894 
895  }
896  packets_received += num;
897  packets_allowed += num;
898  }
899  debug_packets(debug, pkt_out, i);
900 
901  if (i > 0)
902  odp_packet_free_sp(pkt_out, i);
903  }
904  }
905 
906  fill_time_record(end);
907 
908  return rc < 0 ? rc : 0;
909 }
910 
915 static int
916 run_measure_one_config(ipsec_args_t *cargs,
917  ipsec_alg_config_t *config)
918 {
919  unsigned int num_payloads = global_num_payloads;
920  unsigned int *payloads = global_payloads;
922  odp_ipsec_sa_t sa;
923  unsigned int i;
924  int rc = 0;
925 
926  if (odp_ipsec_capability(&capa) < 0) {
927  ODPH_ERR("IPSEC capability call failed.\n");
928  return -1;
929  }
930 
931  if (cargs->ah && (ODP_SUPPORT_NO == capa.proto_ah)) {
932  ODPH_ERR("IPSEC AH protocol not supported.\n");
933  return -1;
934  }
935 
936  rc = odph_ipsec_alg_check(&capa, config->crypto.cipher_alg,
937  config->crypto.cipher_key.length,
938  config->crypto.auth_alg,
939  config->crypto.auth_key.length);
940 
941  if (rc) {
942  printf(" => %s skipped\n\n", config->name);
943  return 0;
944  }
945 
946  sa = create_sa_from_config(config, cargs);
947  if (sa == ODP_IPSEC_SA_INVALID) {
948  ODPH_ERR("IPsec SA create failed.\n");
949  return -1;
950  }
951 
952  print_result_header();
953  if (cargs->payload_length) {
954  num_payloads = 1;
955  payloads = &cargs->payload_length;
956  }
957 
958  for (i = 0; i < num_payloads; i++) {
959  double count;
960  ipsec_run_result_t result;
961  time_record_t start, end;
962 
963  if (cargs->schedule || cargs->poll)
964  rc = run_measure_one_async(cargs, sa,
965  payloads[i],
966  &start, &end);
967  else
968  rc = run_measure_one(cargs, sa,
969  payloads[i],
970  &start, &end);
971  if (rc)
972  break;
973 
974  count = get_elapsed_usec(&start, &end);
975  result.elapsed = count / cargs->packet_count;
976 
977  count = get_rusage_self_diff(&start, &end);
978  result.rusage_self = count / cargs->packet_count;
979 
980  count = get_rusage_thread_diff(&start, &end);
981  result.rusage_thread = count / cargs->packet_count;
982 
983  print_result(cargs, payloads[i],
984  config, &result);
985  }
986 
988  if (cargs->schedule || cargs->poll) {
989  odp_queue_t out_queue = odp_queue_lookup("ipsec-out");
990  odp_ipsec_status_t status;
991 
992  while (1) {
993  odp_event_t event;
994 
995  if (cargs->poll)
996  event = odp_queue_deq(out_queue);
997  else
998  event = odp_schedule(NULL, ODP_SCHED_NO_WAIT);
999 
1000  if (event != ODP_EVENT_INVALID &&
1001  odp_event_type(event) == ODP_EVENT_IPSEC_STATUS &&
1002  odp_ipsec_status(&status, event) == ODP_IPSEC_OK &&
1003  status.id == ODP_IPSEC_STATUS_SA_DISABLE &&
1004  status.sa == sa)
1005  break;
1006  }
1007  }
1009 
1010  return rc;
1011 }
1012 
1013 typedef struct thr_arg {
1014  ipsec_args_t ipsec_args;
1015  ipsec_alg_config_t *ipsec_alg_config;
1016 } thr_arg_t;
1017 
1018 static int run_thr_func(void *arg)
1019 {
1020  thr_arg_t *thr_args = (thr_arg_t *)arg;
1021 
1022  run_measure_one_config(&thr_args->ipsec_args,
1023  thr_args->ipsec_alg_config);
1024  return 0;
1025 }
1026 
1030 static void usage(char *progname)
1031 {
1032  printf("\n"
1033  "Usage: %s OPTIONS\n"
1034  " E.g. %s -i 100000\n"
1035  "\n"
1036  "OpenDataPlane crypto speed measure.\n"
1037  "Optional OPTIONS\n"
1038  " -a, --algorithm <name> Specify algorithm name (default all)\n"
1039  " Supported values are:\n",
1040  progname, progname);
1041 
1042  print_config_names(" ");
1043  printf(" -d, --debug Enable dump of processed packets.\n"
1044  " -f, --flight <number> Max number of packet processed in parallel (default 1)\n"
1045  " -c, --count <number> Number of packets (default 10000)\n"
1046  " -b, --burst <number> Number of packets in one IPsec API submission (default 1)\n"
1047  " -v, --vector <number> Enable vector packet completion from IPsec APIs with specified vector size.\n"
1048  " -l, --payload Payload length.\n"
1049  " -s, --schedule Use scheduler for completion events.\n"
1050  " -p, --poll Poll completion queue for completion events.\n"
1051  " -t, --tunnel Use tunnel-mode IPsec transformation.\n"
1052  " -u, --ah Use AH transformation instead of ESP.\n"
1053  " -h, --help Display help and exit.\n"
1054  "\n");
1055 }
1056 
1057 static void parse_args(int argc, char *argv[], ipsec_args_t *cargs)
1058 {
1059  int opt;
1060  static const struct option longopts[] = {
1061  {"algorithm", optional_argument, NULL, 'a'},
1062  {"debug", no_argument, NULL, 'd'},
1063  {"flight", optional_argument, NULL, 'f'},
1064  {"help", no_argument, NULL, 'h'},
1065  {"count", optional_argument, NULL, 'c'},
1066  {"burst", optional_argument, NULL, 'b'},
1067  {"vector", optional_argument, NULL, 'v'},
1068  {"payload", optional_argument, NULL, 'l'},
1069  {"sessions", optional_argument, NULL, 'm'},
1070  {"poll", no_argument, NULL, 'p'},
1071  {"schedule", no_argument, NULL, 's'},
1072  {"tunnel", no_argument, NULL, 't'},
1073  {"ah", no_argument, NULL, 'u'},
1074  {NULL, 0, NULL, 0}
1075  };
1076 
1077  static const char *shortopts = "+a:b:c:df:hm:nl:sptuv:";
1078 
1079  cargs->in_flight = 1;
1080  cargs->debug_packets = 0;
1081  cargs->packet_count = 10000;
1082  cargs->burst_size = 1;
1083  cargs->vec_pkt_size = 0;
1084  cargs->payload_length = 0;
1085  cargs->alg_config = NULL;
1086  cargs->schedule = 0;
1087  cargs->ah = 0;
1088 
1089  while (1) {
1090  opt = getopt_long(argc, argv, shortopts, longopts, NULL);
1091 
1092  if (opt == -1)
1093  break; /* No more options */
1094 
1095  switch (opt) {
1096  case 'a':
1097  cargs->alg_config = find_config_by_name(optarg);
1098  if (!cargs->alg_config) {
1099  printf("cannot test crypto '%s' configuration\n",
1100  optarg);
1101  usage(argv[0]);
1102  exit(-1);
1103  }
1104  break;
1105  case 'd':
1106  cargs->debug_packets = 1;
1107  break;
1108  case 'c':
1109  cargs->packet_count = atoi(optarg);
1110  break;
1111  case 'b':
1112  if (optarg == NULL)
1113  cargs->burst_size = 32;
1114  else
1115  cargs->burst_size = atoi(optarg);
1116  if (cargs->burst_size > POOL_NUM_PKT) {
1117  printf("Invalid burst size (max allowed: %d)\n", POOL_NUM_PKT);
1118  exit(-1);
1119  }
1120  break;
1121  case 'v':
1122  if (optarg == NULL)
1123  cargs->vec_pkt_size = 32;
1124  else
1125  cargs->vec_pkt_size = atoi(optarg);
1126  break;
1127  case 'f':
1128  cargs->in_flight = atoi(optarg);
1129  break;
1130  case 'h':
1131  usage(argv[0]);
1132  exit(EXIT_SUCCESS);
1133  break;
1134  case 'l':
1135  cargs->payload_length = atoi(optarg);
1136  break;
1137  case 's':
1138  cargs->schedule = 1;
1139  break;
1140  case 'p':
1141  cargs->poll = 1;
1142  break;
1143  case 't':
1144  cargs->tunnel = 1;
1145  break;
1146  case 'u':
1147  cargs->ah = 1;
1148  break;
1149  default:
1150  break;
1151  }
1152  }
1153 
1154  if (cargs->in_flight < cargs->burst_size) {
1155  printf("-f (flight) must be greater than or equal to -b (burst)\n");
1156  exit(-1);
1157  }
1158 
1159  optind = 1; /* reset 'extern optind' from the getopt lib */
1160 
1161  if (cargs->schedule && cargs->poll) {
1162  printf("-s (schedule) and -p (poll) options are not compatible\n");
1163  usage(argv[0]);
1164  exit(-1);
1165  }
1166 }
1167 
1168 int main(int argc, char *argv[])
1169 {
1170  odp_pool_t vec_pool = ODP_POOL_INVALID;
1171  ipsec_args_t cargs;
1172  odp_pool_t pool;
1173  odp_queue_param_t qparam;
1174  odp_pool_param_t param;
1175  odp_queue_t out_queue = ODP_QUEUE_INVALID;
1176  thr_arg_t thr_arg;
1177  odp_cpumask_t cpumask;
1178  char cpumaskstr[ODP_CPUMASK_STR_SIZE];
1179  int num_workers = 1;
1180  odph_helper_options_t helper_options;
1181  odph_thread_t thread_tbl[num_workers];
1182  odph_thread_common_param_t thr_common;
1183  odph_thread_param_t thr_param;
1184  odp_instance_t instance;
1185  odp_init_t init_param;
1186  odp_ipsec_capability_t ipsec_capa;
1187  odp_pool_capability_t capa;
1188  odp_ipsec_config_t config;
1189  uint32_t max_seg_len;
1190  unsigned int i;
1191 
1192  /* Let helper collect its own arguments (e.g. --odph_proc) */
1193  argc = odph_parse_options(argc, argv);
1194  if (odph_options(&helper_options)) {
1195  ODPH_ERR("Reading ODP helper options failed.\n");
1196  exit(EXIT_FAILURE);
1197  }
1198 
1199  odp_init_param_init(&init_param);
1200  init_param.mem_model = helper_options.mem_model;
1201 
1202  memset(&cargs, 0, sizeof(cargs));
1203 
1204  /* Parse and store the application arguments */
1205  parse_args(argc, argv, &cargs);
1206 
1207  /* Init ODP before calling anything else */
1208  if (odp_init_global(&instance, &init_param, NULL)) {
1209  ODPH_ERR("ODP global init failed.\n");
1210  exit(EXIT_FAILURE);
1211  }
1212 
1213  /* Init this thread */
1214  if (odp_init_local(instance, ODP_THREAD_WORKER)) {
1215  ODPH_ERR("ODP local init failed.\n");
1216  exit(EXIT_FAILURE);
1217  }
1218 
1220 
1221  if (odp_pool_capability(&capa)) {
1222  ODPH_ERR("Pool capability request failed.\n");
1223  exit(EXIT_FAILURE);
1224  }
1225 
1226  max_seg_len = capa.pkt.max_seg_len;
1227 
1228  for (i = 0; i < ODPH_ARRAY_SIZE(global_payloads); i++) {
1229  if (global_payloads[i] > max_seg_len)
1230  break;
1231  }
1232 
1233  global_num_payloads = i;
1234 
1235  /* Create packet pool */
1236  odp_pool_param_init(&param);
1237  param.pkt.seg_len = max_seg_len;
1238  param.pkt.len = max_seg_len;
1239  param.pkt.num = POOL_NUM_PKT;
1240  param.type = ODP_POOL_PACKET;
1241  pool = odp_pool_create("packet_pool", &param);
1242 
1243  if (pool == ODP_POOL_INVALID) {
1244  ODPH_ERR("packet pool create failed.\n");
1245  exit(EXIT_FAILURE);
1246  }
1247  odp_pool_print(pool);
1248 
1249  if (odp_ipsec_capability(&ipsec_capa) < 0) {
1250  ODPH_ERR("IPSEC capability call failed.\n");
1251  exit(EXIT_FAILURE);
1252  }
1253 
1254  if (cargs.schedule && !ipsec_capa.queue_type_sched) {
1255  ODPH_ERR("Scheduled type destination queue not supported.\n");
1256  exit(EXIT_FAILURE);
1257  }
1258 
1259  if (cargs.poll && !ipsec_capa.queue_type_plain) {
1260  ODPH_ERR("Plain type destination queue not supported.\n");
1261  exit(EXIT_FAILURE);
1262  }
1263 
1264  if (cargs.vec_pkt_size) {
1265  if (capa.vector.max_pools < 1) {
1266  ODPH_ERR("Vector packet pool not available");
1267  exit(EXIT_FAILURE);
1268  }
1269 
1270  if (!ipsec_capa.vector.supported) {
1271  ODPH_ERR("Vector packet completion not supported by IPsec.\n");
1272  exit(EXIT_FAILURE);
1273  }
1274 
1275  if (capa.vector.max_size < cargs.vec_pkt_size) {
1276  ODPH_ERR("Vector size larger than max size supported by vector pool.\n");
1277  exit(EXIT_FAILURE);
1278  }
1279 
1280  if (!cargs.schedule && !cargs.poll) {
1281  ODPH_ERR("Vector packet is not supported with sync APIs.\n");
1282  exit(EXIT_FAILURE);
1283  }
1284 
1285  /* Create vector pool */
1286  odp_pool_param_init(&param);
1287  param.vector.num = POOL_NUM_PKT;
1288  param.vector.max_size = cargs.vec_pkt_size;
1289  param.type = ODP_POOL_VECTOR;
1290  vec_pool = odp_pool_create("vector_pool", &param);
1291 
1292  if (vec_pool == ODP_POOL_INVALID) {
1293  ODPH_ERR("Vector packet pool create failed.\n");
1294  exit(EXIT_FAILURE);
1295  }
1296 
1297  odp_pool_print(vec_pool);
1298  }
1299 
1300  odp_ipsec_config_init(&config);
1301  config.max_num_sa = 2;
1302  config.inbound.chksums.all_chksum = 0;
1303  config.outbound.all_chksum = 0;
1304 
1305  if (vec_pool != ODP_POOL_INVALID) {
1306  config.vector.enable = true;
1307  config.vector.pool = vec_pool;
1308  config.vector.max_size = cargs.vec_pkt_size;
1309  config.vector.max_tmo_ns = ipsec_capa.vector.max_tmo_ns;
1310  }
1311 
1312  odp_queue_param_init(&qparam);
1313  if (cargs.schedule) {
1314  odp_schedule_config(NULL);
1315  qparam.type = ODP_QUEUE_TYPE_SCHED;
1318  qparam.sched.group = ODP_SCHED_GROUP_ALL;
1319  out_queue = odp_queue_create("ipsec-out", &qparam);
1320  } else if (cargs.poll) {
1321  qparam.type = ODP_QUEUE_TYPE_PLAIN;
1322  out_queue = odp_queue_create("ipsec-out", &qparam);
1323  }
1324  if (cargs.schedule || cargs.poll) {
1325  if (out_queue == ODP_QUEUE_INVALID) {
1326  ODPH_ERR("ipsec-out queue create failed.\n");
1327  exit(EXIT_FAILURE);
1328  }
1331  config.inbound.default_queue = out_queue;
1332  } else {
1336  }
1337  if (odp_ipsec_config(&config)) {
1338  ODPH_ERR("odp_ipsec_config() failed\n");
1339  exit(EXIT_FAILURE);
1340  }
1341 
1342  if (cargs.schedule) {
1343  printf("Run in async scheduled mode\n");
1344 
1345  thr_arg.ipsec_args = cargs;
1346  thr_arg.ipsec_alg_config = cargs.alg_config;
1347  num_workers = odp_cpumask_default_worker(&cpumask,
1348  num_workers);
1349  (void)odp_cpumask_to_str(&cpumask, cpumaskstr,
1350  sizeof(cpumaskstr));
1351  printf("num worker threads: %i\n",
1352  num_workers);
1353  printf("first CPU: %i\n",
1354  odp_cpumask_first(&cpumask));
1355  printf("cpu mask: %s\n",
1356  cpumaskstr);
1357  } else if (cargs.poll) {
1358  printf("Run in async poll mode\n");
1359  } else {
1360  printf("Run in sync mode\n");
1361  }
1362 
1363  if (cargs.alg_config) {
1364  odph_thread_common_param_init(&thr_common);
1365  thr_common.instance = instance;
1366  thr_common.cpumask = &cpumask;
1367  thr_common.share_param = 1;
1368 
1369  if (cargs.schedule) {
1370  odph_thread_param_init(&thr_param);
1371  thr_param.start = run_thr_func;
1372  thr_param.arg = &thr_arg;
1373  thr_param.thr_type = ODP_THREAD_WORKER;
1374 
1375  memset(thread_tbl, 0, sizeof(thread_tbl));
1376  odph_thread_create(thread_tbl, &thr_common, &thr_param, num_workers);
1377 
1378  odph_thread_join(thread_tbl, num_workers);
1379  } else {
1380  run_measure_one_config(&cargs, cargs.alg_config);
1381  }
1382  } else {
1383  for (i = 0; i < ODPH_ARRAY_SIZE(algs_config); i++) {
1384  if (cargs.ah &&
1385  algs_config[i].crypto.cipher_alg !=
1387  continue;
1388  run_measure_one_config(&cargs, algs_config + i);
1389  }
1390  }
1391 
1392  if (cargs.schedule || cargs.poll)
1393  odp_queue_destroy(out_queue);
1394 
1395  if (cargs.vec_pkt_size) {
1396  if (odp_pool_destroy(vec_pool)) {
1397  ODPH_ERR("Error: vector pool destroy\n");
1398  exit(EXIT_FAILURE);
1399  }
1400  }
1401 
1402  if (odp_pool_destroy(pool)) {
1403  ODPH_ERR("Error: pool destroy\n");
1404  exit(EXIT_FAILURE);
1405  }
1406 
1407  if (odp_term_local()) {
1408  ODPH_ERR("Error: term local\n");
1409  exit(EXIT_FAILURE);
1410  }
1411 
1412  if (odp_term_global(instance)) {
1413  ODPH_ERR("Error: term global\n");
1414  exit(EXIT_FAILURE);
1415  }
1416 
1417  return 0;
1418 }
1419 
#define odp_unlikely(x)
Branch unlikely taken.
Definition: spec/hints.h:64
odp_u16be_t odp_cpu_to_be_16(uint16_t cpu16)
Convert cpu native uint16_t to 16bit big endian.
#define odp_likely(x)
Branch likely taken.
Definition: spec/hints.h:59
int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
Default CPU mask for worker threads.
int odp_cpumask_first(const odp_cpumask_t *mask)
Find first set CPU in mask.
int32_t odp_cpumask_to_str(const odp_cpumask_t *mask, char *str, int32_t size)
Format a string from CPU mask.
#define ODP_CPUMASK_STR_SIZE
The maximum number of characters needed to record any CPU mask as a string (output of odp_cpumask_to_...
@ ODP_CIPHER_ALG_AES_CCM
AES-CCM.
@ ODP_CIPHER_ALG_AES_CTR
AES with counter mode.
@ ODP_CIPHER_ALG_CHACHA20_POLY1305
ChaCha20-Poly1305.
@ ODP_CIPHER_ALG_AES_CBC
AES with cipher block chaining.
@ ODP_CIPHER_ALG_AES_GCM
AES-GCM.
@ ODP_CIPHER_ALG_3DES_CBC
Triple DES with cipher block chaining.
@ ODP_CIPHER_ALG_NULL
No cipher algorithm specified.
@ ODP_AUTH_ALG_CHACHA20_POLY1305
ChaCha20-Poly1305 AEAD.
@ ODP_AUTH_ALG_NULL
No authentication algorithm specified.
@ ODP_AUTH_ALG_MD5_HMAC
HMAC-MD5.
@ ODP_AUTH_ALG_SHA512_HMAC
HMAC-SHA-512.
@ ODP_AUTH_ALG_SHA1_HMAC
HMAC-SHA-1.
@ ODP_AUTH_ALG_SHA256_HMAC
HMAC-SHA-256.
@ ODP_AUTH_ALG_AES_GMAC
AES-GMAC.
@ ODP_AUTH_ALG_AES_GCM
AES-GCM.
@ ODP_AUTH_ALG_AES_CCM
AES-CCM.
odp_event_type_t odp_event_type(odp_event_t event)
Event type of an event.
#define ODP_EVENT_INVALID
Invalid event.
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
Thread local ODP initialization.
int odp_init_global(odp_instance_t *instance, const odp_init_t *params, const odp_platform_init_t *platform_params)
Global ODP initialization.
int odp_term_local(void)
Thread local ODP termination.
int odp_term_global(odp_instance_t instance)
Global ODP termination.
uint64_t odp_instance_t
ODP instance ID.
odp_packet_t odp_ipsec_packet_from_event(odp_event_t ev)
Convert IPSEC processed packet event to packet handle.
#define ODP_IPSEC_OK
IPSEC operation status has no errors.
int odp_ipsec_capability(odp_ipsec_capability_t *capa)
Query IPSEC capabilities.
int odp_ipsec_out(const odp_packet_t pkt_in[], int num_in, odp_packet_t pkt_out[], int *num_out, const odp_ipsec_out_param_t *param)
Outbound synchronous IPSEC operation.
void odp_ipsec_config_init(odp_ipsec_config_t *config)
Initialize IPSEC configuration options.
void odp_ipsec_sa_param_init(odp_ipsec_sa_param_t *param)
Initialize IPSEC SA parameters.
int odp_ipsec_config(const odp_ipsec_config_t *config)
Global IPSEC configuration.
int odp_ipsec_sa_disable(odp_ipsec_sa_t sa)
Disable IPSEC SA.
int odp_ipsec_out_enq(const odp_packet_t pkt[], int num, const odp_ipsec_out_param_t *param)
Outbound asynchronous IPSEC operation.
int odp_ipsec_status(odp_ipsec_status_t *status, odp_event_t event)
Get IPSEC status information from an ODP_EVENT_IPSEC_STATUS event.
#define ODP_IPSEC_SA_INVALID
Invalid IPSEC SA.
odp_ipsec_sa_t odp_ipsec_sa_create(const odp_ipsec_sa_param_t *param)
Create IPSEC SA.
int odp_ipsec_sa_destroy(odp_ipsec_sa_t sa)
Destroy IPSEC SA.
int odp_ipsec_result(odp_ipsec_packet_result_t *result, odp_packet_t packet)
Get IPSEC operation results from an IPSEC processed packet.
@ ODP_IPSEC_OP_MODE_SYNC
Synchronous IPSEC operation.
@ ODP_IPSEC_OP_MODE_ASYNC
Asynchronous IPSEC operation.
@ ODP_IPSEC_STATUS_SA_DISABLE
Response to SA disable command.
@ ODP_IPSEC_ESP
ESP protocol.
@ ODP_IPSEC_TUNNEL_IPV4
Outer header is IPv4.
@ ODP_IPSEC_MODE_TRANSPORT
IPSEC transport mode.
@ ODP_IPSEC_MODE_TUNNEL
IPSEC tunnel mode.
@ ODP_IPSEC_DIR_OUTBOUND
Outbound IPSEC SA.
void odp_packet_print_data(odp_packet_t pkt, uint32_t offset, uint32_t len)
Print packet data.
int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset)
Set layer 3 start offset.
odp_packet_vector_t odp_packet_vector_from_event(odp_event_t ev)
Get packet vector handle from event.
void * odp_packet_data(odp_packet_t pkt)
Packet data pointer.
uint32_t odp_packet_len(odp_packet_t pkt)
Packet data length.
void odp_packet_vector_free(odp_packet_vector_t pktv)
Free packet vector.
int odp_packet_copy_from_mem(odp_packet_t pkt, uint32_t offset, uint32_t len, const void *src)
Copy data from memory to packet.
uint32_t odp_packet_vector_tbl(odp_packet_vector_t pktv, odp_packet_t **pkt_tbl)
Get packet vector table.
int odp_packet_alloc_multi(odp_pool_t pool, uint32_t len, odp_packet_t pkt[], int num)
Allocate multiple packets from a packet pool.
void odp_packet_free_sp(const odp_packet_t pkt[], int num)
Free multiple packets to the same pool.
uint32_t odp_packet_vector_size(odp_packet_vector_t pktv)
Number of packets in a vector.
odp_pool_t odp_pool_create(const char *name, const odp_pool_param_t *param)
Create a pool.
int odp_pool_capability(odp_pool_capability_t *capa)
Query pool capabilities.
void odp_pool_param_init(odp_pool_param_t *param)
Initialize pool params.
int odp_pool_destroy(odp_pool_t pool)
Destroy a pool previously created by odp_pool_create()
void odp_pool_print(odp_pool_t pool)
Print pool info.
odp_pool_t odp_pool_lookup(const char *name)
Find a pool by name.
#define ODP_POOL_INVALID
Invalid pool.
@ ODP_POOL_VECTOR
Vector event pool.
@ ODP_POOL_PACKET
Packet pool.
odp_queue_t odp_queue_lookup(const char *name)
Find a queue by name.
void odp_queue_param_init(odp_queue_param_t *param)
Initialize queue params.
#define ODP_QUEUE_INVALID
Invalid queue.
odp_event_t odp_queue_deq(odp_queue_t queue)
Dequeue an event from a queue.
odp_queue_t odp_queue_create(const char *name, const odp_queue_param_t *param)
Queue create.
int odp_queue_destroy(odp_queue_t queue)
Destroy ODP queue.
int odp_queue_deq_multi(odp_queue_t queue, odp_event_t events[], int num)
Dequeue multiple events from a queue.
@ ODP_QUEUE_TYPE_SCHED
Scheduled queue.
@ ODP_QUEUE_TYPE_PLAIN
Plain queue.
#define ODP_SCHED_SYNC_PARALLEL
Parallel scheduled queues.
int odp_schedule_multi(odp_queue_t *from, uint64_t wait, odp_event_t events[], int num)
Schedule multiple events.
#define ODP_SCHED_NO_WAIT
Do not wait.
int odp_schedule_default_prio(void)
Default scheduling priority level.
int odp_schedule_config(const odp_schedule_config_t *config)
Global schedule configuration.
odp_event_t odp_schedule(odp_queue_t *from, uint64_t wait)
Schedule an event.
#define ODP_SCHED_GROUP_ALL
Group of all threads.
@ ODP_SUPPORT_NO
Feature is not supported.
void odp_sys_info_print(void)
Print system info.
@ ODP_THREAD_WORKER
Worker thread.
The OpenDataPlane API.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
odp_pktin_vector_capability_t vector
Support for returning completion packets as vectors.
odp_bool_t queue_type_sched
Scheduled queue support.
odp_bool_t queue_type_plain
Plain queue support.
odp_support_t proto_ah
IP Authenticated Header (ODP_IPSEC_AH) support.
IPSEC configuration options.
odp_pktin_vector_config_t vector
Packet vector configuration for async and inline operations.
odp_ipsec_op_mode_t outbound_mode
Outbound IPSEC operation mode.
odp_ipsec_inbound_config_t inbound
IPSEC inbound processing configuration.
uint32_t max_num_sa
Maximum number of IPSEC SAs that application will use simultaneously.
odp_ipsec_outbound_config_t outbound
IPSEC outbound processing configuration.
odp_ipsec_op_mode_t inbound_mode
Inbound IPSEC operation mode.
IPSEC crypto parameters.
odp_cipher_alg_t cipher_alg
Cipher algorithm.
uint32_t all
All error bits.
odp_queue_t default_queue
Default destination queue for IPSEC events.
odp_proto_chksums_t chksums
Flags to control IPSEC payload data checks up to the selected parse level.
uint8_t ttl
IPv4 Time To Live.
void * src_addr
IPv4 source address (NETWORK ENDIAN)
void * dst_addr
IPv4 destination address (NETWORK ENDIAN)
odp_ipsec_error_t error
IPSEC errors.
IPSEC outbound operation parameters.
int num_opt
Number of outbound operation options.
const odp_ipsec_sa_t * sa
Pointer to an array of IPSEC SAs.
uint32_t all_chksum
All bits of the bit field structure.
IPSEC operation result for a packet.
odp_ipsec_op_status_t status
IPSEC operation status.
IPSEC Security Association (SA) parameters.
odp_ipsec_crypto_param_t crypto
Parameters for crypto and authentication algorithms.
odp_queue_t dest_queue
Destination queue for IPSEC events.
odp_ipsec_mode_t mode
IPSEC protocol mode: transport or tunnel.
odp_ipsec_dir_t dir
IPSEC SA direction: inbound or outbound.
struct odp_ipsec_sa_param_t::@47::@50 outbound
Outbound specific parameters.
odp_ipsec_protocol_t proto
IPSEC protocol: ESP or AH.
IPSEC status content.
odp_ipsec_sa_t sa
IPSEC SA that was target of the operation.
odp_ipsec_status_id_t id
IPSEC status ID.
IPSEC tunnel parameters.
odp_ipsec_tunnel_type_t type
Tunnel type: IPv4 or IPv6.
odp_ipsec_ipv4_param_t ipv4
IPv4 header parameters.
uint64_t max_tmo_ns
Maximum timeout in nanoseconds for the producer to wait for the vector of packets.
odp_support_t supported
Packet input vector availability.
odp_bool_t enable
Enable packet input vector.
uint32_t max_size
Maximum number of packets in a vector.
uint64_t max_tmo_ns
Maximum time to wait for packets.
struct odp_pool_capability_t::@122 pkt
Packet pool capabilities
struct odp_pool_capability_t::@124 vector
Vector pool capabilities.
uint32_t max_size
Maximum buffer data size in bytes.
uint32_t max_pools
Maximum number of pools of any type (odp_pool_type_t)
uint32_t max_seg_len
Maximum packet segment data length in bytes.
Pool parameters.
uint32_t num
Number of buffers in the pool.
odp_pool_type_t type
Pool type.
uint32_t len
Minimum length of 'num' packets.
uint32_t max_size
Maximum number of handles (such as odp_packet_t) in a vector.
uint32_t seg_len
Minimum number of packet data bytes that can be stored in the first segment of a newly allocated pack...
struct odp_pool_param_t::@126 pkt
Parameters for packet pools.
struct odp_pool_param_t::@128 vector
Parameters for vector pools.
ODP Queue parameters.
odp_schedule_param_t sched
Scheduler parameters.
odp_queue_type_t type
Queue type.
odp_schedule_group_t group
Thread group.
odp_schedule_prio_t prio
Priority level.
odp_schedule_sync_t sync
Synchronization method.
uint32_t all_chksum
All checksum bits.