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