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