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