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-cyclecount :" 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 if (test_name == NULL) { 510 RTE_LOG(ERR, USER1, "Failed to rte zmalloc with size: %zu\n", 511 strlen(arg) + 3); 512 return -1; 513 } 514 515 snprintf(test_name, strlen(arg) + 3, "[%s]", arg); 516 opts->test_name = test_name; 517 518 return 0; 519 } 520 521 static int 522 parse_silent(struct cperf_options *opts, 523 const char *arg __rte_unused) 524 { 525 opts->silent = 1; 526 527 return 0; 528 } 529 530 static int 531 parse_cipher_algo(struct cperf_options *opts, const char *arg) 532 { 533 534 enum rte_crypto_cipher_algorithm cipher_algo; 535 536 if (rte_cryptodev_get_cipher_algo_enum(&cipher_algo, arg) < 0) { 537 RTE_LOG(ERR, USER1, "Invalid cipher algorithm specified\n"); 538 return -1; 539 } 540 541 opts->cipher_algo = cipher_algo; 542 543 return 0; 544 } 545 546 static int 547 parse_cipher_op(struct cperf_options *opts, const char *arg) 548 { 549 struct name_id_map cipher_op_namemap[] = { 550 { 551 rte_crypto_cipher_operation_strings 552 [RTE_CRYPTO_CIPHER_OP_ENCRYPT], 553 RTE_CRYPTO_CIPHER_OP_ENCRYPT }, 554 { 555 rte_crypto_cipher_operation_strings 556 [RTE_CRYPTO_CIPHER_OP_DECRYPT], 557 RTE_CRYPTO_CIPHER_OP_DECRYPT 558 } 559 }; 560 561 int id = get_str_key_id_mapping(cipher_op_namemap, 562 RTE_DIM(cipher_op_namemap), arg); 563 if (id < 0) { 564 RTE_LOG(ERR, USER1, "Invalid cipher operation specified\n"); 565 return -1; 566 } 567 568 opts->cipher_op = (enum rte_crypto_cipher_operation)id; 569 570 return 0; 571 } 572 573 static int 574 parse_cipher_key_sz(struct cperf_options *opts, const char *arg) 575 { 576 return parse_uint16_t(&opts->cipher_key_sz, arg); 577 } 578 579 static int 580 parse_cipher_iv_sz(struct cperf_options *opts, const char *arg) 581 { 582 return parse_uint16_t(&opts->cipher_iv_sz, arg); 583 } 584 585 static int 586 parse_auth_algo(struct cperf_options *opts, const char *arg) 587 { 588 enum rte_crypto_auth_algorithm auth_algo; 589 590 if (rte_cryptodev_get_auth_algo_enum(&auth_algo, arg) < 0) { 591 RTE_LOG(ERR, USER1, "Invalid authentication algorithm specified\n"); 592 return -1; 593 } 594 595 opts->auth_algo = auth_algo; 596 597 return 0; 598 } 599 600 static int 601 parse_auth_op(struct cperf_options *opts, const char *arg) 602 { 603 struct name_id_map auth_op_namemap[] = { 604 { 605 rte_crypto_auth_operation_strings 606 [RTE_CRYPTO_AUTH_OP_GENERATE], 607 RTE_CRYPTO_AUTH_OP_GENERATE }, 608 { 609 rte_crypto_auth_operation_strings 610 [RTE_CRYPTO_AUTH_OP_VERIFY], 611 RTE_CRYPTO_AUTH_OP_VERIFY 612 } 613 }; 614 615 int id = get_str_key_id_mapping(auth_op_namemap, 616 RTE_DIM(auth_op_namemap), arg); 617 if (id < 0) { 618 RTE_LOG(ERR, USER1, "invalid authentication operation specified" 619 "\n"); 620 return -1; 621 } 622 623 opts->auth_op = (enum rte_crypto_auth_operation)id; 624 625 return 0; 626 } 627 628 static int 629 parse_auth_key_sz(struct cperf_options *opts, const char *arg) 630 { 631 return parse_uint16_t(&opts->auth_key_sz, arg); 632 } 633 634 static int 635 parse_digest_sz(struct cperf_options *opts, const char *arg) 636 { 637 return parse_uint16_t(&opts->digest_sz, arg); 638 } 639 640 #ifdef RTE_LIB_SECURITY 641 static int 642 parse_pdcp_sn_sz(struct cperf_options *opts, const char *arg) 643 { 644 uint32_t val = 0; 645 int ret = parse_uint32_t(&val, arg); 646 647 if (ret < 0) 648 return ret; 649 650 if (val != RTE_SECURITY_PDCP_SN_SIZE_5 && 651 val != RTE_SECURITY_PDCP_SN_SIZE_7 && 652 val != RTE_SECURITY_PDCP_SN_SIZE_12 && 653 val != RTE_SECURITY_PDCP_SN_SIZE_15 && 654 val != RTE_SECURITY_PDCP_SN_SIZE_18) { 655 printf("\nInvalid pdcp SN size: %u\n", val); 656 return -ERANGE; 657 } 658 opts->pdcp_sn_sz = val; 659 660 return 0; 661 } 662 663 const char *cperf_pdcp_domain_strs[] = { 664 [RTE_SECURITY_PDCP_MODE_CONTROL] = "control", 665 [RTE_SECURITY_PDCP_MODE_DATA] = "data" 666 }; 667 668 static int 669 parse_pdcp_domain(struct cperf_options *opts, const char *arg) 670 { 671 struct name_id_map pdcp_domain_namemap[] = { 672 { 673 cperf_pdcp_domain_strs 674 [RTE_SECURITY_PDCP_MODE_CONTROL], 675 RTE_SECURITY_PDCP_MODE_CONTROL }, 676 { 677 cperf_pdcp_domain_strs 678 [RTE_SECURITY_PDCP_MODE_DATA], 679 RTE_SECURITY_PDCP_MODE_DATA 680 } 681 }; 682 683 int id = get_str_key_id_mapping(pdcp_domain_namemap, 684 RTE_DIM(pdcp_domain_namemap), arg); 685 if (id < 0) { 686 RTE_LOG(ERR, USER1, "invalid pdcp domain specified" 687 "\n"); 688 return -1; 689 } 690 691 opts->pdcp_domain = (enum rte_security_pdcp_domain)id; 692 693 return 0; 694 } 695 696 static int 697 parse_pdcp_ses_hfn_en(struct cperf_options *opts, const char *arg __rte_unused) 698 { 699 opts->pdcp_ses_hfn_en = 1; 700 return 0; 701 } 702 703 static int 704 parse_docsis_hdr_sz(struct cperf_options *opts, const char *arg) 705 { 706 return parse_uint16_t(&opts->docsis_hdr_sz, arg); 707 } 708 #endif 709 710 static int 711 parse_auth_iv_sz(struct cperf_options *opts, const char *arg) 712 { 713 return parse_uint16_t(&opts->auth_iv_sz, arg); 714 } 715 716 static int 717 parse_aead_algo(struct cperf_options *opts, const char *arg) 718 { 719 enum rte_crypto_aead_algorithm aead_algo; 720 721 if (rte_cryptodev_get_aead_algo_enum(&aead_algo, arg) < 0) { 722 RTE_LOG(ERR, USER1, "Invalid AEAD algorithm specified\n"); 723 return -1; 724 } 725 726 opts->aead_algo = aead_algo; 727 728 return 0; 729 } 730 731 static int 732 parse_aead_op(struct cperf_options *opts, const char *arg) 733 { 734 struct name_id_map aead_op_namemap[] = { 735 { 736 rte_crypto_aead_operation_strings 737 [RTE_CRYPTO_AEAD_OP_ENCRYPT], 738 RTE_CRYPTO_AEAD_OP_ENCRYPT }, 739 { 740 rte_crypto_aead_operation_strings 741 [RTE_CRYPTO_AEAD_OP_DECRYPT], 742 RTE_CRYPTO_AEAD_OP_DECRYPT 743 } 744 }; 745 746 int id = get_str_key_id_mapping(aead_op_namemap, 747 RTE_DIM(aead_op_namemap), arg); 748 if (id < 0) { 749 RTE_LOG(ERR, USER1, "invalid AEAD operation specified" 750 "\n"); 751 return -1; 752 } 753 754 opts->aead_op = (enum rte_crypto_aead_operation)id; 755 756 return 0; 757 } 758 759 static int 760 parse_aead_key_sz(struct cperf_options *opts, const char *arg) 761 { 762 return parse_uint16_t(&opts->aead_key_sz, arg); 763 } 764 765 static int 766 parse_aead_iv_sz(struct cperf_options *opts, const char *arg) 767 { 768 return parse_uint16_t(&opts->aead_iv_sz, arg); 769 } 770 771 static int 772 parse_aead_aad_sz(struct cperf_options *opts, const char *arg) 773 { 774 return parse_uint16_t(&opts->aead_aad_sz, arg); 775 } 776 777 static int 778 parse_csv_friendly(struct cperf_options *opts, const char *arg __rte_unused) 779 { 780 opts->csv = 1; 781 opts->silent = 1; 782 return 0; 783 } 784 785 static int 786 parse_pmd_cyclecount_delay_ms(struct cperf_options *opts, 787 const char *arg) 788 { 789 int ret = parse_uint32_t(&opts->pmdcc_delay, arg); 790 791 if (ret) { 792 RTE_LOG(ERR, USER1, "failed to parse pmd-cyclecount delay\n"); 793 return -1; 794 } 795 796 return 0; 797 } 798 799 typedef int (*option_parser_t)(struct cperf_options *opts, 800 const char *arg); 801 802 struct long_opt_parser { 803 const char *lgopt_name; 804 option_parser_t parser_fn; 805 806 }; 807 808 static struct option lgopts[] = { 809 810 { CPERF_PTEST_TYPE, required_argument, 0, 0 }, 811 812 { CPERF_POOL_SIZE, required_argument, 0, 0 }, 813 { CPERF_TOTAL_OPS, required_argument, 0, 0 }, 814 { CPERF_BURST_SIZE, required_argument, 0, 0 }, 815 { CPERF_BUFFER_SIZE, required_argument, 0, 0 }, 816 { CPERF_SEGMENT_SIZE, required_argument, 0, 0 }, 817 { CPERF_DESC_NB, required_argument, 0, 0 }, 818 819 { CPERF_IMIX, required_argument, 0, 0 }, 820 { CPERF_DEVTYPE, required_argument, 0, 0 }, 821 { CPERF_OPTYPE, required_argument, 0, 0 }, 822 823 { CPERF_SILENT, no_argument, 0, 0 }, 824 { CPERF_SESSIONLESS, no_argument, 0, 0 }, 825 { CPERF_OUT_OF_PLACE, no_argument, 0, 0 }, 826 { CPERF_TEST_FILE, required_argument, 0, 0 }, 827 { CPERF_TEST_NAME, required_argument, 0, 0 }, 828 829 { CPERF_CIPHER_ALGO, required_argument, 0, 0 }, 830 { CPERF_CIPHER_OP, required_argument, 0, 0 }, 831 832 { CPERF_CIPHER_KEY_SZ, required_argument, 0, 0 }, 833 { CPERF_CIPHER_IV_SZ, required_argument, 0, 0 }, 834 835 { CPERF_AUTH_ALGO, required_argument, 0, 0 }, 836 { CPERF_AUTH_OP, required_argument, 0, 0 }, 837 838 { CPERF_AUTH_KEY_SZ, required_argument, 0, 0 }, 839 { CPERF_AUTH_IV_SZ, required_argument, 0, 0 }, 840 841 { CPERF_AEAD_ALGO, required_argument, 0, 0 }, 842 { CPERF_AEAD_OP, required_argument, 0, 0 }, 843 844 { CPERF_AEAD_KEY_SZ, required_argument, 0, 0 }, 845 { CPERF_AEAD_AAD_SZ, required_argument, 0, 0 }, 846 { CPERF_AEAD_IV_SZ, required_argument, 0, 0 }, 847 848 { CPERF_DIGEST_SZ, required_argument, 0, 0 }, 849 850 #ifdef RTE_LIB_SECURITY 851 { CPERF_PDCP_SN_SZ, required_argument, 0, 0 }, 852 { CPERF_PDCP_DOMAIN, required_argument, 0, 0 }, 853 { CPERF_PDCP_SES_HFN_EN, no_argument, 0, 0 }, 854 { CPERF_DOCSIS_HDR_SZ, required_argument, 0, 0 }, 855 #endif 856 { CPERF_CSV, no_argument, 0, 0}, 857 858 { CPERF_PMDCC_DELAY_MS, required_argument, 0, 0 }, 859 860 { NULL, 0, 0, 0 } 861 }; 862 863 void 864 cperf_options_default(struct cperf_options *opts) 865 { 866 opts->test = CPERF_TEST_TYPE_THROUGHPUT; 867 868 opts->pool_sz = 8192; 869 opts->total_ops = 10000000; 870 opts->nb_descriptors = 2048; 871 872 opts->buffer_size_list[0] = 64; 873 opts->buffer_size_count = 1; 874 opts->max_buffer_size = 64; 875 opts->min_buffer_size = 64; 876 opts->inc_buffer_size = 0; 877 878 opts->burst_size_list[0] = 32; 879 opts->burst_size_count = 1; 880 opts->max_burst_size = 32; 881 opts->min_burst_size = 32; 882 opts->inc_burst_size = 0; 883 884 /* 885 * Will be parsed from command line or set to 886 * maximum buffer size + digest, later 887 */ 888 opts->segment_sz = 0; 889 890 opts->imix_distribution_count = 0; 891 strncpy(opts->device_type, "crypto_aesni_mb", 892 sizeof(opts->device_type)); 893 opts->nb_qps = 1; 894 895 opts->op_type = CPERF_CIPHER_THEN_AUTH; 896 897 opts->silent = 0; 898 opts->test_file = NULL; 899 opts->test_name = NULL; 900 opts->sessionless = 0; 901 opts->out_of_place = 0; 902 opts->csv = 0; 903 904 opts->cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC; 905 opts->cipher_op = RTE_CRYPTO_CIPHER_OP_ENCRYPT; 906 opts->cipher_key_sz = 16; 907 opts->cipher_iv_sz = 16; 908 909 opts->auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC; 910 opts->auth_op = RTE_CRYPTO_AUTH_OP_GENERATE; 911 912 opts->auth_key_sz = 64; 913 opts->auth_iv_sz = 0; 914 915 opts->aead_key_sz = 0; 916 opts->aead_iv_sz = 0; 917 opts->aead_aad_sz = 0; 918 919 opts->digest_sz = 12; 920 921 opts->pmdcc_delay = 0; 922 #ifdef RTE_LIB_SECURITY 923 opts->pdcp_sn_sz = 12; 924 opts->pdcp_domain = RTE_SECURITY_PDCP_MODE_CONTROL; 925 opts->pdcp_ses_hfn_en = 0; 926 opts->docsis_hdr_sz = 17; 927 #endif 928 } 929 930 static int 931 cperf_opts_parse_long(int opt_idx, struct cperf_options *opts) 932 { 933 struct long_opt_parser parsermap[] = { 934 { CPERF_PTEST_TYPE, parse_cperf_test_type }, 935 { CPERF_SILENT, parse_silent }, 936 { CPERF_POOL_SIZE, parse_pool_sz }, 937 { CPERF_TOTAL_OPS, parse_total_ops }, 938 { CPERF_BURST_SIZE, parse_burst_sz }, 939 { CPERF_BUFFER_SIZE, parse_buffer_sz }, 940 { CPERF_SEGMENT_SIZE, parse_segment_sz }, 941 { CPERF_DESC_NB, parse_desc_nb }, 942 { CPERF_DEVTYPE, parse_device_type }, 943 { CPERF_OPTYPE, parse_op_type }, 944 { CPERF_SESSIONLESS, parse_sessionless }, 945 { CPERF_OUT_OF_PLACE, parse_out_of_place }, 946 { CPERF_IMIX, parse_imix }, 947 { CPERF_TEST_FILE, parse_test_file }, 948 { CPERF_TEST_NAME, parse_test_name }, 949 { CPERF_CIPHER_ALGO, parse_cipher_algo }, 950 { CPERF_CIPHER_OP, parse_cipher_op }, 951 { CPERF_CIPHER_KEY_SZ, parse_cipher_key_sz }, 952 { CPERF_CIPHER_IV_SZ, parse_cipher_iv_sz }, 953 { CPERF_AUTH_ALGO, parse_auth_algo }, 954 { CPERF_AUTH_OP, parse_auth_op }, 955 { CPERF_AUTH_KEY_SZ, parse_auth_key_sz }, 956 { CPERF_AUTH_IV_SZ, parse_auth_iv_sz }, 957 { CPERF_AEAD_ALGO, parse_aead_algo }, 958 { CPERF_AEAD_OP, parse_aead_op }, 959 { CPERF_AEAD_KEY_SZ, parse_aead_key_sz }, 960 { CPERF_AEAD_IV_SZ, parse_aead_iv_sz }, 961 { CPERF_AEAD_AAD_SZ, parse_aead_aad_sz }, 962 { CPERF_DIGEST_SZ, parse_digest_sz }, 963 #ifdef RTE_LIB_SECURITY 964 { CPERF_PDCP_SN_SZ, parse_pdcp_sn_sz }, 965 { CPERF_PDCP_DOMAIN, parse_pdcp_domain }, 966 { CPERF_PDCP_SES_HFN_EN, parse_pdcp_ses_hfn_en }, 967 { CPERF_DOCSIS_HDR_SZ, parse_docsis_hdr_sz }, 968 #endif 969 { CPERF_CSV, parse_csv_friendly}, 970 { CPERF_PMDCC_DELAY_MS, parse_pmd_cyclecount_delay_ms}, 971 }; 972 unsigned int i; 973 974 for (i = 0; i < RTE_DIM(parsermap); i++) { 975 if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name, 976 strlen(lgopts[opt_idx].name)) == 0) 977 return parsermap[i].parser_fn(opts, optarg); 978 } 979 980 return -EINVAL; 981 } 982 983 int 984 cperf_options_parse(struct cperf_options *options, int argc, char **argv) 985 { 986 int opt, retval, opt_idx; 987 988 while ((opt = getopt_long(argc, argv, "h", lgopts, &opt_idx)) != EOF) { 989 switch (opt) { 990 case 'h': 991 usage(argv[0]); 992 exit(EXIT_SUCCESS); 993 break; 994 /* long options */ 995 case 0: 996 retval = cperf_opts_parse_long(opt_idx, options); 997 if (retval != 0) 998 return retval; 999 1000 break; 1001 1002 default: 1003 usage(argv[0]); 1004 return -EINVAL; 1005 } 1006 } 1007 1008 return 0; 1009 } 1010 1011 static int 1012 check_cipher_buffer_length(struct cperf_options *options) 1013 { 1014 uint32_t buffer_size, buffer_size_idx = 0; 1015 1016 if (options->cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC || 1017 options->cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB) { 1018 if (options->inc_buffer_size != 0) 1019 buffer_size = options->min_buffer_size; 1020 else 1021 buffer_size = options->buffer_size_list[0]; 1022 1023 while (buffer_size <= options->max_buffer_size) { 1024 if ((buffer_size % AES_BLOCK_SIZE) != 0) { 1025 RTE_LOG(ERR, USER1, "Some of the buffer sizes are " 1026 "not suitable for the algorithm selected\n"); 1027 return -EINVAL; 1028 } 1029 1030 if (options->inc_buffer_size != 0) 1031 buffer_size += options->inc_buffer_size; 1032 else { 1033 if (++buffer_size_idx == options->buffer_size_count) 1034 break; 1035 buffer_size = options->buffer_size_list[buffer_size_idx]; 1036 } 1037 1038 } 1039 } 1040 1041 if (options->cipher_algo == RTE_CRYPTO_CIPHER_DES_CBC || 1042 options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_CBC || 1043 options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_ECB) { 1044 if (options->inc_buffer_size != 0) 1045 buffer_size = options->min_buffer_size; 1046 else 1047 buffer_size = options->buffer_size_list[0]; 1048 1049 while (buffer_size <= options->max_buffer_size) { 1050 if ((buffer_size % DES_BLOCK_SIZE) != 0) { 1051 RTE_LOG(ERR, USER1, "Some of the buffer sizes are " 1052 "not suitable for the algorithm selected\n"); 1053 return -EINVAL; 1054 } 1055 1056 if (options->inc_buffer_size != 0) 1057 buffer_size += options->inc_buffer_size; 1058 else { 1059 if (++buffer_size_idx == options->buffer_size_count) 1060 break; 1061 buffer_size = options->buffer_size_list[buffer_size_idx]; 1062 } 1063 1064 } 1065 } 1066 1067 return 0; 1068 } 1069 1070 #ifdef RTE_LIB_SECURITY 1071 static int 1072 check_docsis_buffer_length(struct cperf_options *options) 1073 { 1074 uint32_t buffer_size, buffer_size_idx = 0; 1075 1076 if (options->inc_buffer_size != 0) 1077 buffer_size = options->min_buffer_size; 1078 else 1079 buffer_size = options->buffer_size_list[0]; 1080 1081 while (buffer_size <= options->max_buffer_size) { 1082 if (buffer_size < (uint32_t)(options->docsis_hdr_sz + 1083 RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN)) { 1084 RTE_LOG(ERR, USER1, "Some of the buffer sizes are not " 1085 "valid for DOCSIS\n"); 1086 return -EINVAL; 1087 } 1088 1089 if (options->inc_buffer_size != 0) 1090 buffer_size += options->inc_buffer_size; 1091 else { 1092 if (++buffer_size_idx == options->buffer_size_count) 1093 break; 1094 buffer_size = 1095 options->buffer_size_list[buffer_size_idx]; 1096 } 1097 } 1098 1099 return 0; 1100 } 1101 #endif 1102 1103 int 1104 cperf_options_check(struct cperf_options *options) 1105 { 1106 if (options->op_type == CPERF_CIPHER_ONLY || 1107 options->op_type == CPERF_DOCSIS) 1108 options->digest_sz = 0; 1109 1110 if (options->out_of_place && 1111 options->segment_sz <= options->max_buffer_size) { 1112 RTE_LOG(ERR, USER1, "Out of place mode can only work " 1113 "with non segmented buffers\n"); 1114 return -EINVAL; 1115 } 1116 1117 /* 1118 * If segment size is not set, assume only one segment, 1119 * big enough to contain the largest buffer and the digest 1120 */ 1121 if (options->segment_sz == 0) 1122 options->segment_sz = options->max_buffer_size + 1123 options->digest_sz; 1124 1125 if (options->segment_sz < options->digest_sz) { 1126 RTE_LOG(ERR, USER1, 1127 "Segment size should be at least " 1128 "the size of the digest\n"); 1129 return -EINVAL; 1130 } 1131 1132 if ((options->imix_distribution_count != 0) && 1133 (options->imix_distribution_count != 1134 options->buffer_size_count)) { 1135 RTE_LOG(ERR, USER1, "IMIX distribution must have the same " 1136 "number of buffer sizes\n"); 1137 return -EINVAL; 1138 } 1139 1140 if (options->test == CPERF_TEST_TYPE_VERIFY && 1141 options->test_file == NULL) { 1142 RTE_LOG(ERR, USER1, "Define path to the file with test" 1143 " vectors.\n"); 1144 return -EINVAL; 1145 } 1146 1147 if (options->test == CPERF_TEST_TYPE_VERIFY && 1148 options->op_type != CPERF_CIPHER_ONLY && 1149 options->test_name == NULL) { 1150 RTE_LOG(ERR, USER1, "Define test name to get the correct digest" 1151 " from the test vectors.\n"); 1152 return -EINVAL; 1153 } 1154 1155 if (options->test_name != NULL && options->test_file == NULL) { 1156 RTE_LOG(ERR, USER1, "Define path to the file with test" 1157 " vectors.\n"); 1158 return -EINVAL; 1159 } 1160 1161 if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY && 1162 options->test_file == NULL) { 1163 RTE_LOG(ERR, USER1, "Define path to the file with test" 1164 " vectors.\n"); 1165 return -EINVAL; 1166 } 1167 1168 if (options->test == CPERF_TEST_TYPE_VERIFY && 1169 (options->inc_buffer_size != 0 || 1170 options->buffer_size_count > 1)) { 1171 RTE_LOG(ERR, USER1, "Only one buffer size is allowed when " 1172 "using the verify test.\n"); 1173 return -EINVAL; 1174 } 1175 1176 if (options->test == CPERF_TEST_TYPE_VERIFY && 1177 (options->inc_burst_size != 0 || 1178 options->burst_size_count > 1)) { 1179 RTE_LOG(ERR, USER1, "Only one burst size is allowed when " 1180 "using the verify test.\n"); 1181 return -EINVAL; 1182 } 1183 1184 if (options->test == CPERF_TEST_TYPE_PMDCC && 1185 options->pool_sz < options->nb_descriptors) { 1186 RTE_LOG(ERR, USER1, "For pmd cyclecount benchmarks, pool size " 1187 "must be equal or greater than the number of " 1188 "cryptodev descriptors.\n"); 1189 return -EINVAL; 1190 } 1191 1192 if (options->test == CPERF_TEST_TYPE_VERIFY && 1193 options->imix_distribution_count > 0) { 1194 RTE_LOG(ERR, USER1, "IMIX is not allowed when " 1195 "using the verify test.\n"); 1196 return -EINVAL; 1197 } 1198 1199 if (options->op_type == CPERF_CIPHER_THEN_AUTH) { 1200 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_ENCRYPT && 1201 options->auth_op != 1202 RTE_CRYPTO_AUTH_OP_GENERATE) { 1203 RTE_LOG(ERR, USER1, "Option cipher then auth must use" 1204 " options: encrypt and generate.\n"); 1205 return -EINVAL; 1206 } 1207 } else if (options->op_type == CPERF_AUTH_THEN_CIPHER) { 1208 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_DECRYPT && 1209 options->auth_op != 1210 RTE_CRYPTO_AUTH_OP_VERIFY) { 1211 RTE_LOG(ERR, USER1, "Option auth then cipher must use" 1212 " options: decrypt and verify.\n"); 1213 return -EINVAL; 1214 } 1215 } 1216 1217 if (options->op_type == CPERF_CIPHER_ONLY || 1218 options->op_type == CPERF_CIPHER_THEN_AUTH || 1219 options->op_type == CPERF_AUTH_THEN_CIPHER) { 1220 if (check_cipher_buffer_length(options) < 0) 1221 return -EINVAL; 1222 } 1223 1224 #ifdef RTE_LIB_SECURITY 1225 if (options->op_type == CPERF_DOCSIS) { 1226 if (check_docsis_buffer_length(options) < 0) 1227 return -EINVAL; 1228 } 1229 #endif 1230 1231 return 0; 1232 } 1233 1234 void 1235 cperf_options_dump(struct cperf_options *opts) 1236 { 1237 uint8_t size_idx; 1238 1239 printf("# Crypto Performance Application Options:\n"); 1240 printf("#\n"); 1241 printf("# cperf test: %s\n", cperf_test_type_strs[opts->test]); 1242 printf("#\n"); 1243 printf("# size of crypto op / mbuf pool: %u\n", opts->pool_sz); 1244 printf("# total number of ops: %u\n", opts->total_ops); 1245 if (opts->inc_buffer_size != 0) { 1246 printf("# buffer size:\n"); 1247 printf("#\t min: %u\n", opts->min_buffer_size); 1248 printf("#\t max: %u\n", opts->max_buffer_size); 1249 printf("#\t inc: %u\n", opts->inc_buffer_size); 1250 } else { 1251 printf("# buffer sizes: "); 1252 for (size_idx = 0; size_idx < opts->buffer_size_count; size_idx++) 1253 printf("%u ", opts->buffer_size_list[size_idx]); 1254 printf("\n"); 1255 } 1256 if (opts->inc_burst_size != 0) { 1257 printf("# burst size:\n"); 1258 printf("#\t min: %u\n", opts->min_burst_size); 1259 printf("#\t max: %u\n", opts->max_burst_size); 1260 printf("#\t inc: %u\n", opts->inc_burst_size); 1261 } else { 1262 printf("# burst sizes: "); 1263 for (size_idx = 0; size_idx < opts->burst_size_count; size_idx++) 1264 printf("%u ", opts->burst_size_list[size_idx]); 1265 printf("\n"); 1266 } 1267 printf("\n# segment size: %u\n", opts->segment_sz); 1268 printf("#\n"); 1269 printf("# cryptodev type: %s\n", opts->device_type); 1270 printf("#\n"); 1271 printf("# number of queue pairs per device: %u\n", opts->nb_qps); 1272 printf("# crypto operation: %s\n", cperf_op_type_strs[opts->op_type]); 1273 printf("# sessionless: %s\n", opts->sessionless ? "yes" : "no"); 1274 printf("# out of place: %s\n", opts->out_of_place ? "yes" : "no"); 1275 if (opts->test == CPERF_TEST_TYPE_PMDCC) 1276 printf("# inter-burst delay: %u ms\n", opts->pmdcc_delay); 1277 1278 printf("#\n"); 1279 1280 if (opts->op_type == CPERF_AUTH_ONLY || 1281 opts->op_type == CPERF_CIPHER_THEN_AUTH || 1282 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 1283 printf("# auth algorithm: %s\n", 1284 rte_crypto_auth_algorithm_strings[opts->auth_algo]); 1285 printf("# auth operation: %s\n", 1286 rte_crypto_auth_operation_strings[opts->auth_op]); 1287 printf("# auth key size: %u\n", opts->auth_key_sz); 1288 printf("# auth iv size: %u\n", opts->auth_iv_sz); 1289 printf("# auth digest size: %u\n", opts->digest_sz); 1290 printf("#\n"); 1291 } 1292 1293 if (opts->op_type == CPERF_CIPHER_ONLY || 1294 opts->op_type == CPERF_CIPHER_THEN_AUTH || 1295 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 1296 printf("# cipher algorithm: %s\n", 1297 rte_crypto_cipher_algorithm_strings[opts->cipher_algo]); 1298 printf("# cipher operation: %s\n", 1299 rte_crypto_cipher_operation_strings[opts->cipher_op]); 1300 printf("# cipher key size: %u\n", opts->cipher_key_sz); 1301 printf("# cipher iv size: %u\n", opts->cipher_iv_sz); 1302 printf("#\n"); 1303 } 1304 1305 if (opts->op_type == CPERF_AEAD) { 1306 printf("# aead algorithm: %s\n", 1307 rte_crypto_aead_algorithm_strings[opts->aead_algo]); 1308 printf("# aead operation: %s\n", 1309 rte_crypto_aead_operation_strings[opts->aead_op]); 1310 printf("# aead key size: %u\n", opts->aead_key_sz); 1311 printf("# aead iv size: %u\n", opts->aead_iv_sz); 1312 printf("# aead digest size: %u\n", opts->digest_sz); 1313 printf("# aead aad size: %u\n", opts->aead_aad_sz); 1314 printf("#\n"); 1315 } 1316 1317 #ifdef RTE_LIB_SECURITY 1318 if (opts->op_type == CPERF_DOCSIS) { 1319 printf("# docsis header size: %u\n", opts->docsis_hdr_sz); 1320 printf("#\n"); 1321 } 1322 #endif 1323 } 1324