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