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