1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2016-2017 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <unistd.h> 8 9 #include <rte_malloc.h> 10 #include <rte_random.h> 11 #include <rte_eal.h> 12 #include <rte_cryptodev.h> 13 #ifdef RTE_CRYPTO_SCHEDULER 14 #include <rte_cryptodev_scheduler.h> 15 #endif 16 17 #include "cperf.h" 18 #include "cperf_options.h" 19 #include "cperf_test_vector_parsing.h" 20 #include "cperf_test_throughput.h" 21 #include "cperf_test_latency.h" 22 #include "cperf_test_verify.h" 23 #include "cperf_test_pmd_cyclecount.h" 24 25 static struct { 26 struct rte_mempool *sess_mp; 27 } session_pool_socket[RTE_MAX_NUMA_NODES]; 28 29 const char *cperf_test_type_strs[] = { 30 [CPERF_TEST_TYPE_THROUGHPUT] = "throughput", 31 [CPERF_TEST_TYPE_LATENCY] = "latency", 32 [CPERF_TEST_TYPE_VERIFY] = "verify", 33 [CPERF_TEST_TYPE_PMDCC] = "pmd-cyclecount" 34 }; 35 36 const char *cperf_op_type_strs[] = { 37 [CPERF_CIPHER_ONLY] = "cipher-only", 38 [CPERF_AUTH_ONLY] = "auth-only", 39 [CPERF_CIPHER_THEN_AUTH] = "cipher-then-auth", 40 [CPERF_AUTH_THEN_CIPHER] = "auth-then-cipher", 41 [CPERF_AEAD] = "aead", 42 [CPERF_PDCP] = "pdcp", 43 [CPERF_DOCSIS] = "docsis", 44 [CPERF_IPSEC] = "ipsec", 45 [CPERF_ASYM_MODEX] = "modex" 46 }; 47 48 const struct cperf_test cperf_testmap[] = { 49 [CPERF_TEST_TYPE_THROUGHPUT] = { 50 cperf_throughput_test_constructor, 51 cperf_throughput_test_runner, 52 cperf_throughput_test_destructor 53 }, 54 [CPERF_TEST_TYPE_LATENCY] = { 55 cperf_latency_test_constructor, 56 cperf_latency_test_runner, 57 cperf_latency_test_destructor 58 }, 59 [CPERF_TEST_TYPE_VERIFY] = { 60 cperf_verify_test_constructor, 61 cperf_verify_test_runner, 62 cperf_verify_test_destructor 63 }, 64 [CPERF_TEST_TYPE_PMDCC] = { 65 cperf_pmd_cyclecount_test_constructor, 66 cperf_pmd_cyclecount_test_runner, 67 cperf_pmd_cyclecount_test_destructor 68 } 69 }; 70 71 static int 72 create_asym_op_pool_socket(int32_t socket_id, uint32_t nb_sessions) 73 { 74 char mp_name[RTE_MEMPOOL_NAMESIZE]; 75 struct rte_mempool *mpool = NULL; 76 77 if (session_pool_socket[socket_id].sess_mp == NULL) { 78 snprintf(mp_name, RTE_MEMPOOL_NAMESIZE, "perf_asym_sess_pool%u", 79 socket_id); 80 mpool = rte_cryptodev_asym_session_pool_create(mp_name, 81 nb_sessions, 0, 0, socket_id); 82 if (mpool == NULL) { 83 printf("Cannot create pool \"%s\" on socket %d\n", 84 mp_name, socket_id); 85 return -ENOMEM; 86 } 87 session_pool_socket[socket_id].sess_mp = mpool; 88 } 89 return 0; 90 } 91 92 static int 93 fill_session_pool_socket(int32_t socket_id, uint32_t session_priv_size, 94 uint32_t nb_sessions) 95 { 96 char mp_name[RTE_MEMPOOL_NAMESIZE]; 97 struct rte_mempool *sess_mp; 98 99 if (session_pool_socket[socket_id].sess_mp == NULL) { 100 101 snprintf(mp_name, RTE_MEMPOOL_NAMESIZE, 102 "sess_mp_%u", socket_id); 103 104 sess_mp = rte_cryptodev_sym_session_pool_create(mp_name, 105 nb_sessions, session_priv_size, 0, 0, 106 socket_id); 107 108 if (sess_mp == NULL) { 109 printf("Cannot create pool \"%s\" on socket %d\n", 110 mp_name, socket_id); 111 return -ENOMEM; 112 } 113 114 printf("Allocated pool \"%s\" on socket %d\n", 115 mp_name, socket_id); 116 session_pool_socket[socket_id].sess_mp = sess_mp; 117 } 118 119 return 0; 120 } 121 122 static int 123 cperf_initialize_cryptodev(struct cperf_options *opts, uint8_t *enabled_cdevs) 124 { 125 uint8_t enabled_cdev_count = 0, nb_lcores, cdev_id; 126 uint32_t sessions_needed = 0; 127 unsigned int i, j; 128 int ret; 129 130 enabled_cdev_count = rte_cryptodev_devices_get(opts->device_type, 131 enabled_cdevs, RTE_CRYPTO_MAX_DEVS); 132 if (enabled_cdev_count == 0) { 133 printf("No crypto devices type %s available\n", 134 opts->device_type); 135 return -EINVAL; 136 } 137 138 nb_lcores = rte_lcore_count() - 1; 139 140 if (nb_lcores < 1) { 141 RTE_LOG(ERR, USER1, 142 "Number of enabled cores need to be higher than 1\n"); 143 return -EINVAL; 144 } 145 146 /* 147 * Use less number of devices, 148 * if there are more available than cores. 149 */ 150 if (enabled_cdev_count > nb_lcores) 151 enabled_cdev_count = nb_lcores; 152 153 /* Create a mempool shared by all the devices */ 154 uint32_t max_sess_size = 0, sess_size; 155 156 for (cdev_id = 0; cdev_id < rte_cryptodev_count(); cdev_id++) { 157 sess_size = rte_cryptodev_sym_get_private_session_size(cdev_id); 158 if (sess_size > max_sess_size) 159 max_sess_size = sess_size; 160 } 161 #ifdef RTE_LIB_SECURITY 162 for (cdev_id = 0; cdev_id < rte_cryptodev_count(); cdev_id++) { 163 sess_size = rte_security_session_get_size( 164 rte_cryptodev_get_sec_ctx(cdev_id)); 165 if (sess_size > max_sess_size) 166 max_sess_size = sess_size; 167 } 168 #endif 169 /* 170 * Calculate number of needed queue pairs, based on the amount 171 * of available number of logical cores and crypto devices. 172 * For instance, if there are 4 cores and 2 crypto devices, 173 * 2 queue pairs will be set up per device. 174 */ 175 opts->nb_qps = (nb_lcores % enabled_cdev_count) ? 176 (nb_lcores / enabled_cdev_count) + 1 : 177 nb_lcores / enabled_cdev_count; 178 179 for (i = 0; i < enabled_cdev_count && 180 i < RTE_CRYPTO_MAX_DEVS; i++) { 181 cdev_id = enabled_cdevs[i]; 182 #ifdef RTE_CRYPTO_SCHEDULER 183 /* 184 * If multi-core scheduler is used, limit the number 185 * of queue pairs to 1, as there is no way to know 186 * how many cores are being used by the PMD, and 187 * how many will be available for the application. 188 */ 189 if (!strcmp((const char *)opts->device_type, "crypto_scheduler") && 190 rte_cryptodev_scheduler_mode_get(cdev_id) == 191 CDEV_SCHED_MODE_MULTICORE) 192 opts->nb_qps = 1; 193 #endif 194 195 struct rte_cryptodev_info cdev_info; 196 uint8_t socket_id = rte_cryptodev_socket_id(cdev_id); 197 /* range check the socket_id - negative values become big 198 * positive ones due to use of unsigned value 199 */ 200 if (socket_id >= RTE_MAX_NUMA_NODES) 201 socket_id = 0; 202 203 rte_cryptodev_info_get(cdev_id, &cdev_info); 204 205 if (opts->op_type == CPERF_ASYM_MODEX) { 206 if ((cdev_info.feature_flags & 207 RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO) == 0) 208 continue; 209 } 210 211 if (opts->nb_qps > cdev_info.max_nb_queue_pairs) { 212 printf("Number of needed queue pairs is higher " 213 "than the maximum number of queue pairs " 214 "per device.\n"); 215 printf("Lower the number of cores or increase " 216 "the number of crypto devices\n"); 217 return -EINVAL; 218 } 219 struct rte_cryptodev_config conf = { 220 .nb_queue_pairs = opts->nb_qps, 221 .socket_id = socket_id, 222 }; 223 224 switch (opts->op_type) { 225 case CPERF_ASYM_MODEX: 226 conf.ff_disable |= (RTE_CRYPTODEV_FF_SECURITY | 227 RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO); 228 break; 229 case CPERF_CIPHER_ONLY: 230 case CPERF_AUTH_ONLY: 231 case CPERF_CIPHER_THEN_AUTH: 232 case CPERF_AUTH_THEN_CIPHER: 233 case CPERF_AEAD: 234 conf.ff_disable |= RTE_CRYPTODEV_FF_SECURITY; 235 /* Fall through */ 236 case CPERF_PDCP: 237 case CPERF_DOCSIS: 238 case CPERF_IPSEC: 239 /* Fall through */ 240 default: 241 conf.ff_disable |= RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO; 242 } 243 244 struct rte_cryptodev_qp_conf qp_conf = { 245 .nb_descriptors = opts->nb_descriptors 246 }; 247 248 /** 249 * Device info specifies the min headroom and tailroom 250 * requirement for the crypto PMD. This need to be honoured 251 * by the application, while creating mbuf. 252 */ 253 if (opts->headroom_sz < cdev_info.min_mbuf_headroom_req) { 254 /* Update headroom */ 255 opts->headroom_sz = cdev_info.min_mbuf_headroom_req; 256 } 257 if (opts->tailroom_sz < cdev_info.min_mbuf_tailroom_req) { 258 /* Update tailroom */ 259 opts->tailroom_sz = cdev_info.min_mbuf_tailroom_req; 260 } 261 262 /* Update segment size to include headroom & tailroom */ 263 opts->segment_sz += (opts->headroom_sz + opts->tailroom_sz); 264 265 uint32_t dev_max_nb_sess = cdev_info.sym.max_nb_sessions; 266 /* 267 * Two sessions objects are required for each session 268 * (one for the header, one for the private data) 269 */ 270 if (!strcmp((const char *)opts->device_type, 271 "crypto_scheduler")) { 272 #ifdef RTE_CRYPTO_SCHEDULER 273 uint32_t nb_slaves = 274 rte_cryptodev_scheduler_workers_get(cdev_id, 275 NULL); 276 277 sessions_needed = enabled_cdev_count * 278 opts->nb_qps * nb_slaves; 279 #endif 280 } else 281 sessions_needed = enabled_cdev_count * opts->nb_qps; 282 283 /* 284 * A single session is required per queue pair 285 * in each device 286 */ 287 if (dev_max_nb_sess != 0 && dev_max_nb_sess < opts->nb_qps) { 288 RTE_LOG(ERR, USER1, 289 "Device does not support at least " 290 "%u sessions\n", opts->nb_qps); 291 return -ENOTSUP; 292 } 293 294 if (opts->op_type == CPERF_ASYM_MODEX) 295 ret = create_asym_op_pool_socket(socket_id, 296 sessions_needed); 297 else 298 ret = fill_session_pool_socket(socket_id, max_sess_size, 299 sessions_needed); 300 if (ret < 0) 301 return ret; 302 303 qp_conf.mp_session = session_pool_socket[socket_id].sess_mp; 304 305 if (opts->op_type == CPERF_ASYM_MODEX) { 306 qp_conf.mp_session = NULL; 307 } 308 309 ret = rte_cryptodev_configure(cdev_id, &conf); 310 if (ret < 0) { 311 printf("Failed to configure cryptodev %u", cdev_id); 312 return -EINVAL; 313 } 314 315 for (j = 0; j < opts->nb_qps; j++) { 316 ret = rte_cryptodev_queue_pair_setup(cdev_id, j, 317 &qp_conf, socket_id); 318 if (ret < 0) { 319 printf("Failed to setup queue pair %u on " 320 "cryptodev %u", j, cdev_id); 321 return -EINVAL; 322 } 323 } 324 325 ret = rte_cryptodev_start(cdev_id); 326 if (ret < 0) { 327 printf("Failed to start device %u: error %d\n", 328 cdev_id, ret); 329 return -EPERM; 330 } 331 } 332 333 return enabled_cdev_count; 334 } 335 336 static int 337 cperf_verify_devices_capabilities(struct cperf_options *opts, 338 uint8_t *enabled_cdevs, uint8_t nb_cryptodevs) 339 { 340 struct rte_cryptodev_sym_capability_idx cap_idx; 341 const struct rte_cryptodev_symmetric_capability *capability; 342 struct rte_cryptodev_asym_capability_idx asym_cap_idx; 343 const struct rte_cryptodev_asymmetric_xform_capability *asym_capability; 344 345 346 uint8_t i, cdev_id; 347 int ret; 348 349 for (i = 0; i < nb_cryptodevs; i++) { 350 351 cdev_id = enabled_cdevs[i]; 352 353 if (opts->op_type == CPERF_ASYM_MODEX) { 354 asym_cap_idx.type = RTE_CRYPTO_ASYM_XFORM_MODEX; 355 asym_capability = rte_cryptodev_asym_capability_get( 356 cdev_id, &asym_cap_idx); 357 if (asym_capability == NULL) 358 return -1; 359 360 ret = rte_cryptodev_asym_xform_capability_check_modlen( 361 asym_capability, opts->modex_data->modulus.len); 362 if (ret != 0) 363 return ret; 364 365 } 366 367 if (opts->op_type == CPERF_AUTH_ONLY || 368 opts->op_type == CPERF_CIPHER_THEN_AUTH || 369 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 370 371 cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH; 372 cap_idx.algo.auth = opts->auth_algo; 373 374 capability = rte_cryptodev_sym_capability_get(cdev_id, 375 &cap_idx); 376 if (capability == NULL) 377 return -1; 378 379 ret = rte_cryptodev_sym_capability_check_auth( 380 capability, 381 opts->auth_key_sz, 382 opts->digest_sz, 383 opts->auth_iv_sz); 384 if (ret != 0) 385 return ret; 386 } 387 388 if (opts->op_type == CPERF_CIPHER_ONLY || 389 opts->op_type == CPERF_CIPHER_THEN_AUTH || 390 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 391 392 cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER; 393 cap_idx.algo.cipher = opts->cipher_algo; 394 395 capability = rte_cryptodev_sym_capability_get(cdev_id, 396 &cap_idx); 397 if (capability == NULL) 398 return -1; 399 400 ret = rte_cryptodev_sym_capability_check_cipher( 401 capability, 402 opts->cipher_key_sz, 403 opts->cipher_iv_sz); 404 if (ret != 0) 405 return ret; 406 } 407 408 if (opts->op_type == CPERF_AEAD) { 409 410 cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD; 411 cap_idx.algo.aead = opts->aead_algo; 412 413 capability = rte_cryptodev_sym_capability_get(cdev_id, 414 &cap_idx); 415 if (capability == NULL) 416 return -1; 417 418 ret = rte_cryptodev_sym_capability_check_aead( 419 capability, 420 opts->aead_key_sz, 421 opts->digest_sz, 422 opts->aead_aad_sz, 423 opts->aead_iv_sz); 424 if (ret != 0) 425 return ret; 426 } 427 } 428 429 return 0; 430 } 431 432 static int 433 cperf_check_test_vector(struct cperf_options *opts, 434 struct cperf_test_vector *test_vec) 435 { 436 if (opts->op_type == CPERF_CIPHER_ONLY) { 437 if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) { 438 if (test_vec->plaintext.data == NULL) 439 return -1; 440 } else { 441 if (test_vec->plaintext.data == NULL) 442 return -1; 443 if (test_vec->plaintext.length < opts->max_buffer_size) 444 return -1; 445 if (test_vec->ciphertext.data == NULL) 446 return -1; 447 if (test_vec->ciphertext.length < opts->max_buffer_size) 448 return -1; 449 /* Cipher IV is only required for some algorithms */ 450 if (opts->cipher_iv_sz && 451 test_vec->cipher_iv.data == NULL) 452 return -1; 453 if (test_vec->cipher_iv.length != opts->cipher_iv_sz) 454 return -1; 455 if (test_vec->cipher_key.data == NULL) 456 return -1; 457 if (test_vec->cipher_key.length != opts->cipher_key_sz) 458 return -1; 459 } 460 } else if (opts->op_type == CPERF_AUTH_ONLY) { 461 if (opts->auth_algo != RTE_CRYPTO_AUTH_NULL) { 462 if (test_vec->plaintext.data == NULL) 463 return -1; 464 if (test_vec->plaintext.length < opts->max_buffer_size) 465 return -1; 466 /* Auth key is only required for some algorithms */ 467 if (opts->auth_key_sz && 468 test_vec->auth_key.data == NULL) 469 return -1; 470 if (test_vec->auth_key.length != opts->auth_key_sz) 471 return -1; 472 if (test_vec->auth_iv.length != opts->auth_iv_sz) 473 return -1; 474 /* Auth IV is only required for some algorithms */ 475 if (opts->auth_iv_sz && test_vec->auth_iv.data == NULL) 476 return -1; 477 if (test_vec->digest.data == NULL) 478 return -1; 479 if (test_vec->digest.length < opts->digest_sz) 480 return -1; 481 } 482 483 } else if (opts->op_type == CPERF_CIPHER_THEN_AUTH || 484 opts->op_type == CPERF_AUTH_THEN_CIPHER) { 485 if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) { 486 if (test_vec->plaintext.data == NULL) 487 return -1; 488 if (test_vec->plaintext.length < opts->max_buffer_size) 489 return -1; 490 } else { 491 if (test_vec->plaintext.data == NULL) 492 return -1; 493 if (test_vec->plaintext.length < opts->max_buffer_size) 494 return -1; 495 if (test_vec->ciphertext.data == NULL) 496 return -1; 497 if (test_vec->ciphertext.length < opts->max_buffer_size) 498 return -1; 499 if (test_vec->cipher_iv.data == NULL) 500 return -1; 501 if (test_vec->cipher_iv.length != opts->cipher_iv_sz) 502 return -1; 503 if (test_vec->cipher_key.data == NULL) 504 return -1; 505 if (test_vec->cipher_key.length != opts->cipher_key_sz) 506 return -1; 507 } 508 if (opts->auth_algo != RTE_CRYPTO_AUTH_NULL) { 509 if (test_vec->auth_key.data == NULL) 510 return -1; 511 if (test_vec->auth_key.length != opts->auth_key_sz) 512 return -1; 513 if (test_vec->auth_iv.length != opts->auth_iv_sz) 514 return -1; 515 /* Auth IV is only required for some algorithms */ 516 if (opts->auth_iv_sz && test_vec->auth_iv.data == NULL) 517 return -1; 518 if (test_vec->digest.data == NULL) 519 return -1; 520 if (test_vec->digest.length < opts->digest_sz) 521 return -1; 522 } 523 } else if (opts->op_type == CPERF_AEAD) { 524 if (test_vec->plaintext.data == NULL) 525 return -1; 526 if (test_vec->plaintext.length < opts->max_buffer_size) 527 return -1; 528 if (test_vec->ciphertext.data == NULL) 529 return -1; 530 if (test_vec->ciphertext.length < opts->max_buffer_size) 531 return -1; 532 if (test_vec->aead_key.data == NULL) 533 return -1; 534 if (test_vec->aead_key.length != opts->aead_key_sz) 535 return -1; 536 if (test_vec->aead_iv.data == NULL) 537 return -1; 538 if (test_vec->aead_iv.length != opts->aead_iv_sz) 539 return -1; 540 if (test_vec->aad.data == NULL) 541 return -1; 542 if (test_vec->aad.length != opts->aead_aad_sz) 543 return -1; 544 if (test_vec->digest.data == NULL) 545 return -1; 546 if (test_vec->digest.length < opts->digest_sz) 547 return -1; 548 } 549 return 0; 550 } 551 552 int 553 main(int argc, char **argv) 554 { 555 struct cperf_options opts = {0}; 556 struct cperf_test_vector *t_vec = NULL; 557 struct cperf_op_fns op_fns; 558 void *ctx[RTE_MAX_LCORE] = { }; 559 int nb_cryptodevs = 0; 560 uint16_t total_nb_qps = 0; 561 uint8_t cdev_id, i; 562 uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS] = { 0 }; 563 564 uint8_t buffer_size_idx = 0; 565 566 int ret; 567 uint32_t lcore_id; 568 569 /* Initialise DPDK EAL */ 570 ret = rte_eal_init(argc, argv); 571 if (ret < 0) 572 rte_exit(EXIT_FAILURE, "Invalid EAL arguments!\n"); 573 argc -= ret; 574 argv += ret; 575 576 cperf_options_default(&opts); 577 578 ret = cperf_options_parse(&opts, argc, argv); 579 if (ret) { 580 RTE_LOG(ERR, USER1, "Parsing one or more user options failed\n"); 581 goto err; 582 } 583 584 ret = cperf_options_check(&opts); 585 if (ret) { 586 RTE_LOG(ERR, USER1, 587 "Checking one or more user options failed\n"); 588 goto err; 589 } 590 591 nb_cryptodevs = cperf_initialize_cryptodev(&opts, enabled_cdevs); 592 593 if (!opts.silent) 594 cperf_options_dump(&opts); 595 596 if (nb_cryptodevs < 1) { 597 RTE_LOG(ERR, USER1, "Failed to initialise requested crypto " 598 "device type\n"); 599 nb_cryptodevs = 0; 600 goto err; 601 } 602 603 ret = cperf_verify_devices_capabilities(&opts, enabled_cdevs, 604 nb_cryptodevs); 605 if (ret) { 606 RTE_LOG(ERR, USER1, "Crypto device type does not support " 607 "capabilities requested\n"); 608 goto err; 609 } 610 611 if (opts.test_file != NULL) { 612 t_vec = cperf_test_vector_get_from_file(&opts); 613 if (t_vec == NULL) { 614 RTE_LOG(ERR, USER1, 615 "Failed to create test vector for" 616 " specified file\n"); 617 goto err; 618 } 619 620 if (cperf_check_test_vector(&opts, t_vec)) { 621 RTE_LOG(ERR, USER1, "Incomplete necessary test vectors" 622 "\n"); 623 goto err; 624 } 625 } else { 626 t_vec = cperf_test_vector_get_dummy(&opts); 627 if (t_vec == NULL) { 628 RTE_LOG(ERR, USER1, 629 "Failed to create test vector for" 630 " specified algorithms\n"); 631 goto err; 632 } 633 } 634 635 ret = cperf_get_op_functions(&opts, &op_fns); 636 if (ret) { 637 RTE_LOG(ERR, USER1, "Failed to find function ops set for " 638 "specified algorithms combination\n"); 639 goto err; 640 } 641 642 if (!opts.silent && opts.test != CPERF_TEST_TYPE_THROUGHPUT && 643 opts.test != CPERF_TEST_TYPE_LATENCY) 644 show_test_vector(t_vec); 645 646 total_nb_qps = nb_cryptodevs * opts.nb_qps; 647 648 i = 0; 649 uint8_t qp_id = 0, cdev_index = 0; 650 RTE_LCORE_FOREACH_WORKER(lcore_id) { 651 652 if (i == total_nb_qps) 653 break; 654 655 cdev_id = enabled_cdevs[cdev_index]; 656 657 uint8_t socket_id = rte_cryptodev_socket_id(cdev_id); 658 659 ctx[i] = cperf_testmap[opts.test].constructor( 660 session_pool_socket[socket_id].sess_mp, 661 cdev_id, qp_id, 662 &opts, t_vec, &op_fns); 663 if (ctx[i] == NULL) { 664 RTE_LOG(ERR, USER1, "Test run constructor failed\n"); 665 goto err; 666 } 667 qp_id = (qp_id + 1) % opts.nb_qps; 668 if (qp_id == 0) 669 cdev_index++; 670 i++; 671 } 672 673 if (opts.imix_distribution_count != 0) { 674 uint8_t buffer_size_count = opts.buffer_size_count; 675 uint16_t distribution_total[buffer_size_count]; 676 uint32_t op_idx; 677 uint32_t test_average_size = 0; 678 const uint32_t *buffer_size_list = opts.buffer_size_list; 679 const uint32_t *imix_distribution_list = opts.imix_distribution_list; 680 681 opts.imix_buffer_sizes = rte_malloc(NULL, 682 sizeof(uint32_t) * opts.pool_sz, 683 0); 684 /* 685 * Calculate accumulated distribution of 686 * probabilities per packet size 687 */ 688 distribution_total[0] = imix_distribution_list[0]; 689 for (i = 1; i < buffer_size_count; i++) 690 distribution_total[i] = imix_distribution_list[i] + 691 distribution_total[i-1]; 692 693 /* Calculate a random sequence of packet sizes, based on distribution */ 694 for (op_idx = 0; op_idx < opts.pool_sz; op_idx++) { 695 uint16_t random_number = rte_rand() % 696 distribution_total[buffer_size_count - 1]; 697 for (i = 0; i < buffer_size_count; i++) 698 if (random_number < distribution_total[i]) 699 break; 700 701 opts.imix_buffer_sizes[op_idx] = buffer_size_list[i]; 702 } 703 704 /* Calculate average buffer size for the IMIX distribution */ 705 for (i = 0; i < buffer_size_count; i++) 706 test_average_size += buffer_size_list[i] * 707 imix_distribution_list[i]; 708 709 opts.test_buffer_size = test_average_size / 710 distribution_total[buffer_size_count - 1]; 711 712 i = 0; 713 RTE_LCORE_FOREACH_WORKER(lcore_id) { 714 715 if (i == total_nb_qps) 716 break; 717 718 rte_eal_remote_launch(cperf_testmap[opts.test].runner, 719 ctx[i], lcore_id); 720 i++; 721 } 722 i = 0; 723 RTE_LCORE_FOREACH_WORKER(lcore_id) { 724 725 if (i == total_nb_qps) 726 break; 727 ret |= rte_eal_wait_lcore(lcore_id); 728 i++; 729 } 730 731 if (ret != EXIT_SUCCESS) 732 goto err; 733 } else { 734 735 /* Get next size from range or list */ 736 if (opts.inc_buffer_size != 0) 737 opts.test_buffer_size = opts.min_buffer_size; 738 else 739 opts.test_buffer_size = opts.buffer_size_list[0]; 740 741 while (opts.test_buffer_size <= opts.max_buffer_size) { 742 i = 0; 743 RTE_LCORE_FOREACH_WORKER(lcore_id) { 744 745 if (i == total_nb_qps) 746 break; 747 748 rte_eal_remote_launch(cperf_testmap[opts.test].runner, 749 ctx[i], lcore_id); 750 i++; 751 } 752 i = 0; 753 RTE_LCORE_FOREACH_WORKER(lcore_id) { 754 755 if (i == total_nb_qps) 756 break; 757 ret |= rte_eal_wait_lcore(lcore_id); 758 i++; 759 } 760 761 if (ret != EXIT_SUCCESS) 762 goto err; 763 764 /* Get next size from range or list */ 765 if (opts.inc_buffer_size != 0) 766 opts.test_buffer_size += opts.inc_buffer_size; 767 else { 768 if (++buffer_size_idx == opts.buffer_size_count) 769 break; 770 opts.test_buffer_size = 771 opts.buffer_size_list[buffer_size_idx]; 772 } 773 } 774 } 775 776 i = 0; 777 RTE_LCORE_FOREACH_WORKER(lcore_id) { 778 779 if (i == total_nb_qps) 780 break; 781 782 cperf_testmap[opts.test].destructor(ctx[i]); 783 i++; 784 } 785 786 for (i = 0; i < nb_cryptodevs && 787 i < RTE_CRYPTO_MAX_DEVS; i++) { 788 rte_cryptodev_stop(enabled_cdevs[i]); 789 ret = rte_cryptodev_close(enabled_cdevs[i]); 790 if (ret) 791 RTE_LOG(ERR, USER1, 792 "Crypto device close error %d\n", ret); 793 } 794 795 free_test_vector(t_vec, &opts); 796 797 printf("\n"); 798 return EXIT_SUCCESS; 799 800 err: 801 i = 0; 802 RTE_LCORE_FOREACH_WORKER(lcore_id) { 803 if (i == total_nb_qps) 804 break; 805 806 if (ctx[i] && cperf_testmap[opts.test].destructor) 807 cperf_testmap[opts.test].destructor(ctx[i]); 808 i++; 809 } 810 811 for (i = 0; i < nb_cryptodevs && 812 i < RTE_CRYPTO_MAX_DEVS; i++) { 813 rte_cryptodev_stop(enabled_cdevs[i]); 814 ret = rte_cryptodev_close(enabled_cdevs[i]); 815 if (ret) 816 RTE_LOG(ERR, USER1, 817 "Crypto device close error %d\n", ret); 818 819 } 820 rte_free(opts.imix_buffer_sizes); 821 free_test_vector(t_vec, &opts); 822 823 printf("\n"); 824 return EXIT_FAILURE; 825 } 826