1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * * Neither the name of Intel Corporation nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <getopt.h> 34 #include <unistd.h> 35 36 #include <rte_cryptodev.h> 37 #include <rte_malloc.h> 38 39 #include "cperf_options.h" 40 41 #define AES_BLOCK_SIZE 16 42 #define DES_BLOCK_SIZE 8 43 44 struct name_id_map { 45 const char *name; 46 uint32_t id; 47 }; 48 49 static void 50 usage(char *progname) 51 { 52 printf("%s [EAL options] --\n" 53 " --silent: disable options dump\n" 54 " --ptest throughput / latency / verify / pmd-cycleount :" 55 " set test type\n" 56 " --pool_sz N: set the number of crypto ops/mbufs allocated\n" 57 " --total-ops N: set the number of total operations performed\n" 58 " --burst-sz N: set the number of packets per burst\n" 59 " --buffer-sz N: set the size of a single packet\n" 60 " --segment-sz N: set the size of the segment to use\n" 61 " --desc-nb N: set number of descriptors for each crypto device\n" 62 " --devtype TYPE: set crypto device type to use\n" 63 " --optype cipher-only / auth-only / cipher-then-auth /\n" 64 " auth-then-cipher / aead : set operation type\n" 65 " --sessionless: enable session-less crypto operations\n" 66 " --out-of-place: enable out-of-place crypto operations\n" 67 " --test-file NAME: set the test vector file path\n" 68 " --test-name NAME: set specific test name section in test file\n" 69 " --cipher-algo ALGO: set cipher algorithm\n" 70 " --cipher-op encrypt / decrypt: set the cipher operation\n" 71 " --cipher-key-sz N: set the cipher key size\n" 72 " --cipher-iv-sz N: set the cipher IV size\n" 73 " --auth-algo ALGO: set auth algorithm\n" 74 " --auth-op generate / verify: set the auth operation\n" 75 " --auth-key-sz N: set the auth key size\n" 76 " --auth-iv-sz N: set the auth IV size\n" 77 " --aead-algo ALGO: set AEAD algorithm\n" 78 " --aead-op encrypt / decrypt: set the AEAD operation\n" 79 " --aead-key-sz N: set the AEAD key size\n" 80 " --aead-iv-sz N: set the AEAD IV size\n" 81 " --aead-aad-sz N: set the AEAD AAD size\n" 82 " --digest-sz N: set the digest size\n" 83 " --pmd-cyclecount-delay-ms N: set delay between enqueue\n" 84 " and dequeue in pmd-cyclecount benchmarking mode\n" 85 " --csv-friendly: enable test result output CSV friendly\n" 86 " -h: prints this help\n", 87 progname); 88 } 89 90 static int 91 get_str_key_id_mapping(struct name_id_map *map, unsigned int map_len, 92 const char *str_key) 93 { 94 unsigned int i; 95 96 for (i = 0; i < map_len; i++) { 97 98 if (strcmp(str_key, map[i].name) == 0) 99 return map[i].id; 100 } 101 102 return -1; 103 } 104 105 static int 106 parse_cperf_test_type(struct cperf_options *opts, const char *arg) 107 { 108 struct name_id_map cperftest_namemap[] = { 109 { 110 cperf_test_type_strs[CPERF_TEST_TYPE_THROUGHPUT], 111 CPERF_TEST_TYPE_THROUGHPUT 112 }, 113 { 114 cperf_test_type_strs[CPERF_TEST_TYPE_VERIFY], 115 CPERF_TEST_TYPE_VERIFY 116 }, 117 { 118 cperf_test_type_strs[CPERF_TEST_TYPE_LATENCY], 119 CPERF_TEST_TYPE_LATENCY 120 }, 121 { 122 cperf_test_type_strs[CPERF_TEST_TYPE_PMDCC], 123 CPERF_TEST_TYPE_PMDCC 124 } 125 }; 126 127 int id = get_str_key_id_mapping( 128 (struct name_id_map *)cperftest_namemap, 129 RTE_DIM(cperftest_namemap), arg); 130 if (id < 0) { 131 RTE_LOG(ERR, USER1, "failed to parse test type"); 132 return -1; 133 } 134 135 opts->test = (enum cperf_perf_test_type)id; 136 137 return 0; 138 } 139 140 static int 141 parse_uint32_t(uint32_t *value, const char *arg) 142 { 143 char *end = NULL; 144 unsigned long n = strtoul(arg, &end, 10); 145 146 if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0')) 147 return -1; 148 149 if (n > UINT32_MAX) 150 return -ERANGE; 151 152 *value = (uint32_t) n; 153 154 return 0; 155 } 156 157 static int 158 parse_uint16_t(uint16_t *value, const char *arg) 159 { 160 uint32_t val = 0; 161 int ret = parse_uint32_t(&val, arg); 162 163 if (ret < 0) 164 return ret; 165 166 if (val > UINT16_MAX) 167 return -ERANGE; 168 169 *value = (uint16_t) val; 170 171 return 0; 172 } 173 174 static int 175 parse_range(const char *arg, uint32_t *min, uint32_t *max, uint32_t *inc) 176 { 177 char *token; 178 uint32_t number; 179 180 char *copy_arg = strdup(arg); 181 182 if (copy_arg == NULL) 183 return -1; 184 185 errno = 0; 186 token = strtok(copy_arg, ":"); 187 188 /* Parse minimum value */ 189 if (token != NULL) { 190 number = strtoul(token, NULL, 10); 191 192 if (errno == EINVAL || errno == ERANGE || 193 number == 0) 194 goto err_range; 195 196 *min = number; 197 } else 198 goto err_range; 199 200 token = strtok(NULL, ":"); 201 202 /* Parse increment value */ 203 if (token != NULL) { 204 number = strtoul(token, NULL, 10); 205 206 if (errno == EINVAL || errno == ERANGE || 207 number == 0) 208 goto err_range; 209 210 *inc = number; 211 } else 212 goto err_range; 213 214 token = strtok(NULL, ":"); 215 216 /* Parse maximum value */ 217 if (token != NULL) { 218 number = strtoul(token, NULL, 10); 219 220 if (errno == EINVAL || errno == ERANGE || 221 number == 0 || 222 number < *min) 223 goto err_range; 224 225 *max = number; 226 } else 227 goto err_range; 228 229 if (strtok(NULL, ":") != NULL) 230 goto err_range; 231 232 free(copy_arg); 233 return 0; 234 235 err_range: 236 free(copy_arg); 237 return -1; 238 } 239 240 static int 241 parse_list(const char *arg, uint32_t *list, uint32_t *min, uint32_t *max) 242 { 243 char *token; 244 uint32_t number; 245 uint8_t count = 0; 246 247 char *copy_arg = strdup(arg); 248 249 if (copy_arg == NULL) 250 return -1; 251 252 errno = 0; 253 token = strtok(copy_arg, ","); 254 255 /* Parse first value */ 256 if (token != NULL) { 257 number = strtoul(token, NULL, 10); 258 259 if (errno == EINVAL || errno == ERANGE || 260 number == 0) 261 goto err_list; 262 263 list[count++] = number; 264 *min = number; 265 *max = number; 266 } else 267 goto err_list; 268 269 token = strtok(NULL, ","); 270 271 while (token != NULL) { 272 if (count == MAX_LIST) { 273 RTE_LOG(WARNING, USER1, "Using only the first %u sizes\n", 274 MAX_LIST); 275 break; 276 } 277 278 number = strtoul(token, NULL, 10); 279 280 if (errno == EINVAL || errno == ERANGE || 281 number == 0) 282 goto err_list; 283 284 list[count++] = number; 285 286 if (number < *min) 287 *min = number; 288 if (number > *max) 289 *max = number; 290 291 token = strtok(NULL, ","); 292 } 293 294 free(copy_arg); 295 return count; 296 297 err_list: 298 free(copy_arg); 299 return -1; 300 } 301 302 static int 303 parse_total_ops(struct cperf_options *opts, const char *arg) 304 { 305 int ret = parse_uint32_t(&opts->total_ops, arg); 306 307 if (ret) 308 RTE_LOG(ERR, USER1, "failed to parse total operations count\n"); 309 310 if (opts->total_ops == 0) { 311 RTE_LOG(ERR, USER1, 312 "invalid total operations count number specified\n"); 313 return -1; 314 } 315 316 return ret; 317 } 318 319 static int 320 parse_pool_sz(struct cperf_options *opts, const char *arg) 321 { 322 int ret = parse_uint32_t(&opts->pool_sz, arg); 323 324 if (ret) 325 RTE_LOG(ERR, USER1, "failed to parse pool size"); 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_desc_nb(struct cperf_options *opts, const char *arg) 391 { 392 int ret = parse_uint32_t(&opts->nb_descriptors, arg); 393 394 if (ret) { 395 RTE_LOG(ERR, USER1, "failed to parse descriptors number\n"); 396 return -1; 397 } 398 399 if (opts->nb_descriptors == 0) { 400 RTE_LOG(ERR, USER1, "invalid descriptors number specified\n"); 401 return -1; 402 } 403 404 return 0; 405 } 406 407 static int 408 parse_device_type(struct cperf_options *opts, const char *arg) 409 { 410 if (strlen(arg) > (sizeof(opts->device_type) - 1)) 411 return -1; 412 413 strncpy(opts->device_type, arg, sizeof(opts->device_type) - 1); 414 *(opts->device_type + sizeof(opts->device_type) - 1) = '\0'; 415 416 return 0; 417 } 418 419 static int 420 parse_op_type(struct cperf_options *opts, const char *arg) 421 { 422 struct name_id_map optype_namemap[] = { 423 { 424 cperf_op_type_strs[CPERF_CIPHER_ONLY], 425 CPERF_CIPHER_ONLY 426 }, 427 { 428 cperf_op_type_strs[CPERF_AUTH_ONLY], 429 CPERF_AUTH_ONLY 430 }, 431 { 432 cperf_op_type_strs[CPERF_CIPHER_THEN_AUTH], 433 CPERF_CIPHER_THEN_AUTH 434 }, 435 { 436 cperf_op_type_strs[CPERF_AUTH_THEN_CIPHER], 437 CPERF_AUTH_THEN_CIPHER 438 }, 439 { 440 cperf_op_type_strs[CPERF_AEAD], 441 CPERF_AEAD 442 } 443 }; 444 445 int id = get_str_key_id_mapping(optype_namemap, 446 RTE_DIM(optype_namemap), arg); 447 if (id < 0) { 448 RTE_LOG(ERR, USER1, "invalid opt type specified\n"); 449 return -1; 450 } 451 452 opts->op_type = (enum cperf_op_type)id; 453 454 return 0; 455 } 456 457 static int 458 parse_sessionless(struct cperf_options *opts, 459 const char *arg __rte_unused) 460 { 461 opts->sessionless = 1; 462 return 0; 463 } 464 465 static int 466 parse_out_of_place(struct cperf_options *opts, 467 const char *arg __rte_unused) 468 { 469 opts->out_of_place = 1; 470 return 0; 471 } 472 473 static int 474 parse_test_file(struct cperf_options *opts, 475 const char *arg) 476 { 477 opts->test_file = strdup(arg); 478 if (access(opts->test_file, F_OK) != -1) 479 return 0; 480 RTE_LOG(ERR, USER1, "Test vector file doesn't exist\n"); 481 482 return -1; 483 } 484 485 static int 486 parse_test_name(struct cperf_options *opts, 487 const char *arg) 488 { 489 char *test_name = (char *) rte_zmalloc(NULL, 490 sizeof(char) * (strlen(arg) + 3), 0); 491 snprintf(test_name, strlen(arg) + 3, "[%s]", arg); 492 opts->test_name = test_name; 493 494 return 0; 495 } 496 497 static int 498 parse_silent(struct cperf_options *opts, 499 const char *arg __rte_unused) 500 { 501 opts->silent = 1; 502 503 return 0; 504 } 505 506 static int 507 parse_cipher_algo(struct cperf_options *opts, const char *arg) 508 { 509 510 enum rte_crypto_cipher_algorithm cipher_algo; 511 512 if (rte_cryptodev_get_cipher_algo_enum(&cipher_algo, arg) < 0) { 513 RTE_LOG(ERR, USER1, "Invalid cipher algorithm specified\n"); 514 return -1; 515 } 516 517 opts->cipher_algo = cipher_algo; 518 519 return 0; 520 } 521 522 static int 523 parse_cipher_op(struct cperf_options *opts, const char *arg) 524 { 525 struct name_id_map cipher_op_namemap[] = { 526 { 527 rte_crypto_cipher_operation_strings 528 [RTE_CRYPTO_CIPHER_OP_ENCRYPT], 529 RTE_CRYPTO_CIPHER_OP_ENCRYPT }, 530 { 531 rte_crypto_cipher_operation_strings 532 [RTE_CRYPTO_CIPHER_OP_DECRYPT], 533 RTE_CRYPTO_CIPHER_OP_DECRYPT 534 } 535 }; 536 537 int id = get_str_key_id_mapping(cipher_op_namemap, 538 RTE_DIM(cipher_op_namemap), arg); 539 if (id < 0) { 540 RTE_LOG(ERR, USER1, "Invalid cipher operation specified\n"); 541 return -1; 542 } 543 544 opts->cipher_op = (enum rte_crypto_cipher_operation)id; 545 546 return 0; 547 } 548 549 static int 550 parse_cipher_key_sz(struct cperf_options *opts, const char *arg) 551 { 552 return parse_uint16_t(&opts->cipher_key_sz, arg); 553 } 554 555 static int 556 parse_cipher_iv_sz(struct cperf_options *opts, const char *arg) 557 { 558 return parse_uint16_t(&opts->cipher_iv_sz, arg); 559 } 560 561 static int 562 parse_auth_algo(struct cperf_options *opts, const char *arg) 563 { 564 enum rte_crypto_auth_algorithm auth_algo; 565 566 if (rte_cryptodev_get_auth_algo_enum(&auth_algo, arg) < 0) { 567 RTE_LOG(ERR, USER1, "Invalid authentication algorithm specified\n"); 568 return -1; 569 } 570 571 opts->auth_algo = auth_algo; 572 573 return 0; 574 } 575 576 static int 577 parse_auth_op(struct cperf_options *opts, const char *arg) 578 { 579 struct name_id_map auth_op_namemap[] = { 580 { 581 rte_crypto_auth_operation_strings 582 [RTE_CRYPTO_AUTH_OP_GENERATE], 583 RTE_CRYPTO_AUTH_OP_GENERATE }, 584 { 585 rte_crypto_auth_operation_strings 586 [RTE_CRYPTO_AUTH_OP_VERIFY], 587 RTE_CRYPTO_AUTH_OP_VERIFY 588 } 589 }; 590 591 int id = get_str_key_id_mapping(auth_op_namemap, 592 RTE_DIM(auth_op_namemap), arg); 593 if (id < 0) { 594 RTE_LOG(ERR, USER1, "invalid authentication operation specified" 595 "\n"); 596 return -1; 597 } 598 599 opts->auth_op = (enum rte_crypto_auth_operation)id; 600 601 return 0; 602 } 603 604 static int 605 parse_auth_key_sz(struct cperf_options *opts, const char *arg) 606 { 607 return parse_uint16_t(&opts->auth_key_sz, arg); 608 } 609 610 static int 611 parse_digest_sz(struct cperf_options *opts, const char *arg) 612 { 613 return parse_uint16_t(&opts->digest_sz, arg); 614 } 615 616 static int 617 parse_auth_iv_sz(struct cperf_options *opts, const char *arg) 618 { 619 return parse_uint16_t(&opts->auth_iv_sz, arg); 620 } 621 622 static int 623 parse_aead_algo(struct cperf_options *opts, const char *arg) 624 { 625 enum rte_crypto_aead_algorithm aead_algo; 626 627 if (rte_cryptodev_get_aead_algo_enum(&aead_algo, arg) < 0) { 628 RTE_LOG(ERR, USER1, "Invalid AEAD algorithm specified\n"); 629 return -1; 630 } 631 632 opts->aead_algo = aead_algo; 633 634 return 0; 635 } 636 637 static int 638 parse_aead_op(struct cperf_options *opts, const char *arg) 639 { 640 struct name_id_map aead_op_namemap[] = { 641 { 642 rte_crypto_aead_operation_strings 643 [RTE_CRYPTO_AEAD_OP_ENCRYPT], 644 RTE_CRYPTO_AEAD_OP_ENCRYPT }, 645 { 646 rte_crypto_aead_operation_strings 647 [RTE_CRYPTO_AEAD_OP_DECRYPT], 648 RTE_CRYPTO_AEAD_OP_DECRYPT 649 } 650 }; 651 652 int id = get_str_key_id_mapping(aead_op_namemap, 653 RTE_DIM(aead_op_namemap), arg); 654 if (id < 0) { 655 RTE_LOG(ERR, USER1, "invalid AEAD operation specified" 656 "\n"); 657 return -1; 658 } 659 660 opts->aead_op = (enum rte_crypto_aead_operation)id; 661 662 return 0; 663 } 664 665 static int 666 parse_aead_key_sz(struct cperf_options *opts, const char *arg) 667 { 668 return parse_uint16_t(&opts->aead_key_sz, arg); 669 } 670 671 static int 672 parse_aead_iv_sz(struct cperf_options *opts, const char *arg) 673 { 674 return parse_uint16_t(&opts->aead_iv_sz, arg); 675 } 676 677 static int 678 parse_aead_aad_sz(struct cperf_options *opts, const char *arg) 679 { 680 return parse_uint16_t(&opts->aead_aad_sz, arg); 681 } 682 683 static int 684 parse_csv_friendly(struct cperf_options *opts, const char *arg __rte_unused) 685 { 686 opts->csv = 1; 687 opts->silent = 1; 688 return 0; 689 } 690 691 static int 692 parse_pmd_cyclecount_delay_ms(struct cperf_options *opts, 693 const char *arg) 694 { 695 int ret = parse_uint32_t(&opts->pmdcc_delay, arg); 696 697 if (ret) { 698 RTE_LOG(ERR, USER1, "failed to parse pmd-cyclecount delay\n"); 699 return -1; 700 } 701 702 return 0; 703 } 704 705 typedef int (*option_parser_t)(struct cperf_options *opts, 706 const char *arg); 707 708 struct long_opt_parser { 709 const char *lgopt_name; 710 option_parser_t parser_fn; 711 712 }; 713 714 static struct option lgopts[] = { 715 716 { CPERF_PTEST_TYPE, required_argument, 0, 0 }, 717 718 { CPERF_POOL_SIZE, required_argument, 0, 0 }, 719 { CPERF_TOTAL_OPS, required_argument, 0, 0 }, 720 { CPERF_BURST_SIZE, required_argument, 0, 0 }, 721 { CPERF_BUFFER_SIZE, required_argument, 0, 0 }, 722 { CPERF_SEGMENT_SIZE, required_argument, 0, 0 }, 723 { CPERF_DESC_NB, required_argument, 0, 0 }, 724 725 { CPERF_DEVTYPE, required_argument, 0, 0 }, 726 { CPERF_OPTYPE, required_argument, 0, 0 }, 727 728 { CPERF_SILENT, no_argument, 0, 0 }, 729 { CPERF_SESSIONLESS, no_argument, 0, 0 }, 730 { CPERF_OUT_OF_PLACE, no_argument, 0, 0 }, 731 { CPERF_TEST_FILE, required_argument, 0, 0 }, 732 { CPERF_TEST_NAME, required_argument, 0, 0 }, 733 734 { CPERF_CIPHER_ALGO, required_argument, 0, 0 }, 735 { CPERF_CIPHER_OP, required_argument, 0, 0 }, 736 737 { CPERF_CIPHER_KEY_SZ, required_argument, 0, 0 }, 738 { CPERF_CIPHER_IV_SZ, required_argument, 0, 0 }, 739 740 { CPERF_AUTH_ALGO, required_argument, 0, 0 }, 741 { CPERF_AUTH_OP, required_argument, 0, 0 }, 742 743 { CPERF_AUTH_KEY_SZ, required_argument, 0, 0 }, 744 { CPERF_AUTH_IV_SZ, required_argument, 0, 0 }, 745 746 { CPERF_AEAD_ALGO, required_argument, 0, 0 }, 747 { CPERF_AEAD_OP, required_argument, 0, 0 }, 748 749 { CPERF_AEAD_KEY_SZ, required_argument, 0, 0 }, 750 { CPERF_AEAD_AAD_SZ, required_argument, 0, 0 }, 751 { CPERF_AEAD_IV_SZ, required_argument, 0, 0 }, 752 753 { CPERF_DIGEST_SZ, required_argument, 0, 0 }, 754 755 { CPERF_CSV, no_argument, 0, 0}, 756 757 { CPERF_PMDCC_DELAY_MS, required_argument, 0, 0 }, 758 759 { NULL, 0, 0, 0 } 760 }; 761 762 void 763 cperf_options_default(struct cperf_options *opts) 764 { 765 opts->test = CPERF_TEST_TYPE_THROUGHPUT; 766 767 opts->pool_sz = 8192; 768 opts->total_ops = 10000000; 769 opts->nb_descriptors = 2048; 770 771 opts->buffer_size_list[0] = 64; 772 opts->buffer_size_count = 1; 773 opts->max_buffer_size = 64; 774 opts->min_buffer_size = 64; 775 opts->inc_buffer_size = 0; 776 777 opts->burst_size_list[0] = 32; 778 opts->burst_size_count = 1; 779 opts->max_burst_size = 32; 780 opts->min_burst_size = 32; 781 opts->inc_burst_size = 0; 782 783 /* 784 * Will be parsed from command line or set to 785 * maximum buffer size + digest, later 786 */ 787 opts->segment_sz = 0; 788 789 strncpy(opts->device_type, "crypto_aesni_mb", 790 sizeof(opts->device_type)); 791 opts->nb_qps = 1; 792 793 opts->op_type = CPERF_CIPHER_THEN_AUTH; 794 795 opts->silent = 0; 796 opts->test_file = NULL; 797 opts->test_name = NULL; 798 opts->sessionless = 0; 799 opts->out_of_place = 0; 800 opts->csv = 0; 801 802 opts->cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC; 803 opts->cipher_op = RTE_CRYPTO_CIPHER_OP_ENCRYPT; 804 opts->cipher_key_sz = 16; 805 opts->cipher_iv_sz = 16; 806 807 opts->auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC; 808 opts->auth_op = RTE_CRYPTO_AUTH_OP_GENERATE; 809 810 opts->auth_key_sz = 64; 811 opts->auth_iv_sz = 0; 812 813 opts->aead_key_sz = 0; 814 opts->aead_iv_sz = 0; 815 opts->aead_aad_sz = 0; 816 817 opts->digest_sz = 12; 818 819 opts->pmdcc_delay = 0; 820 } 821 822 static int 823 cperf_opts_parse_long(int opt_idx, struct cperf_options *opts) 824 { 825 struct long_opt_parser parsermap[] = { 826 { CPERF_PTEST_TYPE, parse_cperf_test_type }, 827 { CPERF_SILENT, parse_silent }, 828 { CPERF_POOL_SIZE, parse_pool_sz }, 829 { CPERF_TOTAL_OPS, parse_total_ops }, 830 { CPERF_BURST_SIZE, parse_burst_sz }, 831 { CPERF_BUFFER_SIZE, parse_buffer_sz }, 832 { CPERF_SEGMENT_SIZE, parse_segment_sz }, 833 { CPERF_DESC_NB, parse_desc_nb }, 834 { CPERF_DEVTYPE, parse_device_type }, 835 { CPERF_OPTYPE, parse_op_type }, 836 { CPERF_SESSIONLESS, parse_sessionless }, 837 { CPERF_OUT_OF_PLACE, parse_out_of_place }, 838 { CPERF_TEST_FILE, parse_test_file }, 839 { CPERF_TEST_NAME, parse_test_name }, 840 { CPERF_CIPHER_ALGO, parse_cipher_algo }, 841 { CPERF_CIPHER_OP, parse_cipher_op }, 842 { CPERF_CIPHER_KEY_SZ, parse_cipher_key_sz }, 843 { CPERF_CIPHER_IV_SZ, parse_cipher_iv_sz }, 844 { CPERF_AUTH_ALGO, parse_auth_algo }, 845 { CPERF_AUTH_OP, parse_auth_op }, 846 { CPERF_AUTH_KEY_SZ, parse_auth_key_sz }, 847 { CPERF_AUTH_IV_SZ, parse_auth_iv_sz }, 848 { CPERF_AEAD_ALGO, parse_aead_algo }, 849 { CPERF_AEAD_OP, parse_aead_op }, 850 { CPERF_AEAD_KEY_SZ, parse_aead_key_sz }, 851 { CPERF_AEAD_IV_SZ, parse_aead_iv_sz }, 852 { CPERF_AEAD_AAD_SZ, parse_aead_aad_sz }, 853 { CPERF_DIGEST_SZ, parse_digest_sz }, 854 { CPERF_CSV, parse_csv_friendly}, 855 { CPERF_PMDCC_DELAY_MS, parse_pmd_cyclecount_delay_ms}, 856 }; 857 unsigned int i; 858 859 for (i = 0; i < RTE_DIM(parsermap); i++) { 860 if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name, 861 strlen(lgopts[opt_idx].name)) == 0) 862 return parsermap[i].parser_fn(opts, optarg); 863 } 864 865 return -EINVAL; 866 } 867 868 int 869 cperf_options_parse(struct cperf_options *options, int argc, char **argv) 870 { 871 int opt, retval, opt_idx; 872 873 while ((opt = getopt_long(argc, argv, "h", lgopts, &opt_idx)) != EOF) { 874 switch (opt) { 875 case 'h': 876 usage(argv[0]); 877 rte_exit(EXIT_SUCCESS, "Displayed help\n"); 878 break; 879 /* long options */ 880 case 0: 881 retval = cperf_opts_parse_long(opt_idx, options); 882 if (retval != 0) 883 return retval; 884 885 break; 886 887 default: 888 usage(argv[0]); 889 return -EINVAL; 890 } 891 } 892 893 return 0; 894 } 895 896 static int 897 check_cipher_buffer_length(struct cperf_options *options) 898 { 899 uint32_t buffer_size, buffer_size_idx = 0; 900 901 if (options->cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC || 902 options->cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB) { 903 if (options->inc_buffer_size != 0) 904 buffer_size = options->min_buffer_size; 905 else 906 buffer_size = options->buffer_size_list[0]; 907 908 while (buffer_size <= options->max_buffer_size) { 909 if ((buffer_size % AES_BLOCK_SIZE) != 0) { 910 RTE_LOG(ERR, USER1, "Some of the buffer sizes are " 911 "not suitable for the algorithm selected\n"); 912 return -EINVAL; 913 } 914 915 if (options->inc_buffer_size != 0) 916 buffer_size += options->inc_buffer_size; 917 else { 918 if (++buffer_size_idx == options->buffer_size_count) 919 break; 920 buffer_size = options->buffer_size_list[buffer_size_idx]; 921 } 922 923 } 924 } 925 926 if (options->cipher_algo == RTE_CRYPTO_CIPHER_DES_CBC || 927 options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_CBC || 928 options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_ECB) { 929 if (options->inc_buffer_size != 0) 930 buffer_size = options->min_buffer_size; 931 else 932 buffer_size = options->buffer_size_list[0]; 933 934 while (buffer_size <= options->max_buffer_size) { 935 if ((buffer_size % DES_BLOCK_SIZE) != 0) { 936 RTE_LOG(ERR, USER1, "Some of the buffer sizes are " 937 "not suitable for the algorithm selected\n"); 938 return -EINVAL; 939 } 940 941 if (options->inc_buffer_size != 0) 942 buffer_size += options->inc_buffer_size; 943 else { 944 if (++buffer_size_idx == options->buffer_size_count) 945 break; 946 buffer_size = options->buffer_size_list[buffer_size_idx]; 947 } 948 949 } 950 } 951 952 return 0; 953 } 954 955 int 956 cperf_options_check(struct cperf_options *options) 957 { 958 if (options->op_type == CPERF_CIPHER_ONLY) 959 options->digest_sz = 0; 960 961 /* 962 * If segment size is not set, assume only one segment, 963 * big enough to contain the largest buffer and the digest 964 */ 965 if (options->segment_sz == 0) 966 options->segment_sz = options->max_buffer_size + 967 options->digest_sz; 968 969 if (options->segment_sz < options->digest_sz) { 970 RTE_LOG(ERR, USER1, 971 "Segment size should be at least " 972 "the size of the digest\n"); 973 return -EINVAL; 974 } 975 976 if (options->test == CPERF_TEST_TYPE_VERIFY && 977 options->test_file == NULL) { 978 RTE_LOG(ERR, USER1, "Define path to the file with test" 979 " vectors.\n"); 980 return -EINVAL; 981 } 982 983 if (options->test == CPERF_TEST_TYPE_VERIFY && 984 options->op_type != CPERF_CIPHER_ONLY && 985 options->test_name == NULL) { 986 RTE_LOG(ERR, USER1, "Define test name to get the correct digest" 987 " from the test vectors.\n"); 988 return -EINVAL; 989 } 990 991 if (options->test_name != NULL && options->test_file == NULL) { 992 RTE_LOG(ERR, USER1, "Define path to the file with test" 993 " vectors.\n"); 994 return -EINVAL; 995 } 996 997 if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY && 998 options->test_file == NULL) { 999 RTE_LOG(ERR, USER1, "Define path to the file with test" 1000 " vectors.\n"); 1001 return -EINVAL; 1002 } 1003 1004 if (options->test == CPERF_TEST_TYPE_VERIFY && 1005 (options->inc_buffer_size != 0 || 1006 options->buffer_size_count > 1)) { 1007 RTE_LOG(ERR, USER1, "Only one buffer size is allowed when " 1008 "using the verify test.\n"); 1009 return -EINVAL; 1010 } 1011 1012 if (options->test == CPERF_TEST_TYPE_VERIFY && 1013 (options->inc_burst_size != 0 || 1014 options->burst_size_count > 1)) { 1015 RTE_LOG(ERR, USER1, "Only one burst size is allowed when " 1016 "using the verify test.\n"); 1017 return -EINVAL; 1018 } 1019 1020 if (options->test == CPERF_TEST_TYPE_PMDCC && 1021 options->pool_sz < options->nb_descriptors) { 1022 RTE_LOG(ERR, USER1, "For pmd cyclecount benchmarks, pool size " 1023 "must be equal or greater than the number of " 1024 "cryptodev descriptors.\n"); 1025 return -EINVAL; 1026 } 1027 1028 if (options->op_type == CPERF_CIPHER_THEN_AUTH) { 1029 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_ENCRYPT && 1030 options->auth_op != 1031 RTE_CRYPTO_AUTH_OP_GENERATE) { 1032 RTE_LOG(ERR, USER1, "Option cipher then auth must use" 1033 " options: encrypt and generate.\n"); 1034 return -EINVAL; 1035 } 1036 } else if (options->op_type == CPERF_AUTH_THEN_CIPHER) { 1037 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_DECRYPT && 1038 options->auth_op != 1039 RTE_CRYPTO_AUTH_OP_VERIFY) { 1040 RTE_LOG(ERR, USER1, "Option auth then cipher must use" 1041 " options: decrypt and verify.\n"); 1042 return -EINVAL; 1043 } 1044 } 1045 1046 if (options->op_type == CPERF_CIPHER_ONLY || 1047 options->op_type == CPERF_CIPHER_THEN_AUTH || 1048 options->op_type == CPERF_AUTH_THEN_CIPHER) { 1049 if (check_cipher_buffer_length(options) < 0) 1050 return -EINVAL; 1051 } 1052 1053 return 0; 1054 } 1055 1056 void 1057 cperf_options_dump(struct cperf_options *opts) 1058 { 1059 uint8_t size_idx; 1060 1061 printf("# Crypto Performance Application Options:\n"); 1062 printf("#\n"); 1063 printf("# cperf test: %s\n", cperf_test_type_strs[opts->test]); 1064 printf("#\n"); 1065 printf("# size of crypto op / mbuf pool: %u\n", opts->pool_sz); 1066 printf("# total number of ops: %u\n", opts->total_ops); 1067 if (opts->inc_buffer_size != 0) { 1068 printf("# buffer size:\n"); 1069 printf("#\t min: %u\n", opts->min_buffer_size); 1070 printf("#\t max: %u\n", opts->max_buffer_size); 1071 printf("#\t inc: %u\n", opts->inc_buffer_size); 1072 } else { 1073 printf("# buffer sizes: "); 1074 for (size_idx = 0; size_idx < opts->buffer_size_count; size_idx++) 1075 printf("%u ", opts->buffer_size_list[size_idx]); 1076 printf("\n"); 1077 } 1078 if (opts->inc_burst_size != 0) { 1079 printf("# burst size:\n"); 1080 printf("#\t min: %u\n", opts->min_burst_size); 1081 printf("#\t max: %u\n", opts->max_burst_size); 1082 printf("#\t inc: %u\n", opts->inc_burst_size); 1083 } else { 1084 printf("# burst sizes: "); 1085 for (size_idx = 0; size_idx < opts->burst_size_count; size_idx++) 1086 printf("%u ", opts->burst_size_list[size_idx]); 1087 printf("\n"); 1088 } 1089 printf("\n# segment size: %u\n", opts->segment_sz); 1090 printf("#\n"); 1091 printf("# cryptodev type: %s\n", opts->device_type); 1092 printf("#\n"); 1093 printf("# number of queue pairs per device: %u\n", opts->nb_qps); 1094 printf("# crypto operation: %s\n", cperf_op_type_strs[opts->op_type]); 1095 printf("# sessionless: %s\n", opts->sessionless ? "yes" : "no"); 1096 printf("# out of place: %s\n", opts->out_of_place ? "yes" : "no"); 1097 if (opts->test == CPERF_TEST_TYPE_PMDCC) 1098 printf("# inter-burst delay: %u ms\n", opts->pmdcc_delay); 1099 1100 printf("#\n"); 1101 1102 if (opts->op_type == CPERF_AUTH_ONLY || 1103 opts->op_type == CPERF_CIPHER_THEN_AUTH || 1104 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 1105 printf("# auth algorithm: %s\n", 1106 rte_crypto_auth_algorithm_strings[opts->auth_algo]); 1107 printf("# auth operation: %s\n", 1108 rte_crypto_auth_operation_strings[opts->auth_op]); 1109 printf("# auth key size: %u\n", opts->auth_key_sz); 1110 printf("# auth iv size: %u\n", opts->auth_iv_sz); 1111 printf("# auth digest size: %u\n", opts->digest_sz); 1112 printf("#\n"); 1113 } 1114 1115 if (opts->op_type == CPERF_CIPHER_ONLY || 1116 opts->op_type == CPERF_CIPHER_THEN_AUTH || 1117 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 1118 printf("# cipher algorithm: %s\n", 1119 rte_crypto_cipher_algorithm_strings[opts->cipher_algo]); 1120 printf("# cipher operation: %s\n", 1121 rte_crypto_cipher_operation_strings[opts->cipher_op]); 1122 printf("# cipher key size: %u\n", opts->cipher_key_sz); 1123 printf("# cipher iv size: %u\n", opts->cipher_iv_sz); 1124 printf("#\n"); 1125 } 1126 1127 if (opts->op_type == CPERF_AEAD) { 1128 printf("# aead algorithm: %s\n", 1129 rte_crypto_aead_algorithm_strings[opts->aead_algo]); 1130 printf("# aead operation: %s\n", 1131 rte_crypto_aead_operation_strings[opts->aead_op]); 1132 printf("# aead key size: %u\n", opts->aead_key_sz); 1133 printf("# aead iv size: %u\n", opts->aead_iv_sz); 1134 printf("# aead digest size: %u\n", opts->digest_sz); 1135 printf("# aead aad size: %u\n", opts->aead_aad_sz); 1136 printf("#\n"); 1137 } 1138 } 1139