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