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 static bool 1134 is_valid_chained_op(struct cperf_options *options) 1135 { 1136 if (options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT && 1137 options->auth_op == RTE_CRYPTO_AUTH_OP_GENERATE) 1138 return true; 1139 1140 if (options->cipher_op == RTE_CRYPTO_CIPHER_OP_DECRYPT && 1141 options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY) 1142 return true; 1143 1144 return false; 1145 } 1146 1147 int 1148 cperf_options_check(struct cperf_options *options) 1149 { 1150 int i; 1151 1152 if (options->op_type == CPERF_CIPHER_ONLY || 1153 options->op_type == CPERF_DOCSIS) 1154 options->digest_sz = 0; 1155 1156 if (options->out_of_place && 1157 options->segment_sz <= options->max_buffer_size) { 1158 RTE_LOG(ERR, USER1, "Out of place mode can only work " 1159 "with non segmented buffers\n"); 1160 return -EINVAL; 1161 } 1162 1163 /* 1164 * If segment size is not set, assume only one segment, 1165 * big enough to contain the largest buffer and the digest 1166 */ 1167 if (options->segment_sz == 0) { 1168 options->segment_sz = options->max_buffer_size + 1169 options->digest_sz; 1170 /* In IPsec operation, packet length will be increased 1171 * by some bytes depend upon the algorithm, so increasing 1172 * the segment size by headroom to cover most of 1173 * the scenarios. 1174 */ 1175 if (options->op_type == CPERF_IPSEC) 1176 options->segment_sz += RTE_PKTMBUF_HEADROOM; 1177 } 1178 1179 if (options->segment_sz < options->digest_sz) { 1180 RTE_LOG(ERR, USER1, 1181 "Segment size should be at least " 1182 "the size of the digest\n"); 1183 return -EINVAL; 1184 } 1185 1186 if ((options->imix_distribution_count != 0) && 1187 (options->imix_distribution_count != 1188 options->buffer_size_count)) { 1189 RTE_LOG(ERR, USER1, "IMIX distribution must have the same " 1190 "number of buffer sizes\n"); 1191 return -EINVAL; 1192 } 1193 1194 if (options->test == CPERF_TEST_TYPE_VERIFY && 1195 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->test == CPERF_TEST_TYPE_VERIFY && 1202 options->op_type != CPERF_CIPHER_ONLY && 1203 options->test_name == NULL) { 1204 RTE_LOG(ERR, USER1, "Define test name to get the correct digest" 1205 " from the test vectors.\n"); 1206 return -EINVAL; 1207 } 1208 1209 if (options->test_name != NULL && options->test_file == NULL) { 1210 RTE_LOG(ERR, USER1, "Define path to the file with test" 1211 " vectors.\n"); 1212 return -EINVAL; 1213 } 1214 1215 if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY && 1216 options->test_file == NULL) { 1217 RTE_LOG(ERR, USER1, "Define path to the file with test" 1218 " vectors.\n"); 1219 return -EINVAL; 1220 } 1221 1222 if (options->test == CPERF_TEST_TYPE_VERIFY && 1223 (options->inc_buffer_size != 0 || 1224 options->buffer_size_count > 1)) { 1225 RTE_LOG(ERR, USER1, "Only one buffer size is allowed when " 1226 "using the verify test.\n"); 1227 return -EINVAL; 1228 } 1229 1230 if (options->test == CPERF_TEST_TYPE_VERIFY && 1231 (options->inc_burst_size != 0 || 1232 options->burst_size_count > 1)) { 1233 RTE_LOG(ERR, USER1, "Only one burst size is allowed when " 1234 "using the verify test.\n"); 1235 return -EINVAL; 1236 } 1237 1238 if (options->test == CPERF_TEST_TYPE_PMDCC && 1239 options->pool_sz < options->nb_descriptors) { 1240 RTE_LOG(ERR, USER1, "For pmd cyclecount benchmarks, pool size " 1241 "must be equal or greater than the number of " 1242 "cryptodev descriptors.\n"); 1243 return -EINVAL; 1244 } 1245 1246 if (options->test == CPERF_TEST_TYPE_VERIFY && 1247 options->imix_distribution_count > 0) { 1248 RTE_LOG(ERR, USER1, "IMIX is not allowed when " 1249 "using the verify test.\n"); 1250 return -EINVAL; 1251 } 1252 1253 if (options->op_type == CPERF_CIPHER_THEN_AUTH || 1254 options->op_type == CPERF_AUTH_THEN_CIPHER) { 1255 if (!is_valid_chained_op(options)) { 1256 RTE_LOG(ERR, USER1, "Invalid chained operation.\n"); 1257 return -EINVAL; 1258 } 1259 } 1260 1261 if (options->op_type == CPERF_CIPHER_THEN_AUTH) { 1262 if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_ENCRYPT && 1263 options->auth_op != 1264 RTE_CRYPTO_AUTH_OP_GENERATE) { 1265 RTE_LOG(ERR, USER1, "Option cipher then auth must use" 1266 " options: encrypt and generate.\n"); 1267 return -EINVAL; 1268 } 1269 } 1270 1271 if (options->op_type == CPERF_CIPHER_ONLY || 1272 options->op_type == CPERF_CIPHER_THEN_AUTH || 1273 options->op_type == CPERF_AUTH_THEN_CIPHER) { 1274 if (check_cipher_buffer_length(options) < 0) 1275 return -EINVAL; 1276 } 1277 1278 if (options->modex_len) { 1279 if (options->op_type != CPERF_ASYM_MODEX) { 1280 RTE_LOG(ERR, USER1, "Option modex len should be used only with " 1281 " optype: modex.\n"); 1282 return -EINVAL; 1283 } 1284 1285 for (i = 0; i < (int)RTE_DIM(modex_perf_data); i++) { 1286 if (modex_perf_data[i].modulus.len == 1287 options->modex_len) { 1288 options->modex_data = 1289 (struct cperf_modex_test_data 1290 *)&modex_perf_data[i]; 1291 break; 1292 } 1293 } 1294 if (i == (int)RTE_DIM(modex_perf_data)) { 1295 RTE_LOG(ERR, USER1, 1296 "Option modex len: %d is not supported\n", 1297 options->modex_len); 1298 return -EINVAL; 1299 } 1300 } 1301 1302 #ifdef RTE_LIB_SECURITY 1303 if (options->op_type == CPERF_DOCSIS) { 1304 if (check_docsis_buffer_length(options) < 0) 1305 return -EINVAL; 1306 } 1307 #endif 1308 1309 return 0; 1310 } 1311 1312 void 1313 cperf_options_dump(struct cperf_options *opts) 1314 { 1315 uint8_t size_idx; 1316 1317 printf("# Crypto Performance Application Options:\n"); 1318 printf("#\n"); 1319 printf("# cperf test: %s\n", cperf_test_type_strs[opts->test]); 1320 printf("#\n"); 1321 printf("# size of crypto op / mbuf pool: %u\n", opts->pool_sz); 1322 printf("# total number of ops: %u\n", opts->total_ops); 1323 if (opts->inc_buffer_size != 0) { 1324 printf("# buffer size:\n"); 1325 printf("#\t min: %u\n", opts->min_buffer_size); 1326 printf("#\t max: %u\n", opts->max_buffer_size); 1327 printf("#\t inc: %u\n", opts->inc_buffer_size); 1328 } else { 1329 printf("# buffer sizes: "); 1330 for (size_idx = 0; size_idx < opts->buffer_size_count; size_idx++) 1331 printf("%u ", opts->buffer_size_list[size_idx]); 1332 printf("\n"); 1333 } 1334 if (opts->inc_burst_size != 0) { 1335 printf("# burst size:\n"); 1336 printf("#\t min: %u\n", opts->min_burst_size); 1337 printf("#\t max: %u\n", opts->max_burst_size); 1338 printf("#\t inc: %u\n", opts->inc_burst_size); 1339 } else { 1340 printf("# burst sizes: "); 1341 for (size_idx = 0; size_idx < opts->burst_size_count; size_idx++) 1342 printf("%u ", opts->burst_size_list[size_idx]); 1343 printf("\n"); 1344 } 1345 printf("\n# segment size: %u\n", opts->segment_sz); 1346 printf("#\n"); 1347 printf("# cryptodev type: %s\n", opts->device_type); 1348 printf("#\n"); 1349 printf("# number of queue pairs per device: %u\n", opts->nb_qps); 1350 printf("# crypto operation: %s\n", cperf_op_type_strs[opts->op_type]); 1351 printf("# sessionless: %s\n", opts->sessionless ? "yes" : "no"); 1352 printf("# out of place: %s\n", opts->out_of_place ? "yes" : "no"); 1353 if (opts->test == CPERF_TEST_TYPE_PMDCC) 1354 printf("# inter-burst delay: %u ms\n", opts->pmdcc_delay); 1355 1356 printf("#\n"); 1357 1358 if (opts->op_type == CPERF_AUTH_ONLY || 1359 opts->op_type == CPERF_CIPHER_THEN_AUTH || 1360 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 1361 printf("# auth algorithm: %s\n", 1362 rte_crypto_auth_algorithm_strings[opts->auth_algo]); 1363 printf("# auth operation: %s\n", 1364 rte_crypto_auth_operation_strings[opts->auth_op]); 1365 printf("# auth key size: %u\n", opts->auth_key_sz); 1366 printf("# auth iv size: %u\n", opts->auth_iv_sz); 1367 printf("# auth digest size: %u\n", opts->digest_sz); 1368 printf("#\n"); 1369 } 1370 1371 if (opts->op_type == CPERF_CIPHER_ONLY || 1372 opts->op_type == CPERF_CIPHER_THEN_AUTH || 1373 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 1374 printf("# cipher algorithm: %s\n", 1375 rte_crypto_cipher_algorithm_strings[opts->cipher_algo]); 1376 printf("# cipher operation: %s\n", 1377 rte_crypto_cipher_operation_strings[opts->cipher_op]); 1378 printf("# cipher key size: %u\n", opts->cipher_key_sz); 1379 printf("# cipher iv size: %u\n", opts->cipher_iv_sz); 1380 printf("#\n"); 1381 } 1382 1383 if (opts->op_type == CPERF_AEAD) { 1384 printf("# aead algorithm: %s\n", 1385 rte_crypto_aead_algorithm_strings[opts->aead_algo]); 1386 printf("# aead operation: %s\n", 1387 rte_crypto_aead_operation_strings[opts->aead_op]); 1388 printf("# aead key size: %u\n", opts->aead_key_sz); 1389 printf("# aead iv size: %u\n", opts->aead_iv_sz); 1390 printf("# aead digest size: %u\n", opts->digest_sz); 1391 printf("# aead aad size: %u\n", opts->aead_aad_sz); 1392 printf("#\n"); 1393 } 1394 1395 #ifdef RTE_LIB_SECURITY 1396 if (opts->op_type == CPERF_DOCSIS) { 1397 printf("# docsis header size: %u\n", opts->docsis_hdr_sz); 1398 printf("#\n"); 1399 } 1400 #endif 1401 } 1402