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