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