1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Cavium, Inc 3 */ 4 5 #include "test_perf_common.h" 6 7 int 8 perf_test_result(struct evt_test *test, struct evt_options *opt) 9 { 10 RTE_SET_USED(opt); 11 int i; 12 uint64_t total = 0; 13 struct test_perf *t = evt_test_priv(test); 14 15 printf("Packet distribution across worker cores :\n"); 16 for (i = 0; i < t->nb_workers; i++) 17 total += t->worker[i].processed_pkts; 18 for (i = 0; i < t->nb_workers; i++) 19 printf("Worker %d packets: "CLGRN"%"PRIx64" "CLNRM"percentage:" 20 CLGRN" %3.2f\n"CLNRM, i, 21 t->worker[i].processed_pkts, 22 (((double)t->worker[i].processed_pkts)/total) 23 * 100); 24 25 return t->result; 26 } 27 28 static inline int 29 perf_producer(void *arg) 30 { 31 int i; 32 struct prod_data *p = arg; 33 struct test_perf *t = p->t; 34 struct evt_options *opt = t->opt; 35 const uint8_t dev_id = p->dev_id; 36 const uint8_t port = p->port_id; 37 struct rte_mempool *pool = t->pool; 38 const uint64_t nb_pkts = t->nb_pkts; 39 const uint32_t nb_flows = t->nb_flows; 40 uint32_t flow_counter = 0; 41 uint64_t count = 0; 42 struct perf_elt *m[BURST_SIZE + 1] = {NULL}; 43 struct rte_event ev; 44 45 if (opt->verbose_level > 1) 46 printf("%s(): lcore %d dev_id %d port=%d queue %d\n", __func__, 47 rte_lcore_id(), dev_id, port, p->queue_id); 48 49 ev.event = 0; 50 ev.op = RTE_EVENT_OP_NEW; 51 ev.queue_id = p->queue_id; 52 ev.sched_type = t->opt->sched_type_list[0]; 53 ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL; 54 ev.event_type = RTE_EVENT_TYPE_CPU; 55 ev.sub_event_type = 0; /* stage 0 */ 56 57 while (count < nb_pkts && t->done == false) { 58 if (rte_mempool_get_bulk(pool, (void **)m, BURST_SIZE) < 0) 59 continue; 60 for (i = 0; i < BURST_SIZE; i++) { 61 ev.flow_id = flow_counter++ % nb_flows; 62 ev.event_ptr = m[i]; 63 m[i]->timestamp = rte_get_timer_cycles(); 64 while (rte_event_enqueue_burst(dev_id, 65 port, &ev, 1) != 1) { 66 if (t->done) 67 break; 68 rte_pause(); 69 m[i]->timestamp = rte_get_timer_cycles(); 70 } 71 } 72 count += BURST_SIZE; 73 } 74 75 return 0; 76 } 77 78 static inline int 79 perf_event_timer_producer(void *arg) 80 { 81 int i; 82 struct prod_data *p = arg; 83 struct test_perf *t = p->t; 84 struct evt_options *opt = t->opt; 85 uint32_t flow_counter = 0; 86 uint64_t count = 0; 87 uint64_t arm_latency = 0; 88 const uint8_t nb_timer_adptrs = opt->nb_timer_adptrs; 89 const uint32_t nb_flows = t->nb_flows; 90 const uint64_t nb_timers = opt->nb_timers; 91 struct rte_mempool *pool = t->pool; 92 struct perf_elt *m[BURST_SIZE + 1] = {NULL}; 93 struct rte_event_timer_adapter **adptr = t->timer_adptr; 94 struct rte_event_timer tim; 95 uint64_t timeout_ticks = opt->expiry_nsec / opt->timer_tick_nsec; 96 97 memset(&tim, 0, sizeof(struct rte_event_timer)); 98 timeout_ticks = opt->optm_timer_tick_nsec ? 99 (timeout_ticks * opt->timer_tick_nsec) 100 / opt->optm_timer_tick_nsec : timeout_ticks; 101 timeout_ticks += timeout_ticks ? 0 : 1; 102 tim.ev.event_type = RTE_EVENT_TYPE_TIMER; 103 tim.ev.op = RTE_EVENT_OP_NEW; 104 tim.ev.sched_type = t->opt->sched_type_list[0]; 105 tim.ev.queue_id = p->queue_id; 106 tim.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL; 107 tim.state = RTE_EVENT_TIMER_NOT_ARMED; 108 tim.timeout_ticks = timeout_ticks; 109 110 if (opt->verbose_level > 1) 111 printf("%s(): lcore %d\n", __func__, rte_lcore_id()); 112 113 while (count < nb_timers && t->done == false) { 114 if (rte_mempool_get_bulk(pool, (void **)m, BURST_SIZE) < 0) 115 continue; 116 for (i = 0; i < BURST_SIZE; i++) { 117 rte_prefetch0(m[i + 1]); 118 m[i]->tim = tim; 119 m[i]->tim.ev.flow_id = flow_counter++ % nb_flows; 120 m[i]->tim.ev.event_ptr = m[i]; 121 m[i]->timestamp = rte_get_timer_cycles(); 122 while (rte_event_timer_arm_burst( 123 adptr[flow_counter % nb_timer_adptrs], 124 (struct rte_event_timer **)&m[i], 1) != 1) { 125 if (t->done) 126 break; 127 m[i]->timestamp = rte_get_timer_cycles(); 128 } 129 arm_latency += rte_get_timer_cycles() - m[i]->timestamp; 130 } 131 count += BURST_SIZE; 132 } 133 fflush(stdout); 134 rte_delay_ms(1000); 135 printf("%s(): lcore %d Average event timer arm latency = %.3f us\n", 136 __func__, rte_lcore_id(), 137 count ? (float)(arm_latency / count) / 138 (rte_get_timer_hz() / 1000000) : 0); 139 return 0; 140 } 141 142 static inline int 143 perf_event_timer_producer_burst(void *arg) 144 { 145 int i; 146 struct prod_data *p = arg; 147 struct test_perf *t = p->t; 148 struct evt_options *opt = t->opt; 149 uint32_t flow_counter = 0; 150 uint64_t count = 0; 151 uint64_t arm_latency = 0; 152 const uint8_t nb_timer_adptrs = opt->nb_timer_adptrs; 153 const uint32_t nb_flows = t->nb_flows; 154 const uint64_t nb_timers = opt->nb_timers; 155 struct rte_mempool *pool = t->pool; 156 struct perf_elt *m[BURST_SIZE + 1] = {NULL}; 157 struct rte_event_timer_adapter **adptr = t->timer_adptr; 158 struct rte_event_timer tim; 159 uint64_t timeout_ticks = opt->expiry_nsec / opt->timer_tick_nsec; 160 161 memset(&tim, 0, sizeof(struct rte_event_timer)); 162 timeout_ticks = opt->optm_timer_tick_nsec ? 163 (timeout_ticks * opt->timer_tick_nsec) 164 / opt->optm_timer_tick_nsec : timeout_ticks; 165 timeout_ticks += timeout_ticks ? 0 : 1; 166 tim.ev.event_type = RTE_EVENT_TYPE_TIMER; 167 tim.ev.op = RTE_EVENT_OP_NEW; 168 tim.ev.sched_type = t->opt->sched_type_list[0]; 169 tim.ev.queue_id = p->queue_id; 170 tim.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL; 171 tim.state = RTE_EVENT_TIMER_NOT_ARMED; 172 tim.timeout_ticks = timeout_ticks; 173 174 if (opt->verbose_level > 1) 175 printf("%s(): lcore %d\n", __func__, rte_lcore_id()); 176 177 while (count < nb_timers && t->done == false) { 178 if (rte_mempool_get_bulk(pool, (void **)m, BURST_SIZE) < 0) 179 continue; 180 for (i = 0; i < BURST_SIZE; i++) { 181 rte_prefetch0(m[i + 1]); 182 m[i]->tim = tim; 183 m[i]->tim.ev.flow_id = flow_counter++ % nb_flows; 184 m[i]->tim.ev.event_ptr = m[i]; 185 m[i]->timestamp = rte_get_timer_cycles(); 186 } 187 rte_event_timer_arm_tmo_tick_burst( 188 adptr[flow_counter % nb_timer_adptrs], 189 (struct rte_event_timer **)m, 190 tim.timeout_ticks, 191 BURST_SIZE); 192 arm_latency += rte_get_timer_cycles() - m[i - 1]->timestamp; 193 count += BURST_SIZE; 194 } 195 fflush(stdout); 196 rte_delay_ms(1000); 197 printf("%s(): lcore %d Average event timer arm latency = %.3f us\n", 198 __func__, rte_lcore_id(), 199 count ? (float)(arm_latency / count) / 200 (rte_get_timer_hz() / 1000000) : 0); 201 return 0; 202 } 203 204 static int 205 perf_producer_wrapper(void *arg) 206 { 207 struct prod_data *p = arg; 208 struct test_perf *t = p->t; 209 /* Launch the producer function only in case of synthetic producer. */ 210 if (t->opt->prod_type == EVT_PROD_TYPE_SYNT) 211 return perf_producer(arg); 212 else if (t->opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR && 213 !t->opt->timdev_use_burst) 214 return perf_event_timer_producer(arg); 215 else if (t->opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR && 216 t->opt->timdev_use_burst) 217 return perf_event_timer_producer_burst(arg); 218 return 0; 219 } 220 221 static inline uint64_t 222 processed_pkts(struct test_perf *t) 223 { 224 uint8_t i; 225 uint64_t total = 0; 226 227 for (i = 0; i < t->nb_workers; i++) 228 total += t->worker[i].processed_pkts; 229 230 return total; 231 } 232 233 static inline uint64_t 234 total_latency(struct test_perf *t) 235 { 236 uint8_t i; 237 uint64_t total = 0; 238 239 for (i = 0; i < t->nb_workers; i++) 240 total += t->worker[i].latency; 241 242 return total; 243 } 244 245 246 int 247 perf_launch_lcores(struct evt_test *test, struct evt_options *opt, 248 int (*worker)(void *)) 249 { 250 int ret, lcore_id; 251 struct test_perf *t = evt_test_priv(test); 252 253 int port_idx = 0; 254 /* launch workers */ 255 RTE_LCORE_FOREACH_WORKER(lcore_id) { 256 if (!(opt->wlcores[lcore_id])) 257 continue; 258 259 ret = rte_eal_remote_launch(worker, 260 &t->worker[port_idx], lcore_id); 261 if (ret) { 262 evt_err("failed to launch worker %d", lcore_id); 263 return ret; 264 } 265 port_idx++; 266 } 267 268 /* launch producers */ 269 RTE_LCORE_FOREACH_WORKER(lcore_id) { 270 if (!(opt->plcores[lcore_id])) 271 continue; 272 273 ret = rte_eal_remote_launch(perf_producer_wrapper, 274 &t->prod[port_idx], lcore_id); 275 if (ret) { 276 evt_err("failed to launch perf_producer %d", lcore_id); 277 return ret; 278 } 279 port_idx++; 280 } 281 282 const uint64_t total_pkts = t->outstand_pkts; 283 284 uint64_t dead_lock_cycles = rte_get_timer_cycles(); 285 int64_t dead_lock_remaining = total_pkts; 286 const uint64_t dead_lock_sample = rte_get_timer_hz() * 5; 287 288 uint64_t perf_cycles = rte_get_timer_cycles(); 289 int64_t perf_remaining = total_pkts; 290 const uint64_t perf_sample = rte_get_timer_hz(); 291 292 static float total_mpps; 293 static uint64_t samples; 294 295 const uint64_t freq_mhz = rte_get_timer_hz() / 1000000; 296 int64_t remaining = t->outstand_pkts - processed_pkts(t); 297 298 while (t->done == false) { 299 const uint64_t new_cycles = rte_get_timer_cycles(); 300 301 if ((new_cycles - perf_cycles) > perf_sample) { 302 const uint64_t latency = total_latency(t); 303 const uint64_t pkts = processed_pkts(t); 304 305 remaining = t->outstand_pkts - pkts; 306 float mpps = (float)(perf_remaining-remaining)/1000000; 307 308 perf_remaining = remaining; 309 perf_cycles = new_cycles; 310 total_mpps += mpps; 311 ++samples; 312 if (opt->fwd_latency && pkts > 0) { 313 printf(CLGRN"\r%.3f mpps avg %.3f mpps [avg fwd latency %.3f us] "CLNRM, 314 mpps, total_mpps/samples, 315 (float)(latency/pkts)/freq_mhz); 316 } else { 317 printf(CLGRN"\r%.3f mpps avg %.3f mpps"CLNRM, 318 mpps, total_mpps/samples); 319 } 320 fflush(stdout); 321 322 if (remaining <= 0) { 323 t->result = EVT_TEST_SUCCESS; 324 if (opt->prod_type == EVT_PROD_TYPE_SYNT || 325 opt->prod_type == 326 EVT_PROD_TYPE_EVENT_TIMER_ADPTR) { 327 t->done = true; 328 break; 329 } 330 } 331 } 332 333 if (new_cycles - dead_lock_cycles > dead_lock_sample && 334 (opt->prod_type == EVT_PROD_TYPE_SYNT || 335 opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR)) { 336 remaining = t->outstand_pkts - processed_pkts(t); 337 if (dead_lock_remaining == remaining) { 338 rte_event_dev_dump(opt->dev_id, stdout); 339 evt_err("No schedules for seconds, deadlock"); 340 t->done = true; 341 break; 342 } 343 dead_lock_remaining = remaining; 344 dead_lock_cycles = new_cycles; 345 } 346 } 347 printf("\n"); 348 return 0; 349 } 350 351 static int 352 perf_event_rx_adapter_setup(struct evt_options *opt, uint8_t stride, 353 struct rte_event_port_conf prod_conf) 354 { 355 int ret = 0; 356 uint16_t prod; 357 struct rte_event_eth_rx_adapter_queue_conf queue_conf; 358 359 memset(&queue_conf, 0, 360 sizeof(struct rte_event_eth_rx_adapter_queue_conf)); 361 queue_conf.ev.sched_type = opt->sched_type_list[0]; 362 RTE_ETH_FOREACH_DEV(prod) { 363 uint32_t cap; 364 365 ret = rte_event_eth_rx_adapter_caps_get(opt->dev_id, 366 prod, &cap); 367 if (ret) { 368 evt_err("failed to get event rx adapter[%d]" 369 " capabilities", 370 opt->dev_id); 371 return ret; 372 } 373 queue_conf.ev.queue_id = prod * stride; 374 ret = rte_event_eth_rx_adapter_create(prod, opt->dev_id, 375 &prod_conf); 376 if (ret) { 377 evt_err("failed to create rx adapter[%d]", prod); 378 return ret; 379 } 380 ret = rte_event_eth_rx_adapter_queue_add(prod, prod, -1, 381 &queue_conf); 382 if (ret) { 383 evt_err("failed to add rx queues to adapter[%d]", prod); 384 return ret; 385 } 386 387 if (!(cap & RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT)) { 388 uint32_t service_id; 389 390 rte_event_eth_rx_adapter_service_id_get(prod, 391 &service_id); 392 ret = evt_service_setup(service_id); 393 if (ret) { 394 evt_err("Failed to setup service core" 395 " for Rx adapter\n"); 396 return ret; 397 } 398 } 399 } 400 401 return ret; 402 } 403 404 static int 405 perf_event_timer_adapter_setup(struct test_perf *t) 406 { 407 int i; 408 int ret; 409 struct rte_event_timer_adapter_info adapter_info; 410 struct rte_event_timer_adapter *wl; 411 uint8_t nb_producers = evt_nr_active_lcores(t->opt->plcores); 412 uint8_t flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES; 413 414 if (nb_producers == 1) 415 flags |= RTE_EVENT_TIMER_ADAPTER_F_SP_PUT; 416 417 for (i = 0; i < t->opt->nb_timer_adptrs; i++) { 418 struct rte_event_timer_adapter_conf config = { 419 .event_dev_id = t->opt->dev_id, 420 .timer_adapter_id = i, 421 .timer_tick_ns = t->opt->timer_tick_nsec, 422 .max_tmo_ns = t->opt->max_tmo_nsec, 423 .nb_timers = t->opt->pool_sz, 424 .flags = flags, 425 }; 426 427 wl = rte_event_timer_adapter_create(&config); 428 if (wl == NULL) { 429 evt_err("failed to create event timer ring %d", i); 430 return rte_errno; 431 } 432 433 memset(&adapter_info, 0, 434 sizeof(struct rte_event_timer_adapter_info)); 435 rte_event_timer_adapter_get_info(wl, &adapter_info); 436 t->opt->optm_timer_tick_nsec = adapter_info.min_resolution_ns; 437 438 if (!(adapter_info.caps & 439 RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT)) { 440 uint32_t service_id = -1U; 441 442 rte_event_timer_adapter_service_id_get(wl, 443 &service_id); 444 ret = evt_service_setup(service_id); 445 if (ret) { 446 evt_err("Failed to setup service core" 447 " for timer adapter\n"); 448 return ret; 449 } 450 rte_service_runstate_set(service_id, 1); 451 } 452 t->timer_adptr[i] = wl; 453 } 454 return 0; 455 } 456 457 int 458 perf_event_dev_port_setup(struct evt_test *test, struct evt_options *opt, 459 uint8_t stride, uint8_t nb_queues, 460 const struct rte_event_port_conf *port_conf) 461 { 462 struct test_perf *t = evt_test_priv(test); 463 uint16_t port, prod; 464 int ret = -1; 465 466 /* setup one port per worker, linking to all queues */ 467 for (port = 0; port < evt_nr_active_lcores(opt->wlcores); 468 port++) { 469 struct worker_data *w = &t->worker[port]; 470 471 w->dev_id = opt->dev_id; 472 w->port_id = port; 473 w->t = t; 474 w->processed_pkts = 0; 475 w->latency = 0; 476 477 ret = rte_event_port_setup(opt->dev_id, port, port_conf); 478 if (ret) { 479 evt_err("failed to setup port %d", port); 480 return ret; 481 } 482 483 ret = rte_event_port_link(opt->dev_id, port, NULL, NULL, 0); 484 if (ret != nb_queues) { 485 evt_err("failed to link all queues to port %d", port); 486 return -EINVAL; 487 } 488 } 489 490 /* port for producers, no links */ 491 if (opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR) { 492 for ( ; port < perf_nb_event_ports(opt); port++) { 493 struct prod_data *p = &t->prod[port]; 494 p->t = t; 495 } 496 497 ret = perf_event_rx_adapter_setup(opt, stride, *port_conf); 498 if (ret) 499 return ret; 500 } else if (opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) { 501 prod = 0; 502 for ( ; port < perf_nb_event_ports(opt); port++) { 503 struct prod_data *p = &t->prod[port]; 504 p->queue_id = prod * stride; 505 p->t = t; 506 prod++; 507 } 508 509 ret = perf_event_timer_adapter_setup(t); 510 if (ret) 511 return ret; 512 } else { 513 prod = 0; 514 for ( ; port < perf_nb_event_ports(opt); port++) { 515 struct prod_data *p = &t->prod[port]; 516 517 p->dev_id = opt->dev_id; 518 p->port_id = port; 519 p->queue_id = prod * stride; 520 p->t = t; 521 522 ret = rte_event_port_setup(opt->dev_id, port, 523 port_conf); 524 if (ret) { 525 evt_err("failed to setup port %d", port); 526 return ret; 527 } 528 prod++; 529 } 530 } 531 532 return ret; 533 } 534 535 int 536 perf_opt_check(struct evt_options *opt, uint64_t nb_queues) 537 { 538 unsigned int lcores; 539 540 /* N producer + N worker + main when producer cores are used 541 * Else N worker + main when Rx adapter is used 542 */ 543 lcores = opt->prod_type == EVT_PROD_TYPE_SYNT ? 3 : 2; 544 545 if (rte_lcore_count() < lcores) { 546 evt_err("test need minimum %d lcores", lcores); 547 return -1; 548 } 549 550 /* Validate worker lcores */ 551 if (evt_lcores_has_overlap(opt->wlcores, rte_get_main_lcore())) { 552 evt_err("worker lcores overlaps with main lcore"); 553 return -1; 554 } 555 if (evt_lcores_has_overlap_multi(opt->wlcores, opt->plcores)) { 556 evt_err("worker lcores overlaps producer lcores"); 557 return -1; 558 } 559 if (evt_has_disabled_lcore(opt->wlcores)) { 560 evt_err("one or more workers lcores are not enabled"); 561 return -1; 562 } 563 if (!evt_has_active_lcore(opt->wlcores)) { 564 evt_err("minimum one worker is required"); 565 return -1; 566 } 567 568 if (opt->prod_type == EVT_PROD_TYPE_SYNT || 569 opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) { 570 /* Validate producer lcores */ 571 if (evt_lcores_has_overlap(opt->plcores, 572 rte_get_main_lcore())) { 573 evt_err("producer lcores overlaps with main lcore"); 574 return -1; 575 } 576 if (evt_has_disabled_lcore(opt->plcores)) { 577 evt_err("one or more producer lcores are not enabled"); 578 return -1; 579 } 580 if (!evt_has_active_lcore(opt->plcores)) { 581 evt_err("minimum one producer is required"); 582 return -1; 583 } 584 } 585 586 if (evt_has_invalid_stage(opt)) 587 return -1; 588 589 if (evt_has_invalid_sched_type(opt)) 590 return -1; 591 592 if (nb_queues > EVT_MAX_QUEUES) { 593 evt_err("number of queues exceeds %d", EVT_MAX_QUEUES); 594 return -1; 595 } 596 if (perf_nb_event_ports(opt) > EVT_MAX_PORTS) { 597 evt_err("number of ports exceeds %d", EVT_MAX_PORTS); 598 return -1; 599 } 600 601 /* Fixups */ 602 if ((opt->nb_stages == 1 && 603 opt->prod_type != EVT_PROD_TYPE_EVENT_TIMER_ADPTR) && 604 opt->fwd_latency) { 605 evt_info("fwd_latency is valid when nb_stages > 1, disabling"); 606 opt->fwd_latency = 0; 607 } 608 609 if (opt->fwd_latency && !opt->q_priority) { 610 evt_info("enabled queue priority for latency measurement"); 611 opt->q_priority = 1; 612 } 613 if (opt->nb_pkts == 0) 614 opt->nb_pkts = INT64_MAX/evt_nr_active_lcores(opt->plcores); 615 616 return 0; 617 } 618 619 void 620 perf_opt_dump(struct evt_options *opt, uint8_t nb_queues) 621 { 622 evt_dump("nb_prod_lcores", "%d", evt_nr_active_lcores(opt->plcores)); 623 evt_dump_producer_lcores(opt); 624 evt_dump("nb_worker_lcores", "%d", evt_nr_active_lcores(opt->wlcores)); 625 evt_dump_worker_lcores(opt); 626 evt_dump_nb_stages(opt); 627 evt_dump("nb_evdev_ports", "%d", perf_nb_event_ports(opt)); 628 evt_dump("nb_evdev_queues", "%d", nb_queues); 629 evt_dump_queue_priority(opt); 630 evt_dump_sched_type_list(opt); 631 evt_dump_producer_type(opt); 632 } 633 634 void 635 perf_eventdev_destroy(struct evt_test *test, struct evt_options *opt) 636 { 637 int i; 638 struct test_perf *t = evt_test_priv(test); 639 640 if (opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) { 641 for (i = 0; i < opt->nb_timer_adptrs; i++) 642 rte_event_timer_adapter_stop(t->timer_adptr[i]); 643 } 644 rte_event_dev_stop(opt->dev_id); 645 rte_event_dev_close(opt->dev_id); 646 } 647 648 static inline void 649 perf_elt_init(struct rte_mempool *mp, void *arg __rte_unused, 650 void *obj, unsigned i __rte_unused) 651 { 652 memset(obj, 0, mp->elt_size); 653 } 654 655 #define NB_RX_DESC 128 656 #define NB_TX_DESC 512 657 int 658 perf_ethdev_setup(struct evt_test *test, struct evt_options *opt) 659 { 660 uint16_t i; 661 int ret; 662 struct test_perf *t = evt_test_priv(test); 663 struct rte_eth_conf port_conf = { 664 .rxmode = { 665 .mq_mode = ETH_MQ_RX_RSS, 666 .max_rx_pkt_len = RTE_ETHER_MAX_LEN, 667 .split_hdr_size = 0, 668 }, 669 .rx_adv_conf = { 670 .rss_conf = { 671 .rss_key = NULL, 672 .rss_hf = ETH_RSS_IP, 673 }, 674 }, 675 }; 676 677 if (opt->prod_type == EVT_PROD_TYPE_SYNT || 678 opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) 679 return 0; 680 681 if (!rte_eth_dev_count_avail()) { 682 evt_err("No ethernet ports found."); 683 return -ENODEV; 684 } 685 686 RTE_ETH_FOREACH_DEV(i) { 687 struct rte_eth_dev_info dev_info; 688 struct rte_eth_conf local_port_conf = port_conf; 689 690 ret = rte_eth_dev_info_get(i, &dev_info); 691 if (ret != 0) { 692 evt_err("Error during getting device (port %u) info: %s\n", 693 i, strerror(-ret)); 694 return ret; 695 } 696 697 local_port_conf.rx_adv_conf.rss_conf.rss_hf &= 698 dev_info.flow_type_rss_offloads; 699 if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != 700 port_conf.rx_adv_conf.rss_conf.rss_hf) { 701 evt_info("Port %u modified RSS hash function based on hardware support," 702 "requested:%#"PRIx64" configured:%#"PRIx64"\n", 703 i, 704 port_conf.rx_adv_conf.rss_conf.rss_hf, 705 local_port_conf.rx_adv_conf.rss_conf.rss_hf); 706 } 707 708 if (rte_eth_dev_configure(i, 1, 1, &local_port_conf) < 0) { 709 evt_err("Failed to configure eth port [%d]", i); 710 return -EINVAL; 711 } 712 713 if (rte_eth_rx_queue_setup(i, 0, NB_RX_DESC, 714 rte_socket_id(), NULL, t->pool) < 0) { 715 evt_err("Failed to setup eth port [%d] rx_queue: %d.", 716 i, 0); 717 return -EINVAL; 718 } 719 720 if (rte_eth_tx_queue_setup(i, 0, NB_TX_DESC, 721 rte_socket_id(), NULL) < 0) { 722 evt_err("Failed to setup eth port [%d] tx_queue: %d.", 723 i, 0); 724 return -EINVAL; 725 } 726 727 ret = rte_eth_promiscuous_enable(i); 728 if (ret != 0) { 729 evt_err("Failed to enable promiscuous mode for eth port [%d]: %s", 730 i, rte_strerror(-ret)); 731 return ret; 732 } 733 } 734 735 return 0; 736 } 737 738 void perf_ethdev_destroy(struct evt_test *test, struct evt_options *opt) 739 { 740 uint16_t i; 741 RTE_SET_USED(test); 742 743 if (opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR) { 744 RTE_ETH_FOREACH_DEV(i) { 745 rte_event_eth_rx_adapter_stop(i); 746 rte_eth_dev_stop(i); 747 } 748 } 749 } 750 751 int 752 perf_mempool_setup(struct evt_test *test, struct evt_options *opt) 753 { 754 struct test_perf *t = evt_test_priv(test); 755 756 if (opt->prod_type == EVT_PROD_TYPE_SYNT || 757 opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) { 758 t->pool = rte_mempool_create(test->name, /* mempool name */ 759 opt->pool_sz, /* number of elements*/ 760 sizeof(struct perf_elt), /* element size*/ 761 512, /* cache size*/ 762 0, NULL, NULL, 763 perf_elt_init, /* obj constructor */ 764 NULL, opt->socket_id, 0); /* flags */ 765 } else { 766 t->pool = rte_pktmbuf_pool_create(test->name, /* mempool name */ 767 opt->pool_sz, /* number of elements*/ 768 512, /* cache size*/ 769 0, 770 RTE_MBUF_DEFAULT_BUF_SIZE, 771 opt->socket_id); /* flags */ 772 773 } 774 775 if (t->pool == NULL) { 776 evt_err("failed to create mempool"); 777 return -ENOMEM; 778 } 779 780 return 0; 781 } 782 783 void 784 perf_mempool_destroy(struct evt_test *test, struct evt_options *opt) 785 { 786 RTE_SET_USED(opt); 787 struct test_perf *t = evt_test_priv(test); 788 789 rte_mempool_free(t->pool); 790 } 791 792 int 793 perf_test_setup(struct evt_test *test, struct evt_options *opt) 794 { 795 void *test_perf; 796 797 test_perf = rte_zmalloc_socket(test->name, sizeof(struct test_perf), 798 RTE_CACHE_LINE_SIZE, opt->socket_id); 799 if (test_perf == NULL) { 800 evt_err("failed to allocate test_perf memory"); 801 goto nomem; 802 } 803 test->test_priv = test_perf; 804 805 struct test_perf *t = evt_test_priv(test); 806 807 if (opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) { 808 t->outstand_pkts = opt->nb_timers * 809 evt_nr_active_lcores(opt->plcores); 810 t->nb_pkts = opt->nb_timers; 811 } else { 812 t->outstand_pkts = opt->nb_pkts * 813 evt_nr_active_lcores(opt->plcores); 814 t->nb_pkts = opt->nb_pkts; 815 } 816 817 t->nb_workers = evt_nr_active_lcores(opt->wlcores); 818 t->done = false; 819 t->nb_flows = opt->nb_flows; 820 t->result = EVT_TEST_FAILED; 821 t->opt = opt; 822 memcpy(t->sched_type_list, opt->sched_type_list, 823 sizeof(opt->sched_type_list)); 824 return 0; 825 nomem: 826 return -ENOMEM; 827 } 828 829 void 830 perf_test_destroy(struct evt_test *test, struct evt_options *opt) 831 { 832 RTE_SET_USED(opt); 833 834 rte_free(test->test_priv); 835 } 836