xref: /dpdk/app/test-crypto-perf/cperf_options_parsing.c (revision 0a081a5fd26fbdae00a34541924d798b6dd4a63e)
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 }
1017