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 448 int id = get_str_key_id_mapping(optype_namemap, 449 RTE_DIM(optype_namemap), arg); 450 if (id < 0) { 451 RTE_LOG(ERR, USER1, "invalid opt type specified\n"); 452 return -1; 453 } 454 455 opts->op_type = (enum cperf_op_type)id; 456 457 return 0; 458 } 459 460 static int 461 parse_sessionless(struct cperf_options *opts, 462 const char *arg __rte_unused) 463 { 464 opts->sessionless = 1; 465 return 0; 466 } 467 468 static int 469 parse_out_of_place(struct cperf_options *opts, 470 const char *arg __rte_unused) 471 { 472 opts->out_of_place = 1; 473 return 0; 474 } 475 476 static int 477 parse_test_file(struct cperf_options *opts, 478 const char *arg) 479 { 480 opts->test_file = strdup(arg); 481 if (access(opts->test_file, F_OK) != -1) 482 return 0; 483 RTE_LOG(ERR, USER1, "Test vector file doesn't exist\n"); 484 485 return -1; 486 } 487 488 static int 489 parse_test_name(struct cperf_options *opts, 490 const char *arg) 491 { 492 char *test_name = (char *) rte_zmalloc(NULL, 493 sizeof(char) * (strlen(arg) + 3), 0); 494 snprintf(test_name, strlen(arg) + 3, "[%s]", arg); 495 opts->test_name = test_name; 496 497 return 0; 498 } 499 500 static int 501 parse_silent(struct cperf_options *opts, 502 const char *arg __rte_unused) 503 { 504 opts->silent = 1; 505 506 return 0; 507 } 508 509 static int 510 parse_cipher_algo(struct cperf_options *opts, const char *arg) 511 { 512 513 enum rte_crypto_cipher_algorithm cipher_algo; 514 515 if (rte_cryptodev_get_cipher_algo_enum(&cipher_algo, arg) < 0) { 516 RTE_LOG(ERR, USER1, "Invalid cipher algorithm specified\n"); 517 return -1; 518 } 519 520 opts->cipher_algo = cipher_algo; 521 522 return 0; 523 } 524 525 static int 526 parse_cipher_op(struct cperf_options *opts, const char *arg) 527 { 528 struct name_id_map cipher_op_namemap[] = { 529 { 530 rte_crypto_cipher_operation_strings 531 [RTE_CRYPTO_CIPHER_OP_ENCRYPT], 532 RTE_CRYPTO_CIPHER_OP_ENCRYPT }, 533 { 534 rte_crypto_cipher_operation_strings 535 [RTE_CRYPTO_CIPHER_OP_DECRYPT], 536 RTE_CRYPTO_CIPHER_OP_DECRYPT 537 } 538 }; 539 540 int id = get_str_key_id_mapping(cipher_op_namemap, 541 RTE_DIM(cipher_op_namemap), arg); 542 if (id < 0) { 543 RTE_LOG(ERR, USER1, "Invalid cipher operation specified\n"); 544 return -1; 545 } 546 547 opts->cipher_op = (enum rte_crypto_cipher_operation)id; 548 549 return 0; 550 } 551 552 static int 553 parse_cipher_key_sz(struct cperf_options *opts, const char *arg) 554 { 555 return parse_uint16_t(&opts->cipher_key_sz, arg); 556 } 557 558 static int 559 parse_cipher_iv_sz(struct cperf_options *opts, const char *arg) 560 { 561 return parse_uint16_t(&opts->cipher_iv_sz, arg); 562 } 563 564 static int 565 parse_auth_algo(struct cperf_options *opts, const char *arg) 566 { 567 enum rte_crypto_auth_algorithm auth_algo; 568 569 if (rte_cryptodev_get_auth_algo_enum(&auth_algo, arg) < 0) { 570 RTE_LOG(ERR, USER1, "Invalid authentication algorithm specified\n"); 571 return -1; 572 } 573 574 opts->auth_algo = auth_algo; 575 576 return 0; 577 } 578 579 static int 580 parse_auth_op(struct cperf_options *opts, const char *arg) 581 { 582 struct name_id_map auth_op_namemap[] = { 583 { 584 rte_crypto_auth_operation_strings 585 [RTE_CRYPTO_AUTH_OP_GENERATE], 586 RTE_CRYPTO_AUTH_OP_GENERATE }, 587 { 588 rte_crypto_auth_operation_strings 589 [RTE_CRYPTO_AUTH_OP_VERIFY], 590 RTE_CRYPTO_AUTH_OP_VERIFY 591 } 592 }; 593 594 int id = get_str_key_id_mapping(auth_op_namemap, 595 RTE_DIM(auth_op_namemap), arg); 596 if (id < 0) { 597 RTE_LOG(ERR, USER1, "invalid authentication operation specified" 598 "\n"); 599 return -1; 600 } 601 602 opts->auth_op = (enum rte_crypto_auth_operation)id; 603 604 return 0; 605 } 606 607 static int 608 parse_auth_key_sz(struct cperf_options *opts, const char *arg) 609 { 610 return parse_uint16_t(&opts->auth_key_sz, arg); 611 } 612 613 static int 614 parse_digest_sz(struct cperf_options *opts, const char *arg) 615 { 616 return parse_uint16_t(&opts->digest_sz, arg); 617 } 618 619 static int 620 parse_auth_iv_sz(struct cperf_options *opts, const char *arg) 621 { 622 return parse_uint16_t(&opts->auth_iv_sz, arg); 623 } 624 625 static int 626 parse_aead_algo(struct cperf_options *opts, const char *arg) 627 { 628 enum rte_crypto_aead_algorithm aead_algo; 629 630 if (rte_cryptodev_get_aead_algo_enum(&aead_algo, arg) < 0) { 631 RTE_LOG(ERR, USER1, "Invalid AEAD algorithm specified\n"); 632 return -1; 633 } 634 635 opts->aead_algo = aead_algo; 636 637 return 0; 638 } 639 640 static int 641 parse_aead_op(struct cperf_options *opts, const char *arg) 642 { 643 struct name_id_map aead_op_namemap[] = { 644 { 645 rte_crypto_aead_operation_strings 646 [RTE_CRYPTO_AEAD_OP_ENCRYPT], 647 RTE_CRYPTO_AEAD_OP_ENCRYPT }, 648 { 649 rte_crypto_aead_operation_strings 650 [RTE_CRYPTO_AEAD_OP_DECRYPT], 651 RTE_CRYPTO_AEAD_OP_DECRYPT 652 } 653 }; 654 655 int id = get_str_key_id_mapping(aead_op_namemap, 656 RTE_DIM(aead_op_namemap), arg); 657 if (id < 0) { 658 RTE_LOG(ERR, USER1, "invalid AEAD operation specified" 659 "\n"); 660 return -1; 661 } 662 663 opts->aead_op = (enum rte_crypto_aead_operation)id; 664 665 return 0; 666 } 667 668 static int 669 parse_aead_key_sz(struct cperf_options *opts, const char *arg) 670 { 671 return parse_uint16_t(&opts->aead_key_sz, arg); 672 } 673 674 static int 675 parse_aead_iv_sz(struct cperf_options *opts, const char *arg) 676 { 677 return parse_uint16_t(&opts->aead_iv_sz, arg); 678 } 679 680 static int 681 parse_aead_aad_sz(struct cperf_options *opts, const char *arg) 682 { 683 return parse_uint16_t(&opts->aead_aad_sz, arg); 684 } 685 686 static int 687 parse_csv_friendly(struct cperf_options *opts, const char *arg __rte_unused) 688 { 689 opts->csv = 1; 690 opts->silent = 1; 691 return 0; 692 } 693 694 static int 695 parse_pmd_cyclecount_delay_ms(struct cperf_options *opts, 696 const char *arg) 697 { 698 int ret = parse_uint32_t(&opts->pmdcc_delay, arg); 699 700 if (ret) { 701 RTE_LOG(ERR, USER1, "failed to parse pmd-cyclecount delay\n"); 702 return -1; 703 } 704 705 return 0; 706 } 707 708 typedef int (*option_parser_t)(struct cperf_options *opts, 709 const char *arg); 710 711 struct long_opt_parser { 712 const char *lgopt_name; 713 option_parser_t parser_fn; 714 715 }; 716 717 static struct option lgopts[] = { 718 719 { CPERF_PTEST_TYPE, required_argument, 0, 0 }, 720 721 { CPERF_POOL_SIZE, required_argument, 0, 0 }, 722 { CPERF_TOTAL_OPS, required_argument, 0, 0 }, 723 { CPERF_BURST_SIZE, required_argument, 0, 0 }, 724 { CPERF_BUFFER_SIZE, required_argument, 0, 0 }, 725 { CPERF_SEGMENT_SIZE, required_argument, 0, 0 }, 726 { CPERF_DESC_NB, required_argument, 0, 0 }, 727 728 { CPERF_IMIX, required_argument, 0, 0 }, 729 { CPERF_DEVTYPE, required_argument, 0, 0 }, 730 { CPERF_OPTYPE, required_argument, 0, 0 }, 731 732 { CPERF_SILENT, no_argument, 0, 0 }, 733 { CPERF_SESSIONLESS, no_argument, 0, 0 }, 734 { CPERF_OUT_OF_PLACE, no_argument, 0, 0 }, 735 { CPERF_TEST_FILE, required_argument, 0, 0 }, 736 { CPERF_TEST_NAME, required_argument, 0, 0 }, 737 738 { CPERF_CIPHER_ALGO, required_argument, 0, 0 }, 739 { CPERF_CIPHER_OP, required_argument, 0, 0 }, 740 741 { CPERF_CIPHER_KEY_SZ, required_argument, 0, 0 }, 742 { CPERF_CIPHER_IV_SZ, required_argument, 0, 0 }, 743 744 { CPERF_AUTH_ALGO, required_argument, 0, 0 }, 745 { CPERF_AUTH_OP, required_argument, 0, 0 }, 746 747 { CPERF_AUTH_KEY_SZ, required_argument, 0, 0 }, 748 { CPERF_AUTH_IV_SZ, required_argument, 0, 0 }, 749 750 { CPERF_AEAD_ALGO, required_argument, 0, 0 }, 751 { CPERF_AEAD_OP, required_argument, 0, 0 }, 752 753 { CPERF_AEAD_KEY_SZ, required_argument, 0, 0 }, 754 { CPERF_AEAD_AAD_SZ, required_argument, 0, 0 }, 755 { CPERF_AEAD_IV_SZ, required_argument, 0, 0 }, 756 757 { CPERF_DIGEST_SZ, required_argument, 0, 0 }, 758 759 { CPERF_CSV, no_argument, 0, 0}, 760 761 { CPERF_PMDCC_DELAY_MS, required_argument, 0, 0 }, 762 763 { NULL, 0, 0, 0 } 764 }; 765 766 void 767 cperf_options_default(struct cperf_options *opts) 768 { 769 opts->test = CPERF_TEST_TYPE_THROUGHPUT; 770 771 opts->pool_sz = 8192; 772 opts->total_ops = 10000000; 773 opts->nb_descriptors = 2048; 774 775 opts->buffer_size_list[0] = 64; 776 opts->buffer_size_count = 1; 777 opts->max_buffer_size = 64; 778 opts->min_buffer_size = 64; 779 opts->inc_buffer_size = 0; 780 781 opts->burst_size_list[0] = 32; 782 opts->burst_size_count = 1; 783 opts->max_burst_size = 32; 784 opts->min_burst_size = 32; 785 opts->inc_burst_size = 0; 786 787 /* 788 * Will be parsed from command line or set to 789 * maximum buffer size + digest, later 790 */ 791 opts->segment_sz = 0; 792 793 opts->imix_distribution_count = 0; 794 strncpy(opts->device_type, "crypto_aesni_mb", 795 sizeof(opts->device_type)); 796 opts->nb_qps = 1; 797 798 opts->op_type = CPERF_CIPHER_THEN_AUTH; 799 800 opts->silent = 0; 801 opts->test_file = NULL; 802 opts->test_name = NULL; 803 opts->sessionless = 0; 804 opts->out_of_place = 0; 805 opts->csv = 0; 806 807 opts->cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC; 808 opts->cipher_op = RTE_CRYPTO_CIPHER_OP_ENCRYPT; 809 opts->cipher_key_sz = 16; 810 opts->cipher_iv_sz = 16; 811 812 opts->auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC; 813 opts->auth_op = RTE_CRYPTO_AUTH_OP_GENERATE; 814 815 opts->auth_key_sz = 64; 816 opts->auth_iv_sz = 0; 817 818 opts->aead_key_sz = 0; 819 opts->aead_iv_sz = 0; 820 opts->aead_aad_sz = 0; 821 822 opts->digest_sz = 12; 823 824 opts->pmdcc_delay = 0; 825 } 826 827 static int 828 cperf_opts_parse_long(int opt_idx, struct cperf_options *opts) 829 { 830 struct long_opt_parser parsermap[] = { 831 { CPERF_PTEST_TYPE, parse_cperf_test_type }, 832 { CPERF_SILENT, parse_silent }, 833 { CPERF_POOL_SIZE, parse_pool_sz }, 834 { CPERF_TOTAL_OPS, parse_total_ops }, 835 { CPERF_BURST_SIZE, parse_burst_sz }, 836 { CPERF_BUFFER_SIZE, parse_buffer_sz }, 837 { CPERF_SEGMENT_SIZE, parse_segment_sz }, 838 { CPERF_DESC_NB, parse_desc_nb }, 839 { CPERF_DEVTYPE, parse_device_type }, 840 { CPERF_OPTYPE, parse_op_type }, 841 { CPERF_SESSIONLESS, parse_sessionless }, 842 { CPERF_OUT_OF_PLACE, parse_out_of_place }, 843 { CPERF_IMIX, parse_imix }, 844 { CPERF_TEST_FILE, parse_test_file }, 845 { CPERF_TEST_NAME, parse_test_name }, 846 { CPERF_CIPHER_ALGO, parse_cipher_algo }, 847 { CPERF_CIPHER_OP, parse_cipher_op }, 848 { CPERF_CIPHER_KEY_SZ, parse_cipher_key_sz }, 849 { CPERF_CIPHER_IV_SZ, parse_cipher_iv_sz }, 850 { CPERF_AUTH_ALGO, parse_auth_algo }, 851 { CPERF_AUTH_OP, parse_auth_op }, 852 { CPERF_AUTH_KEY_SZ, parse_auth_key_sz }, 853 { CPERF_AUTH_IV_SZ, parse_auth_iv_sz }, 854 { CPERF_AEAD_ALGO, parse_aead_algo }, 855 { CPERF_AEAD_OP, parse_aead_op }, 856 { CPERF_AEAD_KEY_SZ, parse_aead_key_sz }, 857 { CPERF_AEAD_IV_SZ, parse_aead_iv_sz }, 858 { CPERF_AEAD_AAD_SZ, parse_aead_aad_sz }, 859 { CPERF_DIGEST_SZ, parse_digest_sz }, 860 { CPERF_CSV, parse_csv_friendly}, 861 { CPERF_PMDCC_DELAY_MS, parse_pmd_cyclecount_delay_ms}, 862 }; 863 unsigned int i; 864 865 for (i = 0; i < RTE_DIM(parsermap); i++) { 866 if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name, 867 strlen(lgopts[opt_idx].name)) == 0) 868 return parsermap[i].parser_fn(opts, optarg); 869 } 870 871 return -EINVAL; 872 } 873 874 int 875 cperf_options_parse(struct cperf_options *options, int argc, char **argv) 876 { 877 int opt, retval, opt_idx; 878 879 while ((opt = getopt_long(argc, argv, "h", lgopts, &opt_idx)) != EOF) { 880 switch (opt) { 881 case 'h': 882 usage(argv[0]); 883 rte_exit(EXIT_SUCCESS, "Displayed help\n"); 884 break; 885 /* long options */ 886 case 0: 887 retval = cperf_opts_parse_long(opt_idx, options); 888 if (retval != 0) 889 return retval; 890 891 break; 892 893 default: 894 usage(argv[0]); 895 return -EINVAL; 896 } 897 } 898 899 return 0; 900 } 901 902 static int 903 check_cipher_buffer_length(struct cperf_options *options) 904 { 905 uint32_t buffer_size, buffer_size_idx = 0; 906 907 if (options->cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC || 908 options->cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB) { 909 if (options->inc_buffer_size != 0) 910 buffer_size = options->min_buffer_size; 911 else 912 buffer_size = options->buffer_size_list[0]; 913 914 while (buffer_size <= options->max_buffer_size) { 915 if ((buffer_size % AES_BLOCK_SIZE) != 0) { 916 RTE_LOG(ERR, USER1, "Some of the buffer sizes are " 917 "not suitable for the algorithm selected\n"); 918 return -EINVAL; 919 } 920 921 if (options->inc_buffer_size != 0) 922 buffer_size += options->inc_buffer_size; 923 else { 924 if (++buffer_size_idx == options->buffer_size_count) 925 break; 926 buffer_size = options->buffer_size_list[buffer_size_idx]; 927 } 928 929 } 930 } 931 932 if (options->cipher_algo == RTE_CRYPTO_CIPHER_DES_CBC || 933 options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_CBC || 934 options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_ECB) { 935 if (options->inc_buffer_size != 0) 936 buffer_size = options->min_buffer_size; 937 else 938 buffer_size = options->buffer_size_list[0]; 939 940 while (buffer_size <= options->max_buffer_size) { 941 if ((buffer_size % DES_BLOCK_SIZE) != 0) { 942 RTE_LOG(ERR, USER1, "Some of the buffer sizes are " 943 "not suitable for the algorithm selected\n"); 944 return -EINVAL; 945 } 946 947 if (options->inc_buffer_size != 0) 948 buffer_size += options->inc_buffer_size; 949 else { 950 if (++buffer_size_idx == options->buffer_size_count) 951 break; 952 buffer_size = options->buffer_size_list[buffer_size_idx]; 953 } 954 955 } 956 } 957 958 return 0; 959 } 960 961 int 962 cperf_options_check(struct cperf_options *options) 963 { 964 if (options->op_type == CPERF_CIPHER_ONLY) 965 options->digest_sz = 0; 966 967 if (options->out_of_place && 968 options->segment_sz <= options->max_buffer_size) { 969 RTE_LOG(ERR, USER1, "Out of place mode can only work " 970 "with non segmented buffers\n"); 971 return -EINVAL; 972 } 973 974 /* 975 * If segment size is not set, assume only one segment, 976 * big enough to contain the largest buffer and the digest 977 */ 978 if (options->segment_sz == 0) 979 options->segment_sz = options->max_buffer_size + 980 options->digest_sz; 981 982 if (options->segment_sz < options->digest_sz) { 983 RTE_LOG(ERR, USER1, 984 "Segment size should be at least " 985 "the size of the digest\n"); 986 return -EINVAL; 987 } 988 989 if ((options->imix_distribution_count != 0) && 990 (options->imix_distribution_count != 991 options->buffer_size_count)) { 992 RTE_LOG(ERR, USER1, "IMIX distribution must have the same " 993 "number of buffer sizes\n"); 994 return -EINVAL; 995 } 996 997 if (options->test == CPERF_TEST_TYPE_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->op_type != CPERF_CIPHER_ONLY && 1006 options->test_name == NULL) { 1007 RTE_LOG(ERR, USER1, "Define test name to get the correct digest" 1008 " from the test vectors.\n"); 1009 return -EINVAL; 1010 } 1011 1012 if (options->test_name != NULL && options->test_file == NULL) { 1013 RTE_LOG(ERR, USER1, "Define path to the file with test" 1014 " vectors.\n"); 1015 return -EINVAL; 1016 } 1017 1018 if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY && 1019 options->test_file == NULL) { 1020 RTE_LOG(ERR, USER1, "Define path to the file with test" 1021 " vectors.\n"); 1022 return -EINVAL; 1023 } 1024 1025 if (options->test == CPERF_TEST_TYPE_VERIFY && 1026 (options->inc_buffer_size != 0 || 1027 options->buffer_size_count > 1)) { 1028 RTE_LOG(ERR, USER1, "Only one buffer size is allowed when " 1029 "using the verify test.\n"); 1030 return -EINVAL; 1031 } 1032 1033 if (options->test == CPERF_TEST_TYPE_VERIFY && 1034 (options->inc_burst_size != 0 || 1035 options->burst_size_count > 1)) { 1036 RTE_LOG(ERR, USER1, "Only one burst size is allowed when " 1037 "using the verify test.\n"); 1038 return -EINVAL; 1039 } 1040 1041 if (options->test == CPERF_TEST_TYPE_PMDCC && 1042 options->pool_sz < options->nb_descriptors) { 1043 RTE_LOG(ERR, USER1, "For pmd cyclecount benchmarks, pool size " 1044 "must be equal or greater than the number of " 1045 "cryptodev descriptors.\n"); 1046 return -EINVAL; 1047 } 1048 1049 if (options->test == CPERF_TEST_TYPE_VERIFY && 1050 options->imix_distribution_count > 0) { 1051 RTE_LOG(ERR, USER1, "IMIX is not allowed when " 1052 "using the verify test.\n"); 1053 return -EINVAL; 1054 } 1055 1056 if (options->op_type == CPERF_CIPHER_THEN_AUTH) { 1057 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_ENCRYPT && 1058 options->auth_op != 1059 RTE_CRYPTO_AUTH_OP_GENERATE) { 1060 RTE_LOG(ERR, USER1, "Option cipher then auth must use" 1061 " options: encrypt and generate.\n"); 1062 return -EINVAL; 1063 } 1064 } else if (options->op_type == CPERF_AUTH_THEN_CIPHER) { 1065 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_DECRYPT && 1066 options->auth_op != 1067 RTE_CRYPTO_AUTH_OP_VERIFY) { 1068 RTE_LOG(ERR, USER1, "Option auth then cipher must use" 1069 " options: decrypt and verify.\n"); 1070 return -EINVAL; 1071 } 1072 } 1073 1074 if (options->op_type == CPERF_CIPHER_ONLY || 1075 options->op_type == CPERF_CIPHER_THEN_AUTH || 1076 options->op_type == CPERF_AUTH_THEN_CIPHER) { 1077 if (check_cipher_buffer_length(options) < 0) 1078 return -EINVAL; 1079 } 1080 1081 return 0; 1082 } 1083 1084 void 1085 cperf_options_dump(struct cperf_options *opts) 1086 { 1087 uint8_t size_idx; 1088 1089 printf("# Crypto Performance Application Options:\n"); 1090 printf("#\n"); 1091 printf("# cperf test: %s\n", cperf_test_type_strs[opts->test]); 1092 printf("#\n"); 1093 printf("# size of crypto op / mbuf pool: %u\n", opts->pool_sz); 1094 printf("# total number of ops: %u\n", opts->total_ops); 1095 if (opts->inc_buffer_size != 0) { 1096 printf("# buffer size:\n"); 1097 printf("#\t min: %u\n", opts->min_buffer_size); 1098 printf("#\t max: %u\n", opts->max_buffer_size); 1099 printf("#\t inc: %u\n", opts->inc_buffer_size); 1100 } else { 1101 printf("# buffer sizes: "); 1102 for (size_idx = 0; size_idx < opts->buffer_size_count; size_idx++) 1103 printf("%u ", opts->buffer_size_list[size_idx]); 1104 printf("\n"); 1105 } 1106 if (opts->inc_burst_size != 0) { 1107 printf("# burst size:\n"); 1108 printf("#\t min: %u\n", opts->min_burst_size); 1109 printf("#\t max: %u\n", opts->max_burst_size); 1110 printf("#\t inc: %u\n", opts->inc_burst_size); 1111 } else { 1112 printf("# burst sizes: "); 1113 for (size_idx = 0; size_idx < opts->burst_size_count; size_idx++) 1114 printf("%u ", opts->burst_size_list[size_idx]); 1115 printf("\n"); 1116 } 1117 printf("\n# segment size: %u\n", opts->segment_sz); 1118 printf("#\n"); 1119 printf("# cryptodev type: %s\n", opts->device_type); 1120 printf("#\n"); 1121 printf("# number of queue pairs per device: %u\n", opts->nb_qps); 1122 printf("# crypto operation: %s\n", cperf_op_type_strs[opts->op_type]); 1123 printf("# sessionless: %s\n", opts->sessionless ? "yes" : "no"); 1124 printf("# out of place: %s\n", opts->out_of_place ? "yes" : "no"); 1125 if (opts->test == CPERF_TEST_TYPE_PMDCC) 1126 printf("# inter-burst delay: %u ms\n", opts->pmdcc_delay); 1127 1128 printf("#\n"); 1129 1130 if (opts->op_type == CPERF_AUTH_ONLY || 1131 opts->op_type == CPERF_CIPHER_THEN_AUTH || 1132 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 1133 printf("# auth algorithm: %s\n", 1134 rte_crypto_auth_algorithm_strings[opts->auth_algo]); 1135 printf("# auth operation: %s\n", 1136 rte_crypto_auth_operation_strings[opts->auth_op]); 1137 printf("# auth key size: %u\n", opts->auth_key_sz); 1138 printf("# auth iv size: %u\n", opts->auth_iv_sz); 1139 printf("# auth digest size: %u\n", opts->digest_sz); 1140 printf("#\n"); 1141 } 1142 1143 if (opts->op_type == CPERF_CIPHER_ONLY || 1144 opts->op_type == CPERF_CIPHER_THEN_AUTH || 1145 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 1146 printf("# cipher algorithm: %s\n", 1147 rte_crypto_cipher_algorithm_strings[opts->cipher_algo]); 1148 printf("# cipher operation: %s\n", 1149 rte_crypto_cipher_operation_strings[opts->cipher_op]); 1150 printf("# cipher key size: %u\n", opts->cipher_key_sz); 1151 printf("# cipher iv size: %u\n", opts->cipher_iv_sz); 1152 printf("#\n"); 1153 } 1154 1155 if (opts->op_type == CPERF_AEAD) { 1156 printf("# aead algorithm: %s\n", 1157 rte_crypto_aead_algorithm_strings[opts->aead_algo]); 1158 printf("# aead operation: %s\n", 1159 rte_crypto_aead_operation_strings[opts->aead_op]); 1160 printf("# aead key size: %u\n", opts->aead_key_sz); 1161 printf("# aead iv size: %u\n", opts->aead_iv_sz); 1162 printf("# aead digest size: %u\n", opts->digest_sz); 1163 printf("# aead aad size: %u\n", opts->aead_aad_sz); 1164 printf("#\n"); 1165 } 1166 } 1167