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