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