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 /* 968 * If segment size is not set, assume only one segment, 969 * big enough to contain the largest buffer and the digest 970 */ 971 if (options->segment_sz == 0) 972 options->segment_sz = options->max_buffer_size + 973 options->digest_sz; 974 975 if (options->segment_sz < options->digest_sz) { 976 RTE_LOG(ERR, USER1, 977 "Segment size should be at least " 978 "the size of the digest\n"); 979 return -EINVAL; 980 } 981 982 if ((options->imix_distribution_count != 0) && 983 (options->imix_distribution_count != 984 options->buffer_size_count)) { 985 RTE_LOG(ERR, USER1, "IMIX distribution must have the same " 986 "number of buffer sizes\n"); 987 return -EINVAL; 988 } 989 990 if (options->test == CPERF_TEST_TYPE_VERIFY && 991 options->test_file == NULL) { 992 RTE_LOG(ERR, USER1, "Define path to the file with test" 993 " vectors.\n"); 994 return -EINVAL; 995 } 996 997 if (options->test == CPERF_TEST_TYPE_VERIFY && 998 options->op_type != CPERF_CIPHER_ONLY && 999 options->test_name == NULL) { 1000 RTE_LOG(ERR, USER1, "Define test name to get the correct digest" 1001 " from the test vectors.\n"); 1002 return -EINVAL; 1003 } 1004 1005 if (options->test_name != NULL && options->test_file == NULL) { 1006 RTE_LOG(ERR, USER1, "Define path to the file with test" 1007 " vectors.\n"); 1008 return -EINVAL; 1009 } 1010 1011 if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY && 1012 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->test == CPERF_TEST_TYPE_VERIFY && 1019 (options->inc_buffer_size != 0 || 1020 options->buffer_size_count > 1)) { 1021 RTE_LOG(ERR, USER1, "Only one buffer size is allowed when " 1022 "using the verify test.\n"); 1023 return -EINVAL; 1024 } 1025 1026 if (options->test == CPERF_TEST_TYPE_VERIFY && 1027 (options->inc_burst_size != 0 || 1028 options->burst_size_count > 1)) { 1029 RTE_LOG(ERR, USER1, "Only one burst size is allowed when " 1030 "using the verify test.\n"); 1031 return -EINVAL; 1032 } 1033 1034 if (options->test == CPERF_TEST_TYPE_PMDCC && 1035 options->pool_sz < options->nb_descriptors) { 1036 RTE_LOG(ERR, USER1, "For pmd cyclecount benchmarks, pool size " 1037 "must be equal or greater than the number of " 1038 "cryptodev descriptors.\n"); 1039 return -EINVAL; 1040 } 1041 1042 if (options->test == CPERF_TEST_TYPE_VERIFY && 1043 options->imix_distribution_count > 0) { 1044 RTE_LOG(ERR, USER1, "IMIX is not allowed when " 1045 "using the verify test.\n"); 1046 return -EINVAL; 1047 } 1048 1049 if (options->op_type == CPERF_CIPHER_THEN_AUTH) { 1050 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_ENCRYPT && 1051 options->auth_op != 1052 RTE_CRYPTO_AUTH_OP_GENERATE) { 1053 RTE_LOG(ERR, USER1, "Option cipher then auth must use" 1054 " options: encrypt and generate.\n"); 1055 return -EINVAL; 1056 } 1057 } else if (options->op_type == CPERF_AUTH_THEN_CIPHER) { 1058 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_DECRYPT && 1059 options->auth_op != 1060 RTE_CRYPTO_AUTH_OP_VERIFY) { 1061 RTE_LOG(ERR, USER1, "Option auth then cipher must use" 1062 " options: decrypt and verify.\n"); 1063 return -EINVAL; 1064 } 1065 } 1066 1067 if (options->op_type == CPERF_CIPHER_ONLY || 1068 options->op_type == CPERF_CIPHER_THEN_AUTH || 1069 options->op_type == CPERF_AUTH_THEN_CIPHER) { 1070 if (check_cipher_buffer_length(options) < 0) 1071 return -EINVAL; 1072 } 1073 1074 return 0; 1075 } 1076 1077 void 1078 cperf_options_dump(struct cperf_options *opts) 1079 { 1080 uint8_t size_idx; 1081 1082 printf("# Crypto Performance Application Options:\n"); 1083 printf("#\n"); 1084 printf("# cperf test: %s\n", cperf_test_type_strs[opts->test]); 1085 printf("#\n"); 1086 printf("# size of crypto op / mbuf pool: %u\n", opts->pool_sz); 1087 printf("# total number of ops: %u\n", opts->total_ops); 1088 if (opts->inc_buffer_size != 0) { 1089 printf("# buffer size:\n"); 1090 printf("#\t min: %u\n", opts->min_buffer_size); 1091 printf("#\t max: %u\n", opts->max_buffer_size); 1092 printf("#\t inc: %u\n", opts->inc_buffer_size); 1093 } else { 1094 printf("# buffer sizes: "); 1095 for (size_idx = 0; size_idx < opts->buffer_size_count; size_idx++) 1096 printf("%u ", opts->buffer_size_list[size_idx]); 1097 printf("\n"); 1098 } 1099 if (opts->inc_burst_size != 0) { 1100 printf("# burst size:\n"); 1101 printf("#\t min: %u\n", opts->min_burst_size); 1102 printf("#\t max: %u\n", opts->max_burst_size); 1103 printf("#\t inc: %u\n", opts->inc_burst_size); 1104 } else { 1105 printf("# burst sizes: "); 1106 for (size_idx = 0; size_idx < opts->burst_size_count; size_idx++) 1107 printf("%u ", opts->burst_size_list[size_idx]); 1108 printf("\n"); 1109 } 1110 printf("\n# segment size: %u\n", opts->segment_sz); 1111 printf("#\n"); 1112 printf("# cryptodev type: %s\n", opts->device_type); 1113 printf("#\n"); 1114 printf("# number of queue pairs per device: %u\n", opts->nb_qps); 1115 printf("# crypto operation: %s\n", cperf_op_type_strs[opts->op_type]); 1116 printf("# sessionless: %s\n", opts->sessionless ? "yes" : "no"); 1117 printf("# out of place: %s\n", opts->out_of_place ? "yes" : "no"); 1118 if (opts->test == CPERF_TEST_TYPE_PMDCC) 1119 printf("# inter-burst delay: %u ms\n", opts->pmdcc_delay); 1120 1121 printf("#\n"); 1122 1123 if (opts->op_type == CPERF_AUTH_ONLY || 1124 opts->op_type == CPERF_CIPHER_THEN_AUTH || 1125 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 1126 printf("# auth algorithm: %s\n", 1127 rte_crypto_auth_algorithm_strings[opts->auth_algo]); 1128 printf("# auth operation: %s\n", 1129 rte_crypto_auth_operation_strings[opts->auth_op]); 1130 printf("# auth key size: %u\n", opts->auth_key_sz); 1131 printf("# auth iv size: %u\n", opts->auth_iv_sz); 1132 printf("# auth digest size: %u\n", opts->digest_sz); 1133 printf("#\n"); 1134 } 1135 1136 if (opts->op_type == CPERF_CIPHER_ONLY || 1137 opts->op_type == CPERF_CIPHER_THEN_AUTH || 1138 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 1139 printf("# cipher algorithm: %s\n", 1140 rte_crypto_cipher_algorithm_strings[opts->cipher_algo]); 1141 printf("# cipher operation: %s\n", 1142 rte_crypto_cipher_operation_strings[opts->cipher_op]); 1143 printf("# cipher key size: %u\n", opts->cipher_key_sz); 1144 printf("# cipher iv size: %u\n", opts->cipher_iv_sz); 1145 printf("#\n"); 1146 } 1147 1148 if (opts->op_type == CPERF_AEAD) { 1149 printf("# aead algorithm: %s\n", 1150 rte_crypto_aead_algorithm_strings[opts->aead_algo]); 1151 printf("# aead operation: %s\n", 1152 rte_crypto_aead_operation_strings[opts->aead_op]); 1153 printf("# aead key size: %u\n", opts->aead_key_sz); 1154 printf("# aead iv size: %u\n", opts->aead_iv_sz); 1155 printf("# aead digest size: %u\n", opts->digest_sz); 1156 printf("# aead aad size: %u\n", opts->aead_aad_sz); 1157 printf("#\n"); 1158 } 1159 } 1160