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