mempool: fix slow allocation of large mempools
[dpdk.git] / app / test-crypto-perf / cperf_options_parsing.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2016-2017 Intel Corporation
3  */
4
5 #include <getopt.h>
6 #include <unistd.h>
7
8 #include <rte_cryptodev.h>
9 #include <rte_malloc.h>
10
11 #include "cperf_options.h"
12
13 #define AES_BLOCK_SIZE 16
14 #define DES_BLOCK_SIZE 8
15
16 struct name_id_map {
17         const char *name;
18         uint32_t id;
19 };
20
21 static void
22 usage(char *progname)
23 {
24         printf("%s [EAL options] --\n"
25                 " --silent: disable options dump\n"
26                 " --ptest throughput / latency / verify / pmd-cycleount :"
27                 " set test type\n"
28                 " --pool_sz N: set the number of crypto ops/mbufs allocated\n"
29                 " --total-ops N: set the number of total operations performed\n"
30                 " --burst-sz N: set the number of packets per burst\n"
31                 " --buffer-sz N: set the size of a single packet\n"
32                 " --imix N: set the distribution of packet sizes\n"
33                 " --segment-sz N: set the size of the segment to use\n"
34                 " --desc-nb N: set number of descriptors for each crypto device\n"
35                 " --devtype TYPE: set crypto device type to use\n"
36                 " --optype cipher-only / auth-only / cipher-then-auth /\n"
37                 "           auth-then-cipher / aead : set operation type\n"
38                 " --sessionless: enable session-less crypto operations\n"
39                 " --out-of-place: enable out-of-place crypto operations\n"
40                 " --test-file NAME: set the test vector file path\n"
41                 " --test-name NAME: set specific test name section in test file\n"
42                 " --cipher-algo ALGO: set cipher algorithm\n"
43                 " --cipher-op encrypt / decrypt: set the cipher operation\n"
44                 " --cipher-key-sz N: set the cipher key size\n"
45                 " --cipher-iv-sz N: set the cipher IV size\n"
46                 " --auth-algo ALGO: set auth algorithm\n"
47                 " --auth-op generate / verify: set the auth operation\n"
48                 " --auth-key-sz N: set the auth key size\n"
49                 " --auth-iv-sz N: set the auth IV size\n"
50                 " --aead-algo ALGO: set AEAD algorithm\n"
51                 " --aead-op encrypt / decrypt: set the AEAD operation\n"
52                 " --aead-key-sz N: set the AEAD key size\n"
53                 " --aead-iv-sz N: set the AEAD IV size\n"
54                 " --aead-aad-sz N: set the AEAD AAD size\n"
55                 " --digest-sz N: set the digest size\n"
56                 " --pmd-cyclecount-delay-ms N: set delay between enqueue\n"
57                 "           and dequeue in pmd-cyclecount benchmarking mode\n"
58                 " --csv-friendly: enable test result output CSV friendly\n"
59                 " -h: prints this help\n",
60                 progname);
61 }
62
63 static int
64 get_str_key_id_mapping(struct name_id_map *map, unsigned int map_len,
65                 const char *str_key)
66 {
67         unsigned int i;
68
69         for (i = 0; i < map_len; i++) {
70
71                 if (strcmp(str_key, map[i].name) == 0)
72                         return map[i].id;
73         }
74
75         return -1;
76 }
77
78 static int
79 parse_cperf_test_type(struct cperf_options *opts, const char *arg)
80 {
81         struct name_id_map cperftest_namemap[] = {
82                 {
83                         cperf_test_type_strs[CPERF_TEST_TYPE_THROUGHPUT],
84                         CPERF_TEST_TYPE_THROUGHPUT
85                 },
86                 {
87                         cperf_test_type_strs[CPERF_TEST_TYPE_VERIFY],
88                         CPERF_TEST_TYPE_VERIFY
89                 },
90                 {
91                         cperf_test_type_strs[CPERF_TEST_TYPE_LATENCY],
92                         CPERF_TEST_TYPE_LATENCY
93                 },
94                 {
95                         cperf_test_type_strs[CPERF_TEST_TYPE_PMDCC],
96                         CPERF_TEST_TYPE_PMDCC
97                 }
98         };
99
100         int id = get_str_key_id_mapping(
101                         (struct name_id_map *)cperftest_namemap,
102                         RTE_DIM(cperftest_namemap), arg);
103         if (id < 0) {
104                 RTE_LOG(ERR, USER1, "failed to parse test type");
105                 return -1;
106         }
107
108         opts->test = (enum cperf_perf_test_type)id;
109
110         return 0;
111 }
112
113 static int
114 parse_uint32_t(uint32_t *value, const char *arg)
115 {
116         char *end = NULL;
117         unsigned long n = strtoul(arg, &end, 10);
118
119         if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0'))
120                 return -1;
121
122         if (n > UINT32_MAX)
123                 return -ERANGE;
124
125         *value = (uint32_t) n;
126
127         return 0;
128 }
129
130 static int
131 parse_uint16_t(uint16_t *value, const char *arg)
132 {
133         uint32_t val = 0;
134         int ret = parse_uint32_t(&val, arg);
135
136         if (ret < 0)
137                 return ret;
138
139         if (val > UINT16_MAX)
140                 return -ERANGE;
141
142         *value = (uint16_t) val;
143
144         return 0;
145 }
146
147 static int
148 parse_range(const char *arg, uint32_t *min, uint32_t *max, uint32_t *inc)
149 {
150         char *token;
151         uint32_t number;
152
153         char *copy_arg = strdup(arg);
154
155         if (copy_arg == NULL)
156                 return -1;
157
158         errno = 0;
159         token = strtok(copy_arg, ":");
160
161         /* Parse minimum value */
162         if (token != NULL) {
163                 number = strtoul(token, NULL, 10);
164
165                 if (errno == EINVAL || errno == ERANGE ||
166                                 number == 0)
167                         goto err_range;
168
169                 *min = number;
170         } else
171                 goto err_range;
172
173         token = strtok(NULL, ":");
174
175         /* Parse increment value */
176         if (token != NULL) {
177                 number = strtoul(token, NULL, 10);
178
179                 if (errno == EINVAL || errno == ERANGE ||
180                                 number == 0)
181                         goto err_range;
182
183                 *inc = number;
184         } else
185                 goto err_range;
186
187         token = strtok(NULL, ":");
188
189         /* Parse maximum value */
190         if (token != NULL) {
191                 number = strtoul(token, NULL, 10);
192
193                 if (errno == EINVAL || errno == ERANGE ||
194                                 number == 0 ||
195                                 number < *min)
196                         goto err_range;
197
198                 *max = number;
199         } else
200                 goto err_range;
201
202         if (strtok(NULL, ":") != NULL)
203                 goto err_range;
204
205         free(copy_arg);
206         return 0;
207
208 err_range:
209         free(copy_arg);
210         return -1;
211 }
212
213 static int
214 parse_list(const char *arg, uint32_t *list, uint32_t *min, uint32_t *max)
215 {
216         char *token;
217         uint32_t number;
218         uint8_t count = 0;
219         uint32_t temp_min;
220         uint32_t temp_max;
221
222         char *copy_arg = strdup(arg);
223
224         if (copy_arg == NULL)
225                 return -1;
226
227         errno = 0;
228         token = strtok(copy_arg, ",");
229
230         /* Parse first value */
231         if (token != NULL) {
232                 number = strtoul(token, NULL, 10);
233
234                 if (errno == EINVAL || errno == ERANGE ||
235                                 number == 0)
236                         goto err_list;
237
238                 list[count++] = number;
239                 temp_min = number;
240                 temp_max = number;
241         } else
242                 goto err_list;
243
244         token = strtok(NULL, ",");
245
246         while (token != NULL) {
247                 if (count == MAX_LIST) {
248                         RTE_LOG(WARNING, USER1, "Using only the first %u sizes\n",
249                                         MAX_LIST);
250                         break;
251                 }
252
253                 number = strtoul(token, NULL, 10);
254
255                 if (errno == EINVAL || errno == ERANGE ||
256                                 number == 0)
257                         goto err_list;
258
259                 list[count++] = number;
260
261                 if (number < temp_min)
262                         temp_min = number;
263                 if (number > temp_max)
264                         temp_max = number;
265
266                 token = strtok(NULL, ",");
267         }
268
269         if (min)
270                 *min = temp_min;
271         if (max)
272                 *max = temp_max;
273
274         free(copy_arg);
275         return count;
276
277 err_list:
278         free(copy_arg);
279         return -1;
280 }
281
282 static int
283 parse_total_ops(struct cperf_options *opts, const char *arg)
284 {
285         int ret = parse_uint32_t(&opts->total_ops, arg);
286
287         if (ret)
288                 RTE_LOG(ERR, USER1, "failed to parse total operations count\n");
289
290         if (opts->total_ops == 0) {
291                 RTE_LOG(ERR, USER1,
292                                 "invalid total operations count number specified\n");
293                 return -1;
294         }
295
296         return ret;
297 }
298
299 static int
300 parse_pool_sz(struct cperf_options *opts, const char *arg)
301 {
302         int ret =  parse_uint32_t(&opts->pool_sz, arg);
303
304         if (ret)
305                 RTE_LOG(ERR, USER1, "failed to parse pool size");
306         return ret;
307 }
308
309 static int
310 parse_burst_sz(struct cperf_options *opts, const char *arg)
311 {
312         int ret;
313
314         /* Try parsing the argument as a range, if it fails, parse it as a list */
315         if (parse_range(arg, &opts->min_burst_size, &opts->max_burst_size,
316                         &opts->inc_burst_size) < 0) {
317                 ret = parse_list(arg, opts->burst_size_list,
318                                         &opts->min_burst_size,
319                                         &opts->max_burst_size);
320                 if (ret < 0) {
321                         RTE_LOG(ERR, USER1, "failed to parse burst size/s\n");
322                         return -1;
323                 }
324                 opts->burst_size_count = ret;
325         }
326
327         return 0;
328 }
329
330 static int
331 parse_buffer_sz(struct cperf_options *opts, const char *arg)
332 {
333         int ret;
334
335         /* Try parsing the argument as a range, if it fails, parse it as a list */
336         if (parse_range(arg, &opts->min_buffer_size, &opts->max_buffer_size,
337                         &opts->inc_buffer_size) < 0) {
338                 ret = parse_list(arg, opts->buffer_size_list,
339                                         &opts->min_buffer_size,
340                                         &opts->max_buffer_size);
341                 if (ret < 0) {
342                         RTE_LOG(ERR, USER1, "failed to parse buffer size/s\n");
343                         return -1;
344                 }
345                 opts->buffer_size_count = ret;
346         }
347
348         return 0;
349 }
350
351 static int
352 parse_segment_sz(struct cperf_options *opts, const char *arg)
353 {
354         int ret = parse_uint32_t(&opts->segment_sz, arg);
355
356         if (ret) {
357                 RTE_LOG(ERR, USER1, "failed to parse segment size\n");
358                 return -1;
359         }
360
361         if (opts->segment_sz == 0) {
362                 RTE_LOG(ERR, USER1, "Segment size has to be bigger than 0\n");
363                 return -1;
364         }
365
366         return 0;
367 }
368
369 static int
370 parse_imix(struct cperf_options *opts, const char *arg)
371 {
372         int ret;
373
374         ret = parse_list(arg, opts->imix_distribution_list,
375                                 NULL, NULL);
376         if (ret < 0) {
377                 RTE_LOG(ERR, USER1, "failed to parse imix distribution\n");
378                 return -1;
379         }
380
381         opts->imix_distribution_count = ret;
382
383         if (opts->imix_distribution_count <= 1) {
384                 RTE_LOG(ERR, USER1, "imix distribution should have "
385                                 "at least two entries\n");
386                 return -1;
387         }
388
389         return 0;
390 }
391
392 static int
393 parse_desc_nb(struct cperf_options *opts, const char *arg)
394 {
395         int ret = parse_uint32_t(&opts->nb_descriptors, arg);
396
397         if (ret) {
398                 RTE_LOG(ERR, USER1, "failed to parse descriptors number\n");
399                 return -1;
400         }
401
402         if (opts->nb_descriptors == 0) {
403                 RTE_LOG(ERR, USER1, "invalid descriptors number specified\n");
404                 return -1;
405         }
406
407         return 0;
408 }
409
410 static int
411 parse_device_type(struct cperf_options *opts, const char *arg)
412 {
413         if (strlen(arg) > (sizeof(opts->device_type) - 1))
414                 return -1;
415
416         strncpy(opts->device_type, arg, sizeof(opts->device_type) - 1);
417         *(opts->device_type + sizeof(opts->device_type) - 1) = '\0';
418
419         return 0;
420 }
421
422 static int
423 parse_op_type(struct cperf_options *opts, const char *arg)
424 {
425         struct name_id_map optype_namemap[] = {
426                 {
427                         cperf_op_type_strs[CPERF_CIPHER_ONLY],
428                         CPERF_CIPHER_ONLY
429                 },
430                 {
431                         cperf_op_type_strs[CPERF_AUTH_ONLY],
432                         CPERF_AUTH_ONLY
433                 },
434                 {
435                         cperf_op_type_strs[CPERF_CIPHER_THEN_AUTH],
436                         CPERF_CIPHER_THEN_AUTH
437                 },
438                 {
439                         cperf_op_type_strs[CPERF_AUTH_THEN_CIPHER],
440                         CPERF_AUTH_THEN_CIPHER
441                 },
442                 {
443                         cperf_op_type_strs[CPERF_AEAD],
444                         CPERF_AEAD
445                 },
446                 {
447                         cperf_op_type_strs[CPERF_PDCP],
448                         CPERF_PDCP
449                 }
450         };
451
452         int id = get_str_key_id_mapping(optype_namemap,
453                         RTE_DIM(optype_namemap), arg);
454         if (id < 0) {
455                 RTE_LOG(ERR, USER1, "invalid opt type specified\n");
456                 return -1;
457         }
458
459         opts->op_type = (enum cperf_op_type)id;
460
461         return 0;
462 }
463
464 static int
465 parse_sessionless(struct cperf_options *opts,
466                 const char *arg __rte_unused)
467 {
468         opts->sessionless = 1;
469         return 0;
470 }
471
472 static int
473 parse_out_of_place(struct cperf_options *opts,
474                 const char *arg __rte_unused)
475 {
476         opts->out_of_place = 1;
477         return 0;
478 }
479
480 static int
481 parse_test_file(struct cperf_options *opts,
482                 const char *arg)
483 {
484         opts->test_file = strdup(arg);
485         if (access(opts->test_file, F_OK) != -1)
486                 return 0;
487         RTE_LOG(ERR, USER1, "Test vector file doesn't exist\n");
488
489         return -1;
490 }
491
492 static int
493 parse_test_name(struct cperf_options *opts,
494                 const char *arg)
495 {
496         char *test_name = (char *) rte_zmalloc(NULL,
497                 sizeof(char) * (strlen(arg) + 3), 0);
498         snprintf(test_name, strlen(arg) + 3, "[%s]", arg);
499         opts->test_name = test_name;
500
501         return 0;
502 }
503
504 static int
505 parse_silent(struct cperf_options *opts,
506                 const char *arg __rte_unused)
507 {
508         opts->silent = 1;
509
510         return 0;
511 }
512
513 static int
514 parse_cipher_algo(struct cperf_options *opts, const char *arg)
515 {
516
517         enum rte_crypto_cipher_algorithm cipher_algo;
518
519         if (rte_cryptodev_get_cipher_algo_enum(&cipher_algo, arg) < 0) {
520                 RTE_LOG(ERR, USER1, "Invalid cipher algorithm specified\n");
521                 return -1;
522         }
523
524         opts->cipher_algo = cipher_algo;
525
526         return 0;
527 }
528
529 static int
530 parse_cipher_op(struct cperf_options *opts, const char *arg)
531 {
532         struct name_id_map cipher_op_namemap[] = {
533                 {
534                         rte_crypto_cipher_operation_strings
535                         [RTE_CRYPTO_CIPHER_OP_ENCRYPT],
536                         RTE_CRYPTO_CIPHER_OP_ENCRYPT },
537                 {
538                         rte_crypto_cipher_operation_strings
539                         [RTE_CRYPTO_CIPHER_OP_DECRYPT],
540                         RTE_CRYPTO_CIPHER_OP_DECRYPT
541                 }
542         };
543
544         int id = get_str_key_id_mapping(cipher_op_namemap,
545                         RTE_DIM(cipher_op_namemap), arg);
546         if (id < 0) {
547                 RTE_LOG(ERR, USER1, "Invalid cipher operation specified\n");
548                 return -1;
549         }
550
551         opts->cipher_op = (enum rte_crypto_cipher_operation)id;
552
553         return 0;
554 }
555
556 static int
557 parse_cipher_key_sz(struct cperf_options *opts, const char *arg)
558 {
559         return parse_uint16_t(&opts->cipher_key_sz, arg);
560 }
561
562 static int
563 parse_cipher_iv_sz(struct cperf_options *opts, const char *arg)
564 {
565         return parse_uint16_t(&opts->cipher_iv_sz, arg);
566 }
567
568 static int
569 parse_auth_algo(struct cperf_options *opts, const char *arg)
570 {
571         enum rte_crypto_auth_algorithm auth_algo;
572
573         if (rte_cryptodev_get_auth_algo_enum(&auth_algo, arg) < 0) {
574                 RTE_LOG(ERR, USER1, "Invalid authentication algorithm specified\n");
575                 return -1;
576         }
577
578         opts->auth_algo = auth_algo;
579
580         return 0;
581 }
582
583 static int
584 parse_auth_op(struct cperf_options *opts, const char *arg)
585 {
586         struct name_id_map auth_op_namemap[] = {
587                 {
588                         rte_crypto_auth_operation_strings
589                         [RTE_CRYPTO_AUTH_OP_GENERATE],
590                         RTE_CRYPTO_AUTH_OP_GENERATE },
591                 {
592                         rte_crypto_auth_operation_strings
593                         [RTE_CRYPTO_AUTH_OP_VERIFY],
594                         RTE_CRYPTO_AUTH_OP_VERIFY
595                 }
596         };
597
598         int id = get_str_key_id_mapping(auth_op_namemap,
599                         RTE_DIM(auth_op_namemap), arg);
600         if (id < 0) {
601                 RTE_LOG(ERR, USER1, "invalid authentication operation specified"
602                                 "\n");
603                 return -1;
604         }
605
606         opts->auth_op = (enum rte_crypto_auth_operation)id;
607
608         return 0;
609 }
610
611 static int
612 parse_auth_key_sz(struct cperf_options *opts, const char *arg)
613 {
614         return parse_uint16_t(&opts->auth_key_sz, arg);
615 }
616
617 static int
618 parse_digest_sz(struct cperf_options *opts, const char *arg)
619 {
620         return parse_uint16_t(&opts->digest_sz, arg);
621 }
622
623 #ifdef RTE_LIBRTE_SECURITY
624 static int
625 parse_pdcp_sn_sz(struct cperf_options *opts, const char *arg)
626 {
627         uint32_t val = 0;
628         int ret = parse_uint32_t(&val, arg);
629
630         if (ret < 0)
631                 return ret;
632
633         if (val != RTE_SECURITY_PDCP_SN_SIZE_5 &&
634                         val != RTE_SECURITY_PDCP_SN_SIZE_7 &&
635                         val != RTE_SECURITY_PDCP_SN_SIZE_12 &&
636                         val != RTE_SECURITY_PDCP_SN_SIZE_15 &&
637                         val != RTE_SECURITY_PDCP_SN_SIZE_18) {
638                 printf("\nInvalid pdcp SN size: %u\n", val);
639                 return -ERANGE;
640         }
641         opts->pdcp_sn_sz = val;
642
643         return 0;
644 }
645
646 const char *cperf_pdcp_domain_strs[] = {
647         [RTE_SECURITY_PDCP_MODE_CONTROL] = "control",
648         [RTE_SECURITY_PDCP_MODE_DATA] = "data"
649 };
650
651 static int
652 parse_pdcp_domain(struct cperf_options *opts, const char *arg)
653 {
654         struct name_id_map pdcp_domain_namemap[] = {
655                 {
656                         cperf_pdcp_domain_strs
657                         [RTE_SECURITY_PDCP_MODE_CONTROL],
658                         RTE_SECURITY_PDCP_MODE_CONTROL },
659                 {
660                         cperf_pdcp_domain_strs
661                         [RTE_SECURITY_PDCP_MODE_DATA],
662                         RTE_SECURITY_PDCP_MODE_DATA
663                 }
664         };
665
666         int id = get_str_key_id_mapping(pdcp_domain_namemap,
667                         RTE_DIM(pdcp_domain_namemap), arg);
668         if (id < 0) {
669                 RTE_LOG(ERR, USER1, "invalid pdcp domain specified"
670                                 "\n");
671                 return -1;
672         }
673
674         opts->pdcp_domain = (enum rte_security_pdcp_domain)id;
675
676         return 0;
677 }
678 #endif
679
680 static int
681 parse_auth_iv_sz(struct cperf_options *opts, const char *arg)
682 {
683         return parse_uint16_t(&opts->auth_iv_sz, arg);
684 }
685
686 static int
687 parse_aead_algo(struct cperf_options *opts, const char *arg)
688 {
689         enum rte_crypto_aead_algorithm aead_algo;
690
691         if (rte_cryptodev_get_aead_algo_enum(&aead_algo, arg) < 0) {
692                 RTE_LOG(ERR, USER1, "Invalid AEAD algorithm specified\n");
693                 return -1;
694         }
695
696         opts->aead_algo = aead_algo;
697
698         return 0;
699 }
700
701 static int
702 parse_aead_op(struct cperf_options *opts, const char *arg)
703 {
704         struct name_id_map aead_op_namemap[] = {
705                 {
706                         rte_crypto_aead_operation_strings
707                         [RTE_CRYPTO_AEAD_OP_ENCRYPT],
708                         RTE_CRYPTO_AEAD_OP_ENCRYPT },
709                 {
710                         rte_crypto_aead_operation_strings
711                         [RTE_CRYPTO_AEAD_OP_DECRYPT],
712                         RTE_CRYPTO_AEAD_OP_DECRYPT
713                 }
714         };
715
716         int id = get_str_key_id_mapping(aead_op_namemap,
717                         RTE_DIM(aead_op_namemap), arg);
718         if (id < 0) {
719                 RTE_LOG(ERR, USER1, "invalid AEAD operation specified"
720                                 "\n");
721                 return -1;
722         }
723
724         opts->aead_op = (enum rte_crypto_aead_operation)id;
725
726         return 0;
727 }
728
729 static int
730 parse_aead_key_sz(struct cperf_options *opts, const char *arg)
731 {
732         return parse_uint16_t(&opts->aead_key_sz, arg);
733 }
734
735 static int
736 parse_aead_iv_sz(struct cperf_options *opts, const char *arg)
737 {
738         return parse_uint16_t(&opts->aead_iv_sz, arg);
739 }
740
741 static int
742 parse_aead_aad_sz(struct cperf_options *opts, const char *arg)
743 {
744         return parse_uint16_t(&opts->aead_aad_sz, arg);
745 }
746
747 static int
748 parse_csv_friendly(struct cperf_options *opts, const char *arg __rte_unused)
749 {
750         opts->csv = 1;
751         opts->silent = 1;
752         return 0;
753 }
754
755 static int
756 parse_pmd_cyclecount_delay_ms(struct cperf_options *opts,
757                         const char *arg)
758 {
759         int ret = parse_uint32_t(&opts->pmdcc_delay, arg);
760
761         if (ret) {
762                 RTE_LOG(ERR, USER1, "failed to parse pmd-cyclecount delay\n");
763                 return -1;
764         }
765
766         return 0;
767 }
768
769 typedef int (*option_parser_t)(struct cperf_options *opts,
770                 const char *arg);
771
772 struct long_opt_parser {
773         const char *lgopt_name;
774         option_parser_t parser_fn;
775
776 };
777
778 static struct option lgopts[] = {
779
780         { CPERF_PTEST_TYPE, required_argument, 0, 0 },
781
782         { CPERF_POOL_SIZE, required_argument, 0, 0 },
783         { CPERF_TOTAL_OPS, required_argument, 0, 0 },
784         { CPERF_BURST_SIZE, required_argument, 0, 0 },
785         { CPERF_BUFFER_SIZE, required_argument, 0, 0 },
786         { CPERF_SEGMENT_SIZE, required_argument, 0, 0 },
787         { CPERF_DESC_NB, required_argument, 0, 0 },
788
789         { CPERF_IMIX, required_argument, 0, 0 },
790         { CPERF_DEVTYPE, required_argument, 0, 0 },
791         { CPERF_OPTYPE, required_argument, 0, 0 },
792
793         { CPERF_SILENT, no_argument, 0, 0 },
794         { CPERF_SESSIONLESS, no_argument, 0, 0 },
795         { CPERF_OUT_OF_PLACE, no_argument, 0, 0 },
796         { CPERF_TEST_FILE, required_argument, 0, 0 },
797         { CPERF_TEST_NAME, required_argument, 0, 0 },
798
799         { CPERF_CIPHER_ALGO, required_argument, 0, 0 },
800         { CPERF_CIPHER_OP, required_argument, 0, 0 },
801
802         { CPERF_CIPHER_KEY_SZ, required_argument, 0, 0 },
803         { CPERF_CIPHER_IV_SZ, required_argument, 0, 0 },
804
805         { CPERF_AUTH_ALGO, required_argument, 0, 0 },
806         { CPERF_AUTH_OP, required_argument, 0, 0 },
807
808         { CPERF_AUTH_KEY_SZ, required_argument, 0, 0 },
809         { CPERF_AUTH_IV_SZ, required_argument, 0, 0 },
810
811         { CPERF_AEAD_ALGO, required_argument, 0, 0 },
812         { CPERF_AEAD_OP, required_argument, 0, 0 },
813
814         { CPERF_AEAD_KEY_SZ, required_argument, 0, 0 },
815         { CPERF_AEAD_AAD_SZ, required_argument, 0, 0 },
816         { CPERF_AEAD_IV_SZ, required_argument, 0, 0 },
817
818         { CPERF_DIGEST_SZ, required_argument, 0, 0 },
819
820 #ifdef RTE_LIBRTE_SECURITY
821         { CPERF_PDCP_SN_SZ, required_argument, 0, 0 },
822         { CPERF_PDCP_DOMAIN, required_argument, 0, 0 },
823 #endif
824         { CPERF_CSV, no_argument, 0, 0},
825
826         { CPERF_PMDCC_DELAY_MS, required_argument, 0, 0 },
827
828         { NULL, 0, 0, 0 }
829 };
830
831 void
832 cperf_options_default(struct cperf_options *opts)
833 {
834         opts->test = CPERF_TEST_TYPE_THROUGHPUT;
835
836         opts->pool_sz = 8192;
837         opts->total_ops = 10000000;
838         opts->nb_descriptors = 2048;
839
840         opts->buffer_size_list[0] = 64;
841         opts->buffer_size_count = 1;
842         opts->max_buffer_size = 64;
843         opts->min_buffer_size = 64;
844         opts->inc_buffer_size = 0;
845
846         opts->burst_size_list[0] = 32;
847         opts->burst_size_count = 1;
848         opts->max_burst_size = 32;
849         opts->min_burst_size = 32;
850         opts->inc_burst_size = 0;
851
852         /*
853          * Will be parsed from command line or set to
854          * maximum buffer size + digest, later
855          */
856         opts->segment_sz = 0;
857
858         opts->imix_distribution_count = 0;
859         strncpy(opts->device_type, "crypto_aesni_mb",
860                         sizeof(opts->device_type));
861         opts->nb_qps = 1;
862
863         opts->op_type = CPERF_CIPHER_THEN_AUTH;
864
865         opts->silent = 0;
866         opts->test_file = NULL;
867         opts->test_name = NULL;
868         opts->sessionless = 0;
869         opts->out_of_place = 0;
870         opts->csv = 0;
871
872         opts->cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC;
873         opts->cipher_op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
874         opts->cipher_key_sz = 16;
875         opts->cipher_iv_sz = 16;
876
877         opts->auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
878         opts->auth_op = RTE_CRYPTO_AUTH_OP_GENERATE;
879
880         opts->auth_key_sz = 64;
881         opts->auth_iv_sz = 0;
882
883         opts->aead_key_sz = 0;
884         opts->aead_iv_sz = 0;
885         opts->aead_aad_sz = 0;
886
887         opts->digest_sz = 12;
888
889         opts->pmdcc_delay = 0;
890 #ifdef RTE_LIBRTE_SECURITY
891         opts->pdcp_sn_sz = 12;
892         opts->pdcp_domain = RTE_SECURITY_PDCP_MODE_CONTROL;
893 #endif
894 }
895
896 static int
897 cperf_opts_parse_long(int opt_idx, struct cperf_options *opts)
898 {
899         struct long_opt_parser parsermap[] = {
900                 { CPERF_PTEST_TYPE,     parse_cperf_test_type },
901                 { CPERF_SILENT,         parse_silent },
902                 { CPERF_POOL_SIZE,      parse_pool_sz },
903                 { CPERF_TOTAL_OPS,      parse_total_ops },
904                 { CPERF_BURST_SIZE,     parse_burst_sz },
905                 { CPERF_BUFFER_SIZE,    parse_buffer_sz },
906                 { CPERF_SEGMENT_SIZE,   parse_segment_sz },
907                 { CPERF_DESC_NB,        parse_desc_nb },
908                 { CPERF_DEVTYPE,        parse_device_type },
909                 { CPERF_OPTYPE,         parse_op_type },
910                 { CPERF_SESSIONLESS,    parse_sessionless },
911                 { CPERF_OUT_OF_PLACE,   parse_out_of_place },
912                 { CPERF_IMIX,           parse_imix },
913                 { CPERF_TEST_FILE,      parse_test_file },
914                 { CPERF_TEST_NAME,      parse_test_name },
915                 { CPERF_CIPHER_ALGO,    parse_cipher_algo },
916                 { CPERF_CIPHER_OP,      parse_cipher_op },
917                 { CPERF_CIPHER_KEY_SZ,  parse_cipher_key_sz },
918                 { CPERF_CIPHER_IV_SZ,   parse_cipher_iv_sz },
919                 { CPERF_AUTH_ALGO,      parse_auth_algo },
920                 { CPERF_AUTH_OP,        parse_auth_op },
921                 { CPERF_AUTH_KEY_SZ,    parse_auth_key_sz },
922                 { CPERF_AUTH_IV_SZ,     parse_auth_iv_sz },
923                 { CPERF_AEAD_ALGO,      parse_aead_algo },
924                 { CPERF_AEAD_OP,        parse_aead_op },
925                 { CPERF_AEAD_KEY_SZ,    parse_aead_key_sz },
926                 { CPERF_AEAD_IV_SZ,     parse_aead_iv_sz },
927                 { CPERF_AEAD_AAD_SZ,    parse_aead_aad_sz },
928                 { CPERF_DIGEST_SZ,      parse_digest_sz },
929 #ifdef RTE_LIBRTE_SECURITY
930                 { CPERF_PDCP_SN_SZ,     parse_pdcp_sn_sz },
931                 { CPERF_PDCP_DOMAIN,    parse_pdcp_domain },
932 #endif
933                 { CPERF_CSV,            parse_csv_friendly},
934                 { CPERF_PMDCC_DELAY_MS, parse_pmd_cyclecount_delay_ms},
935         };
936         unsigned int i;
937
938         for (i = 0; i < RTE_DIM(parsermap); i++) {
939                 if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name,
940                                 strlen(lgopts[opt_idx].name)) == 0)
941                         return parsermap[i].parser_fn(opts, optarg);
942         }
943
944         return -EINVAL;
945 }
946
947 int
948 cperf_options_parse(struct cperf_options *options, int argc, char **argv)
949 {
950         int opt, retval, opt_idx;
951
952         while ((opt = getopt_long(argc, argv, "h", lgopts, &opt_idx)) != EOF) {
953                 switch (opt) {
954                 case 'h':
955                         usage(argv[0]);
956                         rte_exit(EXIT_SUCCESS, "Displayed help\n");
957                         break;
958                 /* long options */
959                 case 0:
960                         retval = cperf_opts_parse_long(opt_idx, options);
961                         if (retval != 0)
962                                 return retval;
963
964                         break;
965
966                 default:
967                         usage(argv[0]);
968                         return -EINVAL;
969                 }
970         }
971
972         return 0;
973 }
974
975 static int
976 check_cipher_buffer_length(struct cperf_options *options)
977 {
978         uint32_t buffer_size, buffer_size_idx = 0;
979
980         if (options->cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC ||
981                         options->cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB) {
982                 if (options->inc_buffer_size != 0)
983                         buffer_size = options->min_buffer_size;
984                 else
985                         buffer_size = options->buffer_size_list[0];
986
987                 while (buffer_size <= options->max_buffer_size) {
988                         if ((buffer_size % AES_BLOCK_SIZE) != 0) {
989                                 RTE_LOG(ERR, USER1, "Some of the buffer sizes are "
990                                         "not suitable for the algorithm selected\n");
991                                 return -EINVAL;
992                         }
993
994                         if (options->inc_buffer_size != 0)
995                                 buffer_size += options->inc_buffer_size;
996                         else {
997                                 if (++buffer_size_idx == options->buffer_size_count)
998                                         break;
999                                 buffer_size = options->buffer_size_list[buffer_size_idx];
1000                         }
1001
1002                 }
1003         }
1004
1005         if (options->cipher_algo == RTE_CRYPTO_CIPHER_DES_CBC ||
1006                         options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_CBC ||
1007                         options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_ECB) {
1008                 if (options->inc_buffer_size != 0)
1009                         buffer_size = options->min_buffer_size;
1010                 else
1011                         buffer_size = options->buffer_size_list[0];
1012
1013                 while (buffer_size <= options->max_buffer_size) {
1014                         if ((buffer_size % DES_BLOCK_SIZE) != 0) {
1015                                 RTE_LOG(ERR, USER1, "Some of the buffer sizes are "
1016                                         "not suitable for the algorithm selected\n");
1017                                 return -EINVAL;
1018                         }
1019
1020                         if (options->inc_buffer_size != 0)
1021                                 buffer_size += options->inc_buffer_size;
1022                         else {
1023                                 if (++buffer_size_idx == options->buffer_size_count)
1024                                         break;
1025                                 buffer_size = options->buffer_size_list[buffer_size_idx];
1026                         }
1027
1028                 }
1029         }
1030
1031         return 0;
1032 }
1033
1034 int
1035 cperf_options_check(struct cperf_options *options)
1036 {
1037         if (options->op_type == CPERF_CIPHER_ONLY)
1038                 options->digest_sz = 0;
1039
1040         if (options->out_of_place &&
1041                         options->segment_sz <= options->max_buffer_size) {
1042                 RTE_LOG(ERR, USER1, "Out of place mode can only work "
1043                                         "with non segmented buffers\n");
1044                 return -EINVAL;
1045         }
1046
1047         /*
1048          * If segment size is not set, assume only one segment,
1049          * big enough to contain the largest buffer and the digest
1050          */
1051         if (options->segment_sz == 0)
1052                 options->segment_sz = options->max_buffer_size +
1053                                 options->digest_sz;
1054
1055         if (options->segment_sz < options->digest_sz) {
1056                 RTE_LOG(ERR, USER1,
1057                                 "Segment size should be at least "
1058                                 "the size of the digest\n");
1059                 return -EINVAL;
1060         }
1061
1062         if ((options->imix_distribution_count != 0) &&
1063                         (options->imix_distribution_count !=
1064                                 options->buffer_size_count)) {
1065                 RTE_LOG(ERR, USER1, "IMIX distribution must have the same "
1066                                 "number of buffer sizes\n");
1067                 return -EINVAL;
1068         }
1069
1070         if (options->test == CPERF_TEST_TYPE_VERIFY &&
1071                         options->test_file == NULL) {
1072                 RTE_LOG(ERR, USER1, "Define path to the file with test"
1073                                 " vectors.\n");
1074                 return -EINVAL;
1075         }
1076
1077         if (options->test == CPERF_TEST_TYPE_VERIFY &&
1078                         options->op_type != CPERF_CIPHER_ONLY &&
1079                         options->test_name == NULL) {
1080                 RTE_LOG(ERR, USER1, "Define test name to get the correct digest"
1081                                 " from the test vectors.\n");
1082                 return -EINVAL;
1083         }
1084
1085         if (options->test_name != NULL && options->test_file == NULL) {
1086                 RTE_LOG(ERR, USER1, "Define path to the file with test"
1087                                 " vectors.\n");
1088                 return -EINVAL;
1089         }
1090
1091         if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY &&
1092                         options->test_file == NULL) {
1093                 RTE_LOG(ERR, USER1, "Define path to the file with test"
1094                                 " vectors.\n");
1095                 return -EINVAL;
1096         }
1097
1098         if (options->test == CPERF_TEST_TYPE_VERIFY &&
1099                         (options->inc_buffer_size != 0 ||
1100                         options->buffer_size_count > 1)) {
1101                 RTE_LOG(ERR, USER1, "Only one buffer size is allowed when "
1102                                 "using the verify test.\n");
1103                 return -EINVAL;
1104         }
1105
1106         if (options->test == CPERF_TEST_TYPE_VERIFY &&
1107                         (options->inc_burst_size != 0 ||
1108                         options->burst_size_count > 1)) {
1109                 RTE_LOG(ERR, USER1, "Only one burst size is allowed when "
1110                                 "using the verify test.\n");
1111                 return -EINVAL;
1112         }
1113
1114         if (options->test == CPERF_TEST_TYPE_PMDCC &&
1115                         options->pool_sz < options->nb_descriptors) {
1116                 RTE_LOG(ERR, USER1, "For pmd cyclecount benchmarks, pool size "
1117                                 "must be equal or greater than the number of "
1118                                 "cryptodev descriptors.\n");
1119                 return -EINVAL;
1120         }
1121
1122         if (options->test == CPERF_TEST_TYPE_VERIFY &&
1123                         options->imix_distribution_count > 0) {
1124                 RTE_LOG(ERR, USER1, "IMIX is not allowed when "
1125                                 "using the verify test.\n");
1126                 return -EINVAL;
1127         }
1128
1129         if (options->op_type == CPERF_CIPHER_THEN_AUTH) {
1130                 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
1131                                 options->auth_op !=
1132                                 RTE_CRYPTO_AUTH_OP_GENERATE) {
1133                         RTE_LOG(ERR, USER1, "Option cipher then auth must use"
1134                                         " options: encrypt and generate.\n");
1135                         return -EINVAL;
1136                 }
1137         } else if (options->op_type == CPERF_AUTH_THEN_CIPHER) {
1138                 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_DECRYPT &&
1139                                 options->auth_op !=
1140                                 RTE_CRYPTO_AUTH_OP_VERIFY) {
1141                         RTE_LOG(ERR, USER1, "Option auth then cipher must use"
1142                                         " options: decrypt and verify.\n");
1143                         return -EINVAL;
1144                 }
1145         }
1146
1147         if (options->op_type == CPERF_CIPHER_ONLY ||
1148                         options->op_type == CPERF_CIPHER_THEN_AUTH ||
1149                         options->op_type == CPERF_AUTH_THEN_CIPHER) {
1150                 if (check_cipher_buffer_length(options) < 0)
1151                         return -EINVAL;
1152         }
1153
1154         return 0;
1155 }
1156
1157 void
1158 cperf_options_dump(struct cperf_options *opts)
1159 {
1160         uint8_t size_idx;
1161
1162         printf("# Crypto Performance Application Options:\n");
1163         printf("#\n");
1164         printf("# cperf test: %s\n", cperf_test_type_strs[opts->test]);
1165         printf("#\n");
1166         printf("# size of crypto op / mbuf pool: %u\n", opts->pool_sz);
1167         printf("# total number of ops: %u\n", opts->total_ops);
1168         if (opts->inc_buffer_size != 0) {
1169                 printf("# buffer size:\n");
1170                 printf("#\t min: %u\n", opts->min_buffer_size);
1171                 printf("#\t max: %u\n", opts->max_buffer_size);
1172                 printf("#\t inc: %u\n", opts->inc_buffer_size);
1173         } else {
1174                 printf("# buffer sizes: ");
1175                 for (size_idx = 0; size_idx < opts->buffer_size_count; size_idx++)
1176                         printf("%u ", opts->buffer_size_list[size_idx]);
1177                 printf("\n");
1178         }
1179         if (opts->inc_burst_size != 0) {
1180                 printf("# burst size:\n");
1181                 printf("#\t min: %u\n", opts->min_burst_size);
1182                 printf("#\t max: %u\n", opts->max_burst_size);
1183                 printf("#\t inc: %u\n", opts->inc_burst_size);
1184         } else {
1185                 printf("# burst sizes: ");
1186                 for (size_idx = 0; size_idx < opts->burst_size_count; size_idx++)
1187                         printf("%u ", opts->burst_size_list[size_idx]);
1188                 printf("\n");
1189         }
1190         printf("\n# segment size: %u\n", opts->segment_sz);
1191         printf("#\n");
1192         printf("# cryptodev type: %s\n", opts->device_type);
1193         printf("#\n");
1194         printf("# number of queue pairs per device: %u\n", opts->nb_qps);
1195         printf("# crypto operation: %s\n", cperf_op_type_strs[opts->op_type]);
1196         printf("# sessionless: %s\n", opts->sessionless ? "yes" : "no");
1197         printf("# out of place: %s\n", opts->out_of_place ? "yes" : "no");
1198         if (opts->test == CPERF_TEST_TYPE_PMDCC)
1199                 printf("# inter-burst delay: %u ms\n", opts->pmdcc_delay);
1200
1201         printf("#\n");
1202
1203         if (opts->op_type == CPERF_AUTH_ONLY ||
1204                         opts->op_type == CPERF_CIPHER_THEN_AUTH ||
1205                         opts->op_type == CPERF_AUTH_THEN_CIPHER) {
1206                 printf("# auth algorithm: %s\n",
1207                         rte_crypto_auth_algorithm_strings[opts->auth_algo]);
1208                 printf("# auth operation: %s\n",
1209                         rte_crypto_auth_operation_strings[opts->auth_op]);
1210                 printf("# auth key size: %u\n", opts->auth_key_sz);
1211                 printf("# auth iv size: %u\n", opts->auth_iv_sz);
1212                 printf("# auth digest size: %u\n", opts->digest_sz);
1213                 printf("#\n");
1214         }
1215
1216         if (opts->op_type == CPERF_CIPHER_ONLY ||
1217                         opts->op_type == CPERF_CIPHER_THEN_AUTH ||
1218                         opts->op_type == CPERF_AUTH_THEN_CIPHER) {
1219                 printf("# cipher algorithm: %s\n",
1220                         rte_crypto_cipher_algorithm_strings[opts->cipher_algo]);
1221                 printf("# cipher operation: %s\n",
1222                         rte_crypto_cipher_operation_strings[opts->cipher_op]);
1223                 printf("# cipher key size: %u\n", opts->cipher_key_sz);
1224                 printf("# cipher iv size: %u\n", opts->cipher_iv_sz);
1225                 printf("#\n");
1226         }
1227
1228         if (opts->op_type == CPERF_AEAD) {
1229                 printf("# aead algorithm: %s\n",
1230                         rte_crypto_aead_algorithm_strings[opts->aead_algo]);
1231                 printf("# aead operation: %s\n",
1232                         rte_crypto_aead_operation_strings[opts->aead_op]);
1233                 printf("# aead key size: %u\n", opts->aead_key_sz);
1234                 printf("# aead iv size: %u\n", opts->aead_iv_sz);
1235                 printf("# aead digest size: %u\n", opts->digest_sz);
1236                 printf("# aead aad size: %u\n", opts->aead_aad_sz);
1237                 printf("#\n");
1238         }
1239 }