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