app/crypto-perf: fix uninitialized errno value
[dpdk.git] / app / test-crypto-perf / cperf_options_parsing.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *     * Neither the name of Intel Corporation nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <getopt.h>
34 #include <unistd.h>
35
36 #include <rte_cryptodev.h>
37 #include <rte_malloc.h>
38
39 #include "cperf_options.h"
40
41 #define AES_BLOCK_SIZE 16
42 #define DES_BLOCK_SIZE 8
43
44 struct name_id_map {
45         const char *name;
46         uint32_t id;
47 };
48
49 static int
50 get_str_key_id_mapping(struct name_id_map *map, unsigned int map_len,
51                 const char *str_key)
52 {
53         unsigned int i;
54
55         for (i = 0; i < map_len; i++) {
56
57                 if (strcmp(str_key, map[i].name) == 0)
58                         return map[i].id;
59         }
60
61         return -1;
62 }
63
64 static int
65 parse_cperf_test_type(struct cperf_options *opts, const char *arg)
66 {
67         struct name_id_map cperftest_namemap[] = {
68                 {
69                         cperf_test_type_strs[CPERF_TEST_TYPE_THROUGHPUT],
70                         CPERF_TEST_TYPE_THROUGHPUT
71                 },
72                 {
73                         cperf_test_type_strs[CPERF_TEST_TYPE_VERIFY],
74                         CPERF_TEST_TYPE_VERIFY
75                 },
76                 {
77                         cperf_test_type_strs[CPERF_TEST_TYPE_LATENCY],
78                         CPERF_TEST_TYPE_LATENCY
79                 }
80         };
81
82         int id = get_str_key_id_mapping(
83                         (struct name_id_map *)cperftest_namemap,
84                         RTE_DIM(cperftest_namemap), arg);
85         if (id < 0) {
86                 RTE_LOG(ERR, USER1, "failed to parse test type");
87                 return -1;
88         }
89
90         opts->test = (enum cperf_perf_test_type)id;
91
92         return 0;
93 }
94
95 static int
96 parse_uint32_t(uint32_t *value, const char *arg)
97 {
98         char *end = NULL;
99         unsigned long n = strtoul(arg, &end, 10);
100
101         if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0'))
102                 return -1;
103
104         if (n > UINT32_MAX)
105                 return -ERANGE;
106
107         *value = (uint32_t) n;
108
109         return 0;
110 }
111
112 static int
113 parse_uint16_t(uint16_t *value, const char *arg)
114 {
115         uint32_t val = 0;
116         int ret = parse_uint32_t(&val, arg);
117
118         if (ret < 0)
119                 return ret;
120
121         if (val > UINT16_MAX)
122                 return -ERANGE;
123
124         *value = (uint16_t) val;
125
126         return 0;
127 }
128
129 static int
130 parse_range(const char *arg, uint32_t *min, uint32_t *max, uint32_t *inc)
131 {
132         char *token;
133         uint32_t number;
134
135         char *copy_arg = strdup(arg);
136
137         if (copy_arg == NULL)
138                 return -1;
139
140         errno = 0;
141         token = strtok(copy_arg, ":");
142
143         /* Parse minimum value */
144         if (token != NULL) {
145                 number = strtoul(token, NULL, 10);
146
147                 if (errno == EINVAL || errno == ERANGE ||
148                                 number == 0)
149                         goto err_range;
150
151                 *min = number;
152         } else
153                 goto err_range;
154
155         token = strtok(NULL, ":");
156
157         /* Parse increment value */
158         if (token != NULL) {
159                 number = strtoul(token, NULL, 10);
160
161                 if (errno == EINVAL || errno == ERANGE ||
162                                 number == 0)
163                         goto err_range;
164
165                 *inc = number;
166         } else
167                 goto err_range;
168
169         token = strtok(NULL, ":");
170
171         /* Parse maximum value */
172         if (token != NULL) {
173                 number = strtoul(token, NULL, 10);
174
175                 if (errno == EINVAL || errno == ERANGE ||
176                                 number == 0 ||
177                                 number < *min)
178                         goto err_range;
179
180                 *max = number;
181         } else
182                 goto err_range;
183
184         if (strtok(NULL, ":") != NULL)
185                 goto err_range;
186
187         free(copy_arg);
188         return 0;
189
190 err_range:
191         free(copy_arg);
192         return -1;
193 }
194
195 static int
196 parse_list(const char *arg, uint32_t *list, uint32_t *min, uint32_t *max)
197 {
198         char *token;
199         uint32_t number;
200         uint8_t count = 0;
201
202         char *copy_arg = strdup(arg);
203
204         if (copy_arg == NULL)
205                 return -1;
206
207         errno = 0;
208         token = strtok(copy_arg, ",");
209
210         /* Parse first value */
211         if (token != NULL) {
212                 number = strtoul(token, NULL, 10);
213
214                 if (errno == EINVAL || errno == ERANGE ||
215                                 number == 0)
216                         goto err_list;
217
218                 list[count++] = number;
219                 *min = number;
220                 *max = number;
221         } else
222                 goto err_list;
223
224         token = strtok(NULL, ",");
225
226         while (token != NULL) {
227                 if (count == MAX_LIST) {
228                         RTE_LOG(WARNING, USER1, "Using only the first %u sizes\n",
229                                         MAX_LIST);
230                         break;
231                 }
232
233                 number = strtoul(token, NULL, 10);
234
235                 if (errno == EINVAL || errno == ERANGE ||
236                                 number == 0)
237                         goto err_list;
238
239                 list[count++] = number;
240
241                 if (number < *min)
242                         *min = number;
243                 if (number > *max)
244                         *max = number;
245
246                 token = strtok(NULL, ",");
247         }
248
249         free(copy_arg);
250         return count;
251
252 err_list:
253         free(copy_arg);
254         return -1;
255 }
256
257 static int
258 parse_total_ops(struct cperf_options *opts, const char *arg)
259 {
260         int ret = parse_uint32_t(&opts->total_ops, arg);
261
262         if (ret)
263                 RTE_LOG(ERR, USER1, "failed to parse total operations count\n");
264
265         if (opts->total_ops == 0) {
266                 RTE_LOG(ERR, USER1,
267                                 "invalid total operations count number specified\n");
268                 return -1;
269         }
270
271         return ret;
272 }
273
274 static int
275 parse_pool_sz(struct cperf_options *opts, const char *arg)
276 {
277         int ret =  parse_uint32_t(&opts->pool_sz, arg);
278
279         if (ret)
280                 RTE_LOG(ERR, USER1, "failed to parse pool size");
281         return ret;
282 }
283
284 static int
285 parse_burst_sz(struct cperf_options *opts, const char *arg)
286 {
287         int ret;
288
289         /* Try parsing the argument as a range, if it fails, parse it as a list */
290         if (parse_range(arg, &opts->min_burst_size, &opts->max_burst_size,
291                         &opts->inc_burst_size) < 0) {
292                 ret = parse_list(arg, opts->burst_size_list,
293                                         &opts->min_burst_size,
294                                         &opts->max_burst_size);
295                 if (ret < 0) {
296                         RTE_LOG(ERR, USER1, "failed to parse burst size/s\n");
297                         return -1;
298                 }
299                 opts->burst_size_count = ret;
300         }
301
302         return 0;
303 }
304
305 static int
306 parse_buffer_sz(struct cperf_options *opts, const char *arg)
307 {
308         int ret;
309
310         /* Try parsing the argument as a range, if it fails, parse it as a list */
311         if (parse_range(arg, &opts->min_buffer_size, &opts->max_buffer_size,
312                         &opts->inc_buffer_size) < 0) {
313                 ret = parse_list(arg, opts->buffer_size_list,
314                                         &opts->min_buffer_size,
315                                         &opts->max_buffer_size);
316                 if (ret < 0) {
317                         RTE_LOG(ERR, USER1, "failed to parse buffer size/s\n");
318                         return -1;
319                 }
320                 opts->buffer_size_count = ret;
321         }
322
323         return 0;
324 }
325
326 static int
327 parse_segments_nb(struct cperf_options *opts, const char *arg)
328 {
329         int ret = parse_uint32_t(&opts->segments_nb, arg);
330
331         if (ret) {
332                 RTE_LOG(ERR, USER1, "failed to parse segments number\n");
333                 return -1;
334         }
335
336         if ((opts->segments_nb == 0) || (opts->segments_nb > 255)) {
337                 RTE_LOG(ERR, USER1, "invalid segments number specified\n");
338                 return -1;
339         }
340
341         return 0;
342 }
343
344 static int
345 parse_device_type(struct cperf_options *opts, const char *arg)
346 {
347         if (strlen(arg) > (sizeof(opts->device_type) - 1))
348                 return -1;
349
350         strncpy(opts->device_type, arg, sizeof(opts->device_type) - 1);
351         *(opts->device_type + sizeof(opts->device_type) - 1) = '\0';
352
353         return 0;
354 }
355
356 static int
357 parse_op_type(struct cperf_options *opts, const char *arg)
358 {
359         struct name_id_map optype_namemap[] = {
360                 {
361                         cperf_op_type_strs[CPERF_CIPHER_ONLY],
362                         CPERF_CIPHER_ONLY
363                 },
364                 {
365                         cperf_op_type_strs[CPERF_AUTH_ONLY],
366                         CPERF_AUTH_ONLY
367                 },
368                 {
369                         cperf_op_type_strs[CPERF_CIPHER_THEN_AUTH],
370                         CPERF_CIPHER_THEN_AUTH
371                 },
372                 {
373                         cperf_op_type_strs[CPERF_AUTH_THEN_CIPHER],
374                         CPERF_AUTH_THEN_CIPHER
375                 },
376                 {
377                         cperf_op_type_strs[CPERF_AEAD],
378                         CPERF_AEAD
379                 }
380         };
381
382         int id = get_str_key_id_mapping(optype_namemap,
383                         RTE_DIM(optype_namemap), arg);
384         if (id < 0) {
385                 RTE_LOG(ERR, USER1, "invalid opt type specified\n");
386                 return -1;
387         }
388
389         opts->op_type = (enum cperf_op_type)id;
390
391         return 0;
392 }
393
394 static int
395 parse_sessionless(struct cperf_options *opts,
396                 const char *arg __rte_unused)
397 {
398         opts->sessionless = 1;
399         return 0;
400 }
401
402 static int
403 parse_out_of_place(struct cperf_options *opts,
404                 const char *arg __rte_unused)
405 {
406         opts->out_of_place = 1;
407         return 0;
408 }
409
410 static int
411 parse_test_file(struct cperf_options *opts,
412                 const char *arg)
413 {
414         opts->test_file = strdup(arg);
415         if (access(opts->test_file, F_OK) != -1)
416                 return 0;
417         RTE_LOG(ERR, USER1, "Test vector file doesn't exist\n");
418
419         return -1;
420 }
421
422 static int
423 parse_test_name(struct cperf_options *opts,
424                 const char *arg)
425 {
426         char *test_name = (char *) rte_zmalloc(NULL,
427                 sizeof(char) * (strlen(arg) + 3), 0);
428         snprintf(test_name, strlen(arg) + 3, "[%s]", arg);
429         opts->test_name = test_name;
430
431         return 0;
432 }
433
434 static int
435 parse_silent(struct cperf_options *opts,
436                 const char *arg __rte_unused)
437 {
438         opts->silent = 1;
439
440         return 0;
441 }
442
443 static int
444 parse_cipher_algo(struct cperf_options *opts, const char *arg)
445 {
446
447         enum rte_crypto_cipher_algorithm cipher_algo;
448
449         if (rte_cryptodev_get_cipher_algo_enum(&cipher_algo, arg) < 0) {
450                 RTE_LOG(ERR, USER1, "Invalid cipher algorithm specified\n");
451                 return -1;
452         }
453
454         opts->cipher_algo = cipher_algo;
455
456         return 0;
457 }
458
459 static int
460 parse_cipher_op(struct cperf_options *opts, const char *arg)
461 {
462         struct name_id_map cipher_op_namemap[] = {
463                 {
464                         rte_crypto_cipher_operation_strings
465                         [RTE_CRYPTO_CIPHER_OP_ENCRYPT],
466                         RTE_CRYPTO_CIPHER_OP_ENCRYPT },
467                 {
468                         rte_crypto_cipher_operation_strings
469                         [RTE_CRYPTO_CIPHER_OP_DECRYPT],
470                         RTE_CRYPTO_CIPHER_OP_DECRYPT
471                 }
472         };
473
474         int id = get_str_key_id_mapping(cipher_op_namemap,
475                         RTE_DIM(cipher_op_namemap), arg);
476         if (id < 0) {
477                 RTE_LOG(ERR, USER1, "Invalid cipher operation specified\n");
478                 return -1;
479         }
480
481         opts->cipher_op = (enum rte_crypto_cipher_operation)id;
482
483         return 0;
484 }
485
486 static int
487 parse_cipher_key_sz(struct cperf_options *opts, const char *arg)
488 {
489         return parse_uint16_t(&opts->cipher_key_sz, arg);
490 }
491
492 static int
493 parse_cipher_iv_sz(struct cperf_options *opts, const char *arg)
494 {
495         return parse_uint16_t(&opts->cipher_iv_sz, arg);
496 }
497
498 static int
499 parse_auth_algo(struct cperf_options *opts, const char *arg)
500 {
501         enum rte_crypto_auth_algorithm auth_algo;
502
503         if (rte_cryptodev_get_auth_algo_enum(&auth_algo, arg) < 0) {
504                 RTE_LOG(ERR, USER1, "Invalid authentication algorithm specified\n");
505                 return -1;
506         }
507
508         opts->auth_algo = auth_algo;
509
510         return 0;
511 }
512
513 static int
514 parse_auth_op(struct cperf_options *opts, const char *arg)
515 {
516         struct name_id_map auth_op_namemap[] = {
517                 {
518                         rte_crypto_auth_operation_strings
519                         [RTE_CRYPTO_AUTH_OP_GENERATE],
520                         RTE_CRYPTO_AUTH_OP_GENERATE },
521                 {
522                         rte_crypto_auth_operation_strings
523                         [RTE_CRYPTO_AUTH_OP_VERIFY],
524                         RTE_CRYPTO_AUTH_OP_VERIFY
525                 }
526         };
527
528         int id = get_str_key_id_mapping(auth_op_namemap,
529                         RTE_DIM(auth_op_namemap), arg);
530         if (id < 0) {
531                 RTE_LOG(ERR, USER1, "invalid authentication operation specified"
532                                 "\n");
533                 return -1;
534         }
535
536         opts->auth_op = (enum rte_crypto_auth_operation)id;
537
538         return 0;
539 }
540
541 static int
542 parse_auth_key_sz(struct cperf_options *opts, const char *arg)
543 {
544         return parse_uint16_t(&opts->auth_key_sz, arg);
545 }
546
547 static int
548 parse_digest_sz(struct cperf_options *opts, const char *arg)
549 {
550         return parse_uint16_t(&opts->digest_sz, arg);
551 }
552
553 static int
554 parse_auth_iv_sz(struct cperf_options *opts, const char *arg)
555 {
556         return parse_uint16_t(&opts->auth_iv_sz, arg);
557 }
558
559 static int
560 parse_aead_algo(struct cperf_options *opts, const char *arg)
561 {
562         enum rte_crypto_aead_algorithm aead_algo;
563
564         if (rte_cryptodev_get_aead_algo_enum(&aead_algo, arg) < 0) {
565                 RTE_LOG(ERR, USER1, "Invalid AEAD algorithm specified\n");
566                 return -1;
567         }
568
569         opts->aead_algo = aead_algo;
570
571         return 0;
572 }
573
574 static int
575 parse_aead_op(struct cperf_options *opts, const char *arg)
576 {
577         struct name_id_map aead_op_namemap[] = {
578                 {
579                         rte_crypto_aead_operation_strings
580                         [RTE_CRYPTO_AEAD_OP_ENCRYPT],
581                         RTE_CRYPTO_AEAD_OP_ENCRYPT },
582                 {
583                         rte_crypto_aead_operation_strings
584                         [RTE_CRYPTO_AEAD_OP_DECRYPT],
585                         RTE_CRYPTO_AEAD_OP_DECRYPT
586                 }
587         };
588
589         int id = get_str_key_id_mapping(aead_op_namemap,
590                         RTE_DIM(aead_op_namemap), arg);
591         if (id < 0) {
592                 RTE_LOG(ERR, USER1, "invalid AEAD operation specified"
593                                 "\n");
594                 return -1;
595         }
596
597         opts->aead_op = (enum rte_crypto_aead_operation)id;
598
599         return 0;
600 }
601
602 static int
603 parse_aead_key_sz(struct cperf_options *opts, const char *arg)
604 {
605         return parse_uint16_t(&opts->aead_key_sz, arg);
606 }
607
608 static int
609 parse_aead_iv_sz(struct cperf_options *opts, const char *arg)
610 {
611         return parse_uint16_t(&opts->aead_iv_sz, arg);
612 }
613
614 static int
615 parse_aead_aad_sz(struct cperf_options *opts, const char *arg)
616 {
617         return parse_uint16_t(&opts->aead_aad_sz, arg);
618 }
619
620 static int
621 parse_csv_friendly(struct cperf_options *opts, const char *arg __rte_unused)
622 {
623         opts->csv = 1;
624         opts->silent = 1;
625         return 0;
626 }
627
628 typedef int (*option_parser_t)(struct cperf_options *opts,
629                 const char *arg);
630
631 struct long_opt_parser {
632         const char *lgopt_name;
633         option_parser_t parser_fn;
634
635 };
636
637 static struct option lgopts[] = {
638
639         { CPERF_PTEST_TYPE, required_argument, 0, 0 },
640
641         { CPERF_POOL_SIZE, required_argument, 0, 0 },
642         { CPERF_TOTAL_OPS, required_argument, 0, 0 },
643         { CPERF_BURST_SIZE, required_argument, 0, 0 },
644         { CPERF_BUFFER_SIZE, required_argument, 0, 0 },
645         { CPERF_SEGMENTS_NB, required_argument, 0, 0 },
646
647         { CPERF_DEVTYPE, required_argument, 0, 0 },
648         { CPERF_OPTYPE, required_argument, 0, 0 },
649
650         { CPERF_SILENT, no_argument, 0, 0 },
651         { CPERF_SESSIONLESS, no_argument, 0, 0 },
652         { CPERF_OUT_OF_PLACE, no_argument, 0, 0 },
653         { CPERF_TEST_FILE, required_argument, 0, 0 },
654         { CPERF_TEST_NAME, required_argument, 0, 0 },
655
656         { CPERF_CIPHER_ALGO, required_argument, 0, 0 },
657         { CPERF_CIPHER_OP, required_argument, 0, 0 },
658
659         { CPERF_CIPHER_KEY_SZ, required_argument, 0, 0 },
660         { CPERF_CIPHER_IV_SZ, required_argument, 0, 0 },
661
662         { CPERF_AUTH_ALGO, required_argument, 0, 0 },
663         { CPERF_AUTH_OP, required_argument, 0, 0 },
664
665         { CPERF_AUTH_KEY_SZ, required_argument, 0, 0 },
666         { CPERF_AUTH_IV_SZ, required_argument, 0, 0 },
667
668         { CPERF_AEAD_ALGO, required_argument, 0, 0 },
669         { CPERF_AEAD_OP, required_argument, 0, 0 },
670
671         { CPERF_AEAD_KEY_SZ, required_argument, 0, 0 },
672         { CPERF_AEAD_AAD_SZ, required_argument, 0, 0 },
673         { CPERF_AEAD_IV_SZ, required_argument, 0, 0 },
674
675         { CPERF_DIGEST_SZ, required_argument, 0, 0 },
676
677         { CPERF_CSV, no_argument, 0, 0},
678
679         { NULL, 0, 0, 0 }
680 };
681
682 void
683 cperf_options_default(struct cperf_options *opts)
684 {
685         opts->test = CPERF_TEST_TYPE_THROUGHPUT;
686
687         opts->pool_sz = 8192;
688         opts->total_ops = 10000000;
689
690         opts->buffer_size_list[0] = 64;
691         opts->buffer_size_count = 1;
692         opts->max_buffer_size = 64;
693         opts->min_buffer_size = 64;
694         opts->inc_buffer_size = 0;
695
696         opts->burst_size_list[0] = 32;
697         opts->burst_size_count = 1;
698         opts->max_burst_size = 32;
699         opts->min_burst_size = 32;
700         opts->inc_burst_size = 0;
701
702         opts->segments_nb = 1;
703
704         strncpy(opts->device_type, "crypto_aesni_mb",
705                         sizeof(opts->device_type));
706
707         opts->op_type = CPERF_CIPHER_THEN_AUTH;
708
709         opts->silent = 0;
710         opts->test_file = NULL;
711         opts->test_name = NULL;
712         opts->sessionless = 0;
713         opts->out_of_place = 0;
714         opts->csv = 0;
715
716         opts->cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC;
717         opts->cipher_op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
718         opts->cipher_key_sz = 16;
719         opts->cipher_iv_sz = 16;
720
721         opts->auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
722         opts->auth_op = RTE_CRYPTO_AUTH_OP_GENERATE;
723
724         opts->auth_key_sz = 64;
725         opts->auth_iv_sz = 0;
726
727         opts->aead_key_sz = 0;
728         opts->aead_iv_sz = 0;
729         opts->aead_aad_sz = 0;
730
731         opts->digest_sz = 12;
732 }
733
734 static int
735 cperf_opts_parse_long(int opt_idx, struct cperf_options *opts)
736 {
737         struct long_opt_parser parsermap[] = {
738                 { CPERF_PTEST_TYPE,     parse_cperf_test_type },
739                 { CPERF_SILENT,         parse_silent },
740                 { CPERF_POOL_SIZE,      parse_pool_sz },
741                 { CPERF_TOTAL_OPS,      parse_total_ops },
742                 { CPERF_BURST_SIZE,     parse_burst_sz },
743                 { CPERF_BUFFER_SIZE,    parse_buffer_sz },
744                 { CPERF_SEGMENTS_NB,    parse_segments_nb },
745                 { CPERF_DEVTYPE,        parse_device_type },
746                 { CPERF_OPTYPE,         parse_op_type },
747                 { CPERF_SESSIONLESS,    parse_sessionless },
748                 { CPERF_OUT_OF_PLACE,   parse_out_of_place },
749                 { CPERF_TEST_FILE,      parse_test_file },
750                 { CPERF_TEST_NAME,      parse_test_name },
751                 { CPERF_CIPHER_ALGO,    parse_cipher_algo },
752                 { CPERF_CIPHER_OP,      parse_cipher_op },
753                 { CPERF_CIPHER_KEY_SZ,  parse_cipher_key_sz },
754                 { CPERF_CIPHER_IV_SZ,   parse_cipher_iv_sz },
755                 { CPERF_AUTH_ALGO,      parse_auth_algo },
756                 { CPERF_AUTH_OP,        parse_auth_op },
757                 { CPERF_AUTH_KEY_SZ,    parse_auth_key_sz },
758                 { CPERF_AUTH_IV_SZ,     parse_auth_iv_sz },
759                 { CPERF_AEAD_ALGO,      parse_aead_algo },
760                 { CPERF_AEAD_OP,        parse_aead_op },
761                 { CPERF_AEAD_KEY_SZ,    parse_aead_key_sz },
762                 { CPERF_AEAD_IV_SZ,     parse_aead_iv_sz },
763                 { CPERF_AEAD_AAD_SZ,    parse_aead_aad_sz },
764                 { CPERF_DIGEST_SZ,      parse_digest_sz },
765                 { CPERF_CSV,            parse_csv_friendly},
766         };
767         unsigned int i;
768
769         for (i = 0; i < RTE_DIM(parsermap); i++) {
770                 if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name,
771                                 strlen(lgopts[opt_idx].name)) == 0)
772                         return parsermap[i].parser_fn(opts, optarg);
773         }
774
775         return -EINVAL;
776 }
777
778 int
779 cperf_options_parse(struct cperf_options *options, int argc, char **argv)
780 {
781         int opt, retval, opt_idx;
782
783         while ((opt = getopt_long(argc, argv, "", lgopts, &opt_idx)) != EOF) {
784                 switch (opt) {
785                 /* long options */
786                 case 0:
787
788                         retval = cperf_opts_parse_long(opt_idx, options);
789                         if (retval != 0)
790                                 return retval;
791
792                         break;
793
794                 default:
795                         return -EINVAL;
796                 }
797         }
798
799         return 0;
800 }
801
802 static int
803 check_cipher_buffer_length(struct cperf_options *options)
804 {
805         uint32_t buffer_size, buffer_size_idx = 0;
806
807         if (options->cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC ||
808                         options->cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB) {
809                 if (options->inc_buffer_size != 0)
810                         buffer_size = options->min_buffer_size;
811                 else
812                         buffer_size = options->buffer_size_list[0];
813
814                 while (buffer_size <= options->max_buffer_size) {
815                         if ((buffer_size % AES_BLOCK_SIZE) != 0) {
816                                 RTE_LOG(ERR, USER1, "Some of the buffer sizes are "
817                                         "not suitable for the algorithm selected\n");
818                                 return -EINVAL;
819                         }
820
821                         if (options->inc_buffer_size != 0)
822                                 buffer_size += options->inc_buffer_size;
823                         else {
824                                 if (++buffer_size_idx == options->buffer_size_count)
825                                         break;
826                                 buffer_size = options->buffer_size_list[buffer_size_idx];
827                         }
828
829                 }
830         }
831
832         if (options->cipher_algo == RTE_CRYPTO_CIPHER_DES_CBC ||
833                         options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_CBC ||
834                         options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_ECB) {
835                 for (buffer_size = options->min_buffer_size;
836                                 buffer_size < options->max_buffer_size;
837                                 buffer_size += options->inc_buffer_size) {
838                         if ((buffer_size % DES_BLOCK_SIZE) != 0) {
839                                 RTE_LOG(ERR, USER1, "Some of the buffer sizes are "
840                                         "not suitable for the algorithm selected\n");
841                                 return -EINVAL;
842                         }
843                 }
844         }
845
846         return 0;
847 }
848
849 int
850 cperf_options_check(struct cperf_options *options)
851 {
852         if (options->segments_nb > options->min_buffer_size) {
853                 RTE_LOG(ERR, USER1,
854                                 "Segments number greater than buffer size.\n");
855                 return -EINVAL;
856         }
857
858         if (options->test == CPERF_TEST_TYPE_VERIFY &&
859                         options->test_file == NULL) {
860                 RTE_LOG(ERR, USER1, "Define path to the file with test"
861                                 " vectors.\n");
862                 return -EINVAL;
863         }
864
865         if (options->test == CPERF_TEST_TYPE_VERIFY &&
866                         options->op_type != CPERF_CIPHER_ONLY &&
867                         options->test_name == NULL) {
868                 RTE_LOG(ERR, USER1, "Define test name to get the correct digest"
869                                 " from the test vectors.\n");
870                 return -EINVAL;
871         }
872
873         if (options->test_name != NULL && options->test_file == NULL) {
874                 RTE_LOG(ERR, USER1, "Define path to the file with test"
875                                 " vectors.\n");
876                 return -EINVAL;
877         }
878
879         if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY &&
880                         options->test_file == NULL) {
881                 RTE_LOG(ERR, USER1, "Define path to the file with test"
882                                 " vectors.\n");
883                 return -EINVAL;
884         }
885
886         if (options->test == CPERF_TEST_TYPE_VERIFY &&
887                         options->total_ops > options->pool_sz) {
888                 RTE_LOG(ERR, USER1, "Total number of ops must be less than or"
889                                 " equal to the pool size.\n");
890                 return -EINVAL;
891         }
892
893         if (options->test == CPERF_TEST_TYPE_VERIFY &&
894                         (options->inc_buffer_size != 0 ||
895                         options->buffer_size_count > 1)) {
896                 RTE_LOG(ERR, USER1, "Only one buffer size is allowed when "
897                                 "using the verify test.\n");
898                 return -EINVAL;
899         }
900
901         if (options->test == CPERF_TEST_TYPE_VERIFY &&
902                         (options->inc_burst_size != 0 ||
903                         options->burst_size_count > 1)) {
904                 RTE_LOG(ERR, USER1, "Only one burst size is allowed when "
905                                 "using the verify test.\n");
906                 return -EINVAL;
907         }
908
909         if (options->op_type == CPERF_CIPHER_THEN_AUTH) {
910                 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
911                                 options->auth_op !=
912                                 RTE_CRYPTO_AUTH_OP_GENERATE) {
913                         RTE_LOG(ERR, USER1, "Option cipher then auth must use"
914                                         " options: encrypt and generate.\n");
915                         return -EINVAL;
916                 }
917         } else if (options->op_type == CPERF_AUTH_THEN_CIPHER) {
918                 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_DECRYPT &&
919                                 options->auth_op !=
920                                 RTE_CRYPTO_AUTH_OP_VERIFY) {
921                         RTE_LOG(ERR, USER1, "Option auth then cipher must use"
922                                         " options: decrypt and verify.\n");
923                         return -EINVAL;
924                 }
925         }
926
927         if (options->op_type == CPERF_CIPHER_ONLY ||
928                         options->op_type == CPERF_CIPHER_THEN_AUTH ||
929                         options->op_type == CPERF_AUTH_THEN_CIPHER) {
930                 if (check_cipher_buffer_length(options) < 0)
931                         return -EINVAL;
932         }
933
934         return 0;
935 }
936
937 void
938 cperf_options_dump(struct cperf_options *opts)
939 {
940         uint8_t size_idx;
941
942         printf("# Crypto Performance Application Options:\n");
943         printf("#\n");
944         printf("# cperf test: %s\n", cperf_test_type_strs[opts->test]);
945         printf("#\n");
946         printf("# size of crypto op / mbuf pool: %u\n", opts->pool_sz);
947         printf("# total number of ops: %u\n", opts->total_ops);
948         if (opts->inc_buffer_size != 0) {
949                 printf("# buffer size:\n");
950                 printf("#\t min: %u\n", opts->min_buffer_size);
951                 printf("#\t max: %u\n", opts->max_buffer_size);
952                 printf("#\t inc: %u\n", opts->inc_buffer_size);
953         } else {
954                 printf("# buffer sizes: ");
955                 for (size_idx = 0; size_idx < opts->buffer_size_count; size_idx++)
956                         printf("%u ", opts->buffer_size_list[size_idx]);
957                 printf("\n");
958         }
959         if (opts->inc_burst_size != 0) {
960                 printf("# burst size:\n");
961                 printf("#\t min: %u\n", opts->min_burst_size);
962                 printf("#\t max: %u\n", opts->max_burst_size);
963                 printf("#\t inc: %u\n", opts->inc_burst_size);
964         } else {
965                 printf("# burst sizes: ");
966                 for (size_idx = 0; size_idx < opts->burst_size_count; size_idx++)
967                         printf("%u ", opts->burst_size_list[size_idx]);
968                 printf("\n");
969         }
970         printf("\n# segments per buffer: %u\n", opts->segments_nb);
971         printf("#\n");
972         printf("# cryptodev type: %s\n", opts->device_type);
973         printf("#\n");
974         printf("# crypto operation: %s\n", cperf_op_type_strs[opts->op_type]);
975         printf("# sessionless: %s\n", opts->sessionless ? "yes" : "no");
976         printf("# out of place: %s\n", opts->out_of_place ? "yes" : "no");
977
978         printf("#\n");
979
980         if (opts->op_type == CPERF_AUTH_ONLY ||
981                         opts->op_type == CPERF_CIPHER_THEN_AUTH ||
982                         opts->op_type == CPERF_AUTH_THEN_CIPHER) {
983                 printf("# auth algorithm: %s\n",
984                         rte_crypto_auth_algorithm_strings[opts->auth_algo]);
985                 printf("# auth operation: %s\n",
986                         rte_crypto_auth_operation_strings[opts->auth_op]);
987                 printf("# auth key size: %u\n", opts->auth_key_sz);
988                 printf("# auth iv size: %u\n", opts->auth_iv_sz);
989                 printf("# auth digest size: %u\n", opts->digest_sz);
990                 printf("#\n");
991         }
992
993         if (opts->op_type == CPERF_CIPHER_ONLY ||
994                         opts->op_type == CPERF_CIPHER_THEN_AUTH ||
995                         opts->op_type == CPERF_AUTH_THEN_CIPHER) {
996                 printf("# cipher algorithm: %s\n",
997                         rte_crypto_cipher_algorithm_strings[opts->cipher_algo]);
998                 printf("# cipher operation: %s\n",
999                         rte_crypto_cipher_operation_strings[opts->cipher_op]);
1000                 printf("# cipher key size: %u\n", opts->cipher_key_sz);
1001                 printf("# cipher iv size: %u\n", opts->cipher_iv_sz);
1002                 printf("#\n");
1003         }
1004
1005         if (opts->op_type == CPERF_AEAD) {
1006                 printf("# aead algorithm: %s\n",
1007                         rte_crypto_aead_algorithm_strings[opts->aead_algo]);
1008                 printf("# aead operation: %s\n",
1009                         rte_crypto_aead_operation_strings[opts->aead_op]);
1010                 printf("# aead key size: %u\n", opts->aead_key_sz);
1011                 printf("# aead iv size: %u\n", opts->aead_iv_sz);
1012                 printf("# aead digest size: %u\n", opts->digest_sz);
1013                 printf("# aead aad size: %u\n", opts->aead_aad_sz);
1014                 printf("#\n");
1015         }
1016 }