app/crypto-perf: support multiple queue pairs
[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                         cperf_test_type_strs[CPERF_TEST_TYPE_PMDCC],
82                         CPERF_TEST_TYPE_PMDCC
83                 }
84         };
85
86         int id = get_str_key_id_mapping(
87                         (struct name_id_map *)cperftest_namemap,
88                         RTE_DIM(cperftest_namemap), arg);
89         if (id < 0) {
90                 RTE_LOG(ERR, USER1, "failed to parse test type");
91                 return -1;
92         }
93
94         opts->test = (enum cperf_perf_test_type)id;
95
96         return 0;
97 }
98
99 static int
100 parse_uint32_t(uint32_t *value, const char *arg)
101 {
102         char *end = NULL;
103         unsigned long n = strtoul(arg, &end, 10);
104
105         if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0'))
106                 return -1;
107
108         if (n > UINT32_MAX)
109                 return -ERANGE;
110
111         *value = (uint32_t) n;
112
113         return 0;
114 }
115
116 static int
117 parse_uint16_t(uint16_t *value, const char *arg)
118 {
119         uint32_t val = 0;
120         int ret = parse_uint32_t(&val, arg);
121
122         if (ret < 0)
123                 return ret;
124
125         if (val > UINT16_MAX)
126                 return -ERANGE;
127
128         *value = (uint16_t) val;
129
130         return 0;
131 }
132
133 static int
134 parse_range(const char *arg, uint32_t *min, uint32_t *max, uint32_t *inc)
135 {
136         char *token;
137         uint32_t number;
138
139         char *copy_arg = strdup(arg);
140
141         if (copy_arg == NULL)
142                 return -1;
143
144         errno = 0;
145         token = strtok(copy_arg, ":");
146
147         /* Parse minimum value */
148         if (token != NULL) {
149                 number = strtoul(token, NULL, 10);
150
151                 if (errno == EINVAL || errno == ERANGE ||
152                                 number == 0)
153                         goto err_range;
154
155                 *min = number;
156         } else
157                 goto err_range;
158
159         token = strtok(NULL, ":");
160
161         /* Parse increment 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                 *inc = number;
170         } else
171                 goto err_range;
172
173         token = strtok(NULL, ":");
174
175         /* Parse maximum value */
176         if (token != NULL) {
177                 number = strtoul(token, NULL, 10);
178
179                 if (errno == EINVAL || errno == ERANGE ||
180                                 number == 0 ||
181                                 number < *min)
182                         goto err_range;
183
184                 *max = number;
185         } else
186                 goto err_range;
187
188         if (strtok(NULL, ":") != NULL)
189                 goto err_range;
190
191         free(copy_arg);
192         return 0;
193
194 err_range:
195         free(copy_arg);
196         return -1;
197 }
198
199 static int
200 parse_list(const char *arg, uint32_t *list, uint32_t *min, uint32_t *max)
201 {
202         char *token;
203         uint32_t number;
204         uint8_t count = 0;
205
206         char *copy_arg = strdup(arg);
207
208         if (copy_arg == NULL)
209                 return -1;
210
211         errno = 0;
212         token = strtok(copy_arg, ",");
213
214         /* Parse first value */
215         if (token != NULL) {
216                 number = strtoul(token, NULL, 10);
217
218                 if (errno == EINVAL || errno == ERANGE ||
219                                 number == 0)
220                         goto err_list;
221
222                 list[count++] = number;
223                 *min = number;
224                 *max = number;
225         } else
226                 goto err_list;
227
228         token = strtok(NULL, ",");
229
230         while (token != NULL) {
231                 if (count == MAX_LIST) {
232                         RTE_LOG(WARNING, USER1, "Using only the first %u sizes\n",
233                                         MAX_LIST);
234                         break;
235                 }
236
237                 number = strtoul(token, NULL, 10);
238
239                 if (errno == EINVAL || errno == ERANGE ||
240                                 number == 0)
241                         goto err_list;
242
243                 list[count++] = number;
244
245                 if (number < *min)
246                         *min = number;
247                 if (number > *max)
248                         *max = number;
249
250                 token = strtok(NULL, ",");
251         }
252
253         free(copy_arg);
254         return count;
255
256 err_list:
257         free(copy_arg);
258         return -1;
259 }
260
261 static int
262 parse_total_ops(struct cperf_options *opts, const char *arg)
263 {
264         int ret = parse_uint32_t(&opts->total_ops, arg);
265
266         if (ret)
267                 RTE_LOG(ERR, USER1, "failed to parse total operations count\n");
268
269         if (opts->total_ops == 0) {
270                 RTE_LOG(ERR, USER1,
271                                 "invalid total operations count number specified\n");
272                 return -1;
273         }
274
275         return ret;
276 }
277
278 static int
279 parse_pool_sz(struct cperf_options *opts, const char *arg)
280 {
281         int ret =  parse_uint32_t(&opts->pool_sz, arg);
282
283         if (ret)
284                 RTE_LOG(ERR, USER1, "failed to parse pool size");
285         return ret;
286 }
287
288 static int
289 parse_burst_sz(struct cperf_options *opts, const char *arg)
290 {
291         int ret;
292
293         /* Try parsing the argument as a range, if it fails, parse it as a list */
294         if (parse_range(arg, &opts->min_burst_size, &opts->max_burst_size,
295                         &opts->inc_burst_size) < 0) {
296                 ret = parse_list(arg, opts->burst_size_list,
297                                         &opts->min_burst_size,
298                                         &opts->max_burst_size);
299                 if (ret < 0) {
300                         RTE_LOG(ERR, USER1, "failed to parse burst size/s\n");
301                         return -1;
302                 }
303                 opts->burst_size_count = ret;
304         }
305
306         return 0;
307 }
308
309 static int
310 parse_buffer_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_buffer_size, &opts->max_buffer_size,
316                         &opts->inc_buffer_size) < 0) {
317                 ret = parse_list(arg, opts->buffer_size_list,
318                                         &opts->min_buffer_size,
319                                         &opts->max_buffer_size);
320                 if (ret < 0) {
321                         RTE_LOG(ERR, USER1, "failed to parse buffer size/s\n");
322                         return -1;
323                 }
324                 opts->buffer_size_count = ret;
325         }
326
327         return 0;
328 }
329
330 static int
331 parse_segment_sz(struct cperf_options *opts, const char *arg)
332 {
333         int ret = parse_uint32_t(&opts->segment_sz, arg);
334
335         if (ret) {
336                 RTE_LOG(ERR, USER1, "failed to parse segment size\n");
337                 return -1;
338         }
339
340         if (opts->segment_sz == 0) {
341                 RTE_LOG(ERR, USER1, "Segment size has to be bigger than 0\n");
342                 return -1;
343         }
344
345         return 0;
346 }
347
348 static int
349 parse_desc_nb(struct cperf_options *opts, const char *arg)
350 {
351         int ret = parse_uint32_t(&opts->nb_descriptors, arg);
352
353         if (ret) {
354                 RTE_LOG(ERR, USER1, "failed to parse descriptors number\n");
355                 return -1;
356         }
357
358         if (opts->nb_descriptors == 0) {
359                 RTE_LOG(ERR, USER1, "invalid descriptors number specified\n");
360                 return -1;
361         }
362
363         return 0;
364 }
365
366 static int
367 parse_device_type(struct cperf_options *opts, const char *arg)
368 {
369         if (strlen(arg) > (sizeof(opts->device_type) - 1))
370                 return -1;
371
372         strncpy(opts->device_type, arg, sizeof(opts->device_type) - 1);
373         *(opts->device_type + sizeof(opts->device_type) - 1) = '\0';
374
375         return 0;
376 }
377
378 static int
379 parse_op_type(struct cperf_options *opts, const char *arg)
380 {
381         struct name_id_map optype_namemap[] = {
382                 {
383                         cperf_op_type_strs[CPERF_CIPHER_ONLY],
384                         CPERF_CIPHER_ONLY
385                 },
386                 {
387                         cperf_op_type_strs[CPERF_AUTH_ONLY],
388                         CPERF_AUTH_ONLY
389                 },
390                 {
391                         cperf_op_type_strs[CPERF_CIPHER_THEN_AUTH],
392                         CPERF_CIPHER_THEN_AUTH
393                 },
394                 {
395                         cperf_op_type_strs[CPERF_AUTH_THEN_CIPHER],
396                         CPERF_AUTH_THEN_CIPHER
397                 },
398                 {
399                         cperf_op_type_strs[CPERF_AEAD],
400                         CPERF_AEAD
401                 }
402         };
403
404         int id = get_str_key_id_mapping(optype_namemap,
405                         RTE_DIM(optype_namemap), arg);
406         if (id < 0) {
407                 RTE_LOG(ERR, USER1, "invalid opt type specified\n");
408                 return -1;
409         }
410
411         opts->op_type = (enum cperf_op_type)id;
412
413         return 0;
414 }
415
416 static int
417 parse_sessionless(struct cperf_options *opts,
418                 const char *arg __rte_unused)
419 {
420         opts->sessionless = 1;
421         return 0;
422 }
423
424 static int
425 parse_out_of_place(struct cperf_options *opts,
426                 const char *arg __rte_unused)
427 {
428         opts->out_of_place = 1;
429         return 0;
430 }
431
432 static int
433 parse_test_file(struct cperf_options *opts,
434                 const char *arg)
435 {
436         opts->test_file = strdup(arg);
437         if (access(opts->test_file, F_OK) != -1)
438                 return 0;
439         RTE_LOG(ERR, USER1, "Test vector file doesn't exist\n");
440
441         return -1;
442 }
443
444 static int
445 parse_test_name(struct cperf_options *opts,
446                 const char *arg)
447 {
448         char *test_name = (char *) rte_zmalloc(NULL,
449                 sizeof(char) * (strlen(arg) + 3), 0);
450         snprintf(test_name, strlen(arg) + 3, "[%s]", arg);
451         opts->test_name = test_name;
452
453         return 0;
454 }
455
456 static int
457 parse_silent(struct cperf_options *opts,
458                 const char *arg __rte_unused)
459 {
460         opts->silent = 1;
461
462         return 0;
463 }
464
465 static int
466 parse_cipher_algo(struct cperf_options *opts, const char *arg)
467 {
468
469         enum rte_crypto_cipher_algorithm cipher_algo;
470
471         if (rte_cryptodev_get_cipher_algo_enum(&cipher_algo, arg) < 0) {
472                 RTE_LOG(ERR, USER1, "Invalid cipher algorithm specified\n");
473                 return -1;
474         }
475
476         opts->cipher_algo = cipher_algo;
477
478         return 0;
479 }
480
481 static int
482 parse_cipher_op(struct cperf_options *opts, const char *arg)
483 {
484         struct name_id_map cipher_op_namemap[] = {
485                 {
486                         rte_crypto_cipher_operation_strings
487                         [RTE_CRYPTO_CIPHER_OP_ENCRYPT],
488                         RTE_CRYPTO_CIPHER_OP_ENCRYPT },
489                 {
490                         rte_crypto_cipher_operation_strings
491                         [RTE_CRYPTO_CIPHER_OP_DECRYPT],
492                         RTE_CRYPTO_CIPHER_OP_DECRYPT
493                 }
494         };
495
496         int id = get_str_key_id_mapping(cipher_op_namemap,
497                         RTE_DIM(cipher_op_namemap), arg);
498         if (id < 0) {
499                 RTE_LOG(ERR, USER1, "Invalid cipher operation specified\n");
500                 return -1;
501         }
502
503         opts->cipher_op = (enum rte_crypto_cipher_operation)id;
504
505         return 0;
506 }
507
508 static int
509 parse_cipher_key_sz(struct cperf_options *opts, const char *arg)
510 {
511         return parse_uint16_t(&opts->cipher_key_sz, arg);
512 }
513
514 static int
515 parse_cipher_iv_sz(struct cperf_options *opts, const char *arg)
516 {
517         return parse_uint16_t(&opts->cipher_iv_sz, arg);
518 }
519
520 static int
521 parse_auth_algo(struct cperf_options *opts, const char *arg)
522 {
523         enum rte_crypto_auth_algorithm auth_algo;
524
525         if (rte_cryptodev_get_auth_algo_enum(&auth_algo, arg) < 0) {
526                 RTE_LOG(ERR, USER1, "Invalid authentication algorithm specified\n");
527                 return -1;
528         }
529
530         opts->auth_algo = auth_algo;
531
532         return 0;
533 }
534
535 static int
536 parse_auth_op(struct cperf_options *opts, const char *arg)
537 {
538         struct name_id_map auth_op_namemap[] = {
539                 {
540                         rte_crypto_auth_operation_strings
541                         [RTE_CRYPTO_AUTH_OP_GENERATE],
542                         RTE_CRYPTO_AUTH_OP_GENERATE },
543                 {
544                         rte_crypto_auth_operation_strings
545                         [RTE_CRYPTO_AUTH_OP_VERIFY],
546                         RTE_CRYPTO_AUTH_OP_VERIFY
547                 }
548         };
549
550         int id = get_str_key_id_mapping(auth_op_namemap,
551                         RTE_DIM(auth_op_namemap), arg);
552         if (id < 0) {
553                 RTE_LOG(ERR, USER1, "invalid authentication operation specified"
554                                 "\n");
555                 return -1;
556         }
557
558         opts->auth_op = (enum rte_crypto_auth_operation)id;
559
560         return 0;
561 }
562
563 static int
564 parse_auth_key_sz(struct cperf_options *opts, const char *arg)
565 {
566         return parse_uint16_t(&opts->auth_key_sz, arg);
567 }
568
569 static int
570 parse_digest_sz(struct cperf_options *opts, const char *arg)
571 {
572         return parse_uint16_t(&opts->digest_sz, arg);
573 }
574
575 static int
576 parse_auth_iv_sz(struct cperf_options *opts, const char *arg)
577 {
578         return parse_uint16_t(&opts->auth_iv_sz, arg);
579 }
580
581 static int
582 parse_aead_algo(struct cperf_options *opts, const char *arg)
583 {
584         enum rte_crypto_aead_algorithm aead_algo;
585
586         if (rte_cryptodev_get_aead_algo_enum(&aead_algo, arg) < 0) {
587                 RTE_LOG(ERR, USER1, "Invalid AEAD algorithm specified\n");
588                 return -1;
589         }
590
591         opts->aead_algo = aead_algo;
592
593         return 0;
594 }
595
596 static int
597 parse_aead_op(struct cperf_options *opts, const char *arg)
598 {
599         struct name_id_map aead_op_namemap[] = {
600                 {
601                         rte_crypto_aead_operation_strings
602                         [RTE_CRYPTO_AEAD_OP_ENCRYPT],
603                         RTE_CRYPTO_AEAD_OP_ENCRYPT },
604                 {
605                         rte_crypto_aead_operation_strings
606                         [RTE_CRYPTO_AEAD_OP_DECRYPT],
607                         RTE_CRYPTO_AEAD_OP_DECRYPT
608                 }
609         };
610
611         int id = get_str_key_id_mapping(aead_op_namemap,
612                         RTE_DIM(aead_op_namemap), arg);
613         if (id < 0) {
614                 RTE_LOG(ERR, USER1, "invalid AEAD operation specified"
615                                 "\n");
616                 return -1;
617         }
618
619         opts->aead_op = (enum rte_crypto_aead_operation)id;
620
621         return 0;
622 }
623
624 static int
625 parse_aead_key_sz(struct cperf_options *opts, const char *arg)
626 {
627         return parse_uint16_t(&opts->aead_key_sz, arg);
628 }
629
630 static int
631 parse_aead_iv_sz(struct cperf_options *opts, const char *arg)
632 {
633         return parse_uint16_t(&opts->aead_iv_sz, arg);
634 }
635
636 static int
637 parse_aead_aad_sz(struct cperf_options *opts, const char *arg)
638 {
639         return parse_uint16_t(&opts->aead_aad_sz, arg);
640 }
641
642 static int
643 parse_csv_friendly(struct cperf_options *opts, const char *arg __rte_unused)
644 {
645         opts->csv = 1;
646         opts->silent = 1;
647         return 0;
648 }
649
650 static int
651 parse_pmd_cyclecount_delay_ms(struct cperf_options *opts,
652                         const char *arg)
653 {
654         int ret = parse_uint32_t(&opts->pmdcc_delay, arg);
655
656         if (ret) {
657                 RTE_LOG(ERR, USER1, "failed to parse pmd-cyclecount delay\n");
658                 return -1;
659         }
660
661         return 0;
662 }
663
664 typedef int (*option_parser_t)(struct cperf_options *opts,
665                 const char *arg);
666
667 struct long_opt_parser {
668         const char *lgopt_name;
669         option_parser_t parser_fn;
670
671 };
672
673 static struct option lgopts[] = {
674
675         { CPERF_PTEST_TYPE, required_argument, 0, 0 },
676
677         { CPERF_POOL_SIZE, required_argument, 0, 0 },
678         { CPERF_TOTAL_OPS, required_argument, 0, 0 },
679         { CPERF_BURST_SIZE, required_argument, 0, 0 },
680         { CPERF_BUFFER_SIZE, required_argument, 0, 0 },
681         { CPERF_SEGMENT_SIZE, required_argument, 0, 0 },
682         { CPERF_DESC_NB, required_argument, 0, 0 },
683
684         { CPERF_DEVTYPE, required_argument, 0, 0 },
685         { CPERF_OPTYPE, required_argument, 0, 0 },
686
687         { CPERF_SILENT, no_argument, 0, 0 },
688         { CPERF_SESSIONLESS, no_argument, 0, 0 },
689         { CPERF_OUT_OF_PLACE, no_argument, 0, 0 },
690         { CPERF_TEST_FILE, required_argument, 0, 0 },
691         { CPERF_TEST_NAME, required_argument, 0, 0 },
692
693         { CPERF_CIPHER_ALGO, required_argument, 0, 0 },
694         { CPERF_CIPHER_OP, required_argument, 0, 0 },
695
696         { CPERF_CIPHER_KEY_SZ, required_argument, 0, 0 },
697         { CPERF_CIPHER_IV_SZ, required_argument, 0, 0 },
698
699         { CPERF_AUTH_ALGO, required_argument, 0, 0 },
700         { CPERF_AUTH_OP, required_argument, 0, 0 },
701
702         { CPERF_AUTH_KEY_SZ, required_argument, 0, 0 },
703         { CPERF_AUTH_IV_SZ, required_argument, 0, 0 },
704
705         { CPERF_AEAD_ALGO, required_argument, 0, 0 },
706         { CPERF_AEAD_OP, required_argument, 0, 0 },
707
708         { CPERF_AEAD_KEY_SZ, required_argument, 0, 0 },
709         { CPERF_AEAD_AAD_SZ, required_argument, 0, 0 },
710         { CPERF_AEAD_IV_SZ, required_argument, 0, 0 },
711
712         { CPERF_DIGEST_SZ, required_argument, 0, 0 },
713
714         { CPERF_CSV, no_argument, 0, 0},
715
716         { CPERF_PMDCC_DELAY_MS, required_argument, 0, 0 },
717
718         { NULL, 0, 0, 0 }
719 };
720
721 void
722 cperf_options_default(struct cperf_options *opts)
723 {
724         opts->test = CPERF_TEST_TYPE_THROUGHPUT;
725
726         opts->pool_sz = 8192;
727         opts->total_ops = 10000000;
728         opts->nb_descriptors = 2048;
729
730         opts->buffer_size_list[0] = 64;
731         opts->buffer_size_count = 1;
732         opts->max_buffer_size = 64;
733         opts->min_buffer_size = 64;
734         opts->inc_buffer_size = 0;
735
736         opts->burst_size_list[0] = 32;
737         opts->burst_size_count = 1;
738         opts->max_burst_size = 32;
739         opts->min_burst_size = 32;
740         opts->inc_burst_size = 0;
741
742         /*
743          * Will be parsed from command line or set to
744          * maximum buffer size + digest, later
745          */
746         opts->segment_sz = 0;
747
748         strncpy(opts->device_type, "crypto_aesni_mb",
749                         sizeof(opts->device_type));
750         opts->nb_qps = 1;
751
752         opts->op_type = CPERF_CIPHER_THEN_AUTH;
753
754         opts->silent = 0;
755         opts->test_file = NULL;
756         opts->test_name = NULL;
757         opts->sessionless = 0;
758         opts->out_of_place = 0;
759         opts->csv = 0;
760
761         opts->cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC;
762         opts->cipher_op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
763         opts->cipher_key_sz = 16;
764         opts->cipher_iv_sz = 16;
765
766         opts->auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
767         opts->auth_op = RTE_CRYPTO_AUTH_OP_GENERATE;
768
769         opts->auth_key_sz = 64;
770         opts->auth_iv_sz = 0;
771
772         opts->aead_key_sz = 0;
773         opts->aead_iv_sz = 0;
774         opts->aead_aad_sz = 0;
775
776         opts->digest_sz = 12;
777
778         opts->pmdcc_delay = 0;
779 }
780
781 static int
782 cperf_opts_parse_long(int opt_idx, struct cperf_options *opts)
783 {
784         struct long_opt_parser parsermap[] = {
785                 { CPERF_PTEST_TYPE,     parse_cperf_test_type },
786                 { CPERF_SILENT,         parse_silent },
787                 { CPERF_POOL_SIZE,      parse_pool_sz },
788                 { CPERF_TOTAL_OPS,      parse_total_ops },
789                 { CPERF_BURST_SIZE,     parse_burst_sz },
790                 { CPERF_BUFFER_SIZE,    parse_buffer_sz },
791                 { CPERF_SEGMENT_SIZE,   parse_segment_sz },
792                 { CPERF_DESC_NB,        parse_desc_nb },
793                 { CPERF_DEVTYPE,        parse_device_type },
794                 { CPERF_OPTYPE,         parse_op_type },
795                 { CPERF_SESSIONLESS,    parse_sessionless },
796                 { CPERF_OUT_OF_PLACE,   parse_out_of_place },
797                 { CPERF_TEST_FILE,      parse_test_file },
798                 { CPERF_TEST_NAME,      parse_test_name },
799                 { CPERF_CIPHER_ALGO,    parse_cipher_algo },
800                 { CPERF_CIPHER_OP,      parse_cipher_op },
801                 { CPERF_CIPHER_KEY_SZ,  parse_cipher_key_sz },
802                 { CPERF_CIPHER_IV_SZ,   parse_cipher_iv_sz },
803                 { CPERF_AUTH_ALGO,      parse_auth_algo },
804                 { CPERF_AUTH_OP,        parse_auth_op },
805                 { CPERF_AUTH_KEY_SZ,    parse_auth_key_sz },
806                 { CPERF_AUTH_IV_SZ,     parse_auth_iv_sz },
807                 { CPERF_AEAD_ALGO,      parse_aead_algo },
808                 { CPERF_AEAD_OP,        parse_aead_op },
809                 { CPERF_AEAD_KEY_SZ,    parse_aead_key_sz },
810                 { CPERF_AEAD_IV_SZ,     parse_aead_iv_sz },
811                 { CPERF_AEAD_AAD_SZ,    parse_aead_aad_sz },
812                 { CPERF_DIGEST_SZ,      parse_digest_sz },
813                 { CPERF_CSV,            parse_csv_friendly},
814                 { CPERF_PMDCC_DELAY_MS, parse_pmd_cyclecount_delay_ms},
815         };
816         unsigned int i;
817
818         for (i = 0; i < RTE_DIM(parsermap); i++) {
819                 if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name,
820                                 strlen(lgopts[opt_idx].name)) == 0)
821                         return parsermap[i].parser_fn(opts, optarg);
822         }
823
824         return -EINVAL;
825 }
826
827 int
828 cperf_options_parse(struct cperf_options *options, int argc, char **argv)
829 {
830         int opt, retval, opt_idx;
831
832         while ((opt = getopt_long(argc, argv, "", lgopts, &opt_idx)) != EOF) {
833                 switch (opt) {
834                 /* long options */
835                 case 0:
836
837                         retval = cperf_opts_parse_long(opt_idx, options);
838                         if (retval != 0)
839                                 return retval;
840
841                         break;
842
843                 default:
844                         return -EINVAL;
845                 }
846         }
847
848         return 0;
849 }
850
851 static int
852 check_cipher_buffer_length(struct cperf_options *options)
853 {
854         uint32_t buffer_size, buffer_size_idx = 0;
855
856         if (options->cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC ||
857                         options->cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB) {
858                 if (options->inc_buffer_size != 0)
859                         buffer_size = options->min_buffer_size;
860                 else
861                         buffer_size = options->buffer_size_list[0];
862
863                 while (buffer_size <= options->max_buffer_size) {
864                         if ((buffer_size % AES_BLOCK_SIZE) != 0) {
865                                 RTE_LOG(ERR, USER1, "Some of the buffer sizes are "
866                                         "not suitable for the algorithm selected\n");
867                                 return -EINVAL;
868                         }
869
870                         if (options->inc_buffer_size != 0)
871                                 buffer_size += options->inc_buffer_size;
872                         else {
873                                 if (++buffer_size_idx == options->buffer_size_count)
874                                         break;
875                                 buffer_size = options->buffer_size_list[buffer_size_idx];
876                         }
877
878                 }
879         }
880
881         if (options->cipher_algo == RTE_CRYPTO_CIPHER_DES_CBC ||
882                         options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_CBC ||
883                         options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_ECB) {
884                 if (options->inc_buffer_size != 0)
885                         buffer_size = options->min_buffer_size;
886                 else
887                         buffer_size = options->buffer_size_list[0];
888
889                 while (buffer_size <= options->max_buffer_size) {
890                         if ((buffer_size % DES_BLOCK_SIZE) != 0) {
891                                 RTE_LOG(ERR, USER1, "Some of the buffer sizes are "
892                                         "not suitable for the algorithm selected\n");
893                                 return -EINVAL;
894                         }
895
896                         if (options->inc_buffer_size != 0)
897                                 buffer_size += options->inc_buffer_size;
898                         else {
899                                 if (++buffer_size_idx == options->buffer_size_count)
900                                         break;
901                                 buffer_size = options->buffer_size_list[buffer_size_idx];
902                         }
903
904                 }
905         }
906
907         return 0;
908 }
909
910 int
911 cperf_options_check(struct cperf_options *options)
912 {
913         if (options->op_type == CPERF_CIPHER_ONLY)
914                 options->digest_sz = 0;
915
916         /*
917          * If segment size is not set, assume only one segment,
918          * big enough to contain the largest buffer and the digest
919          */
920         if (options->segment_sz == 0)
921                 options->segment_sz = options->max_buffer_size +
922                                 options->digest_sz;
923
924         if (options->segment_sz < options->digest_sz) {
925                 RTE_LOG(ERR, USER1,
926                                 "Segment size should be at least "
927                                 "the size of the digest\n");
928                 return -EINVAL;
929         }
930
931         if (options->test == CPERF_TEST_TYPE_VERIFY &&
932                         options->test_file == NULL) {
933                 RTE_LOG(ERR, USER1, "Define path to the file with test"
934                                 " vectors.\n");
935                 return -EINVAL;
936         }
937
938         if (options->test == CPERF_TEST_TYPE_VERIFY &&
939                         options->op_type != CPERF_CIPHER_ONLY &&
940                         options->test_name == NULL) {
941                 RTE_LOG(ERR, USER1, "Define test name to get the correct digest"
942                                 " from the test vectors.\n");
943                 return -EINVAL;
944         }
945
946         if (options->test_name != NULL && options->test_file == NULL) {
947                 RTE_LOG(ERR, USER1, "Define path to the file with test"
948                                 " vectors.\n");
949                 return -EINVAL;
950         }
951
952         if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY &&
953                         options->test_file == NULL) {
954                 RTE_LOG(ERR, USER1, "Define path to the file with test"
955                                 " vectors.\n");
956                 return -EINVAL;
957         }
958
959         if (options->test == CPERF_TEST_TYPE_VERIFY &&
960                         (options->inc_buffer_size != 0 ||
961                         options->buffer_size_count > 1)) {
962                 RTE_LOG(ERR, USER1, "Only one buffer size is allowed when "
963                                 "using the verify test.\n");
964                 return -EINVAL;
965         }
966
967         if (options->test == CPERF_TEST_TYPE_VERIFY &&
968                         (options->inc_burst_size != 0 ||
969                         options->burst_size_count > 1)) {
970                 RTE_LOG(ERR, USER1, "Only one burst size is allowed when "
971                                 "using the verify test.\n");
972                 return -EINVAL;
973         }
974
975         if (options->test == CPERF_TEST_TYPE_PMDCC &&
976                         options->pool_sz < options->nb_descriptors) {
977                 RTE_LOG(ERR, USER1, "For pmd cyclecount benchmarks, pool size "
978                                 "must be equal or greater than the number of "
979                                 "cryptodev descriptors.\n");
980                 return -EINVAL;
981         }
982
983         if (options->op_type == CPERF_CIPHER_THEN_AUTH) {
984                 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
985                                 options->auth_op !=
986                                 RTE_CRYPTO_AUTH_OP_GENERATE) {
987                         RTE_LOG(ERR, USER1, "Option cipher then auth must use"
988                                         " options: encrypt and generate.\n");
989                         return -EINVAL;
990                 }
991         } else if (options->op_type == CPERF_AUTH_THEN_CIPHER) {
992                 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_DECRYPT &&
993                                 options->auth_op !=
994                                 RTE_CRYPTO_AUTH_OP_VERIFY) {
995                         RTE_LOG(ERR, USER1, "Option auth then cipher must use"
996                                         " options: decrypt and verify.\n");
997                         return -EINVAL;
998                 }
999         }
1000
1001         if (options->op_type == CPERF_CIPHER_ONLY ||
1002                         options->op_type == CPERF_CIPHER_THEN_AUTH ||
1003                         options->op_type == CPERF_AUTH_THEN_CIPHER) {
1004                 if (check_cipher_buffer_length(options) < 0)
1005                         return -EINVAL;
1006         }
1007
1008         return 0;
1009 }
1010
1011 void
1012 cperf_options_dump(struct cperf_options *opts)
1013 {
1014         uint8_t size_idx;
1015
1016         printf("# Crypto Performance Application Options:\n");
1017         printf("#\n");
1018         printf("# cperf test: %s\n", cperf_test_type_strs[opts->test]);
1019         printf("#\n");
1020         printf("# size of crypto op / mbuf pool: %u\n", opts->pool_sz);
1021         printf("# total number of ops: %u\n", opts->total_ops);
1022         if (opts->inc_buffer_size != 0) {
1023                 printf("# buffer size:\n");
1024                 printf("#\t min: %u\n", opts->min_buffer_size);
1025                 printf("#\t max: %u\n", opts->max_buffer_size);
1026                 printf("#\t inc: %u\n", opts->inc_buffer_size);
1027         } else {
1028                 printf("# buffer sizes: ");
1029                 for (size_idx = 0; size_idx < opts->buffer_size_count; size_idx++)
1030                         printf("%u ", opts->buffer_size_list[size_idx]);
1031                 printf("\n");
1032         }
1033         if (opts->inc_burst_size != 0) {
1034                 printf("# burst size:\n");
1035                 printf("#\t min: %u\n", opts->min_burst_size);
1036                 printf("#\t max: %u\n", opts->max_burst_size);
1037                 printf("#\t inc: %u\n", opts->inc_burst_size);
1038         } else {
1039                 printf("# burst sizes: ");
1040                 for (size_idx = 0; size_idx < opts->burst_size_count; size_idx++)
1041                         printf("%u ", opts->burst_size_list[size_idx]);
1042                 printf("\n");
1043         }
1044         printf("\n# segment size: %u\n", opts->segment_sz);
1045         printf("#\n");
1046         printf("# cryptodev type: %s\n", opts->device_type);
1047         printf("#\n");
1048         printf("# number of queue pairs per device: %u\n", opts->nb_qps);
1049         printf("# crypto operation: %s\n", cperf_op_type_strs[opts->op_type]);
1050         printf("# sessionless: %s\n", opts->sessionless ? "yes" : "no");
1051         printf("# out of place: %s\n", opts->out_of_place ? "yes" : "no");
1052         if (opts->test == CPERF_TEST_TYPE_PMDCC)
1053                 printf("# inter-burst delay: %u ms\n", opts->pmdcc_delay);
1054
1055         printf("#\n");
1056
1057         if (opts->op_type == CPERF_AUTH_ONLY ||
1058                         opts->op_type == CPERF_CIPHER_THEN_AUTH ||
1059                         opts->op_type == CPERF_AUTH_THEN_CIPHER) {
1060                 printf("# auth algorithm: %s\n",
1061                         rte_crypto_auth_algorithm_strings[opts->auth_algo]);
1062                 printf("# auth operation: %s\n",
1063                         rte_crypto_auth_operation_strings[opts->auth_op]);
1064                 printf("# auth key size: %u\n", opts->auth_key_sz);
1065                 printf("# auth iv size: %u\n", opts->auth_iv_sz);
1066                 printf("# auth digest size: %u\n", opts->digest_sz);
1067                 printf("#\n");
1068         }
1069
1070         if (opts->op_type == CPERF_CIPHER_ONLY ||
1071                         opts->op_type == CPERF_CIPHER_THEN_AUTH ||
1072                         opts->op_type == CPERF_AUTH_THEN_CIPHER) {
1073                 printf("# cipher algorithm: %s\n",
1074                         rte_crypto_cipher_algorithm_strings[opts->cipher_algo]);
1075                 printf("# cipher operation: %s\n",
1076                         rte_crypto_cipher_operation_strings[opts->cipher_op]);
1077                 printf("# cipher key size: %u\n", opts->cipher_key_sz);
1078                 printf("# cipher iv size: %u\n", opts->cipher_iv_sz);
1079                 printf("#\n");
1080         }
1081
1082         if (opts->op_type == CPERF_AEAD) {
1083                 printf("# aead algorithm: %s\n",
1084                         rte_crypto_aead_algorithm_strings[opts->aead_algo]);
1085                 printf("# aead operation: %s\n",
1086                         rte_crypto_aead_operation_strings[opts->aead_op]);
1087                 printf("# aead key size: %u\n", opts->aead_key_sz);
1088                 printf("# aead iv size: %u\n", opts->aead_iv_sz);
1089                 printf("# aead digest size: %u\n", opts->digest_sz);
1090                 printf("# aead aad size: %u\n", opts->aead_aad_sz);
1091                 printf("#\n");
1092         }
1093 }