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