1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2016-2017 Intel Corporation 3 */ 4 5 #include <stdalign.h> 6 #include <stdio.h> 7 #include <string.h> 8 #include <stdint.h> 9 #include <stdlib.h> 10 #include <errno.h> 11 #include <unistd.h> 12 #include <sys/queue.h> 13 14 #include <rte_memory.h> 15 #include <rte_launch.h> 16 #include <rte_eal.h> 17 #include <rte_per_lcore.h> 18 #include <rte_lcore.h> 19 #include <rte_debug.h> 20 #include <rte_ethdev.h> 21 #include <rte_cycles.h> 22 #include <rte_eventdev.h> 23 #include <rte_pause.h> 24 #include <rte_service.h> 25 #include <rte_service_component.h> 26 #include <bus_vdev_driver.h> 27 28 #include "sw_evdev.h" 29 30 #define MAX_PORTS 16 31 #define MAX_QIDS 16 32 #define NUM_PACKETS (1 << 17) 33 #define DEQUEUE_DEPTH 128 34 35 static int evdev; 36 37 struct test { 38 struct rte_mempool *mbuf_pool; 39 uint8_t port[MAX_PORTS]; 40 uint8_t qid[MAX_QIDS]; 41 int nb_qids; 42 uint32_t service_id; 43 }; 44 45 typedef uint8_t counter_dynfield_t; 46 static int counter_dynfield_offset = -1; 47 48 static inline counter_dynfield_t * 49 counter_field(struct rte_mbuf *mbuf) 50 { 51 return RTE_MBUF_DYNFIELD(mbuf, \ 52 counter_dynfield_offset, counter_dynfield_t *); 53 } 54 55 static struct rte_event release_ev; 56 57 static inline struct rte_mbuf * 58 rte_gen_arp(int portid, struct rte_mempool *mp) 59 { 60 /* 61 * len = 14 + 46 62 * ARP, Request who-has 10.0.0.1 tell 10.0.0.2, length 46 63 */ 64 static const uint8_t arp_request[] = { 65 /*0x0000:*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xa8, 66 0x6b, 0xfd, 0x02, 0x29, 0x08, 0x06, 0x00, 0x01, 67 /*0x0010:*/ 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xec, 0xa8, 68 0x6b, 0xfd, 0x02, 0x29, 0x0a, 0x00, 0x00, 0x01, 69 /*0x0020:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 70 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71 /*0x0030:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 72 0x00, 0x00, 0x00, 0x00 73 }; 74 struct rte_mbuf *m; 75 int pkt_len = sizeof(arp_request) - 1; 76 77 m = rte_pktmbuf_alloc(mp); 78 if (!m) 79 return 0; 80 81 memcpy((void *)((uintptr_t)m->buf_addr + m->data_off), 82 arp_request, pkt_len); 83 rte_pktmbuf_pkt_len(m) = pkt_len; 84 rte_pktmbuf_data_len(m) = pkt_len; 85 86 RTE_SET_USED(portid); 87 88 return m; 89 } 90 91 static void 92 xstats_print(void) 93 { 94 const uint32_t XSTATS_MAX = 1024; 95 uint32_t i; 96 uint64_t ids[XSTATS_MAX]; 97 uint64_t values[XSTATS_MAX]; 98 struct rte_event_dev_xstats_name xstats_names[XSTATS_MAX]; 99 100 for (i = 0; i < XSTATS_MAX; i++) 101 ids[i] = i; 102 103 /* Device names / values */ 104 int ret = rte_event_dev_xstats_names_get(evdev, 105 RTE_EVENT_DEV_XSTATS_DEVICE, 0, 106 xstats_names, ids, XSTATS_MAX); 107 if (ret < 0) { 108 printf("%d: xstats names get() returned error\n", 109 __LINE__); 110 return; 111 } 112 ret = rte_event_dev_xstats_get(evdev, 113 RTE_EVENT_DEV_XSTATS_DEVICE, 114 0, ids, values, ret); 115 if (ret > (signed int)XSTATS_MAX) 116 printf("%s %d: more xstats available than space\n", 117 __func__, __LINE__); 118 for (i = 0; (signed int)i < ret; i++) { 119 printf("%d : %s : %"PRIu64"\n", 120 i, xstats_names[i].name, values[i]); 121 } 122 123 /* Port names / values */ 124 ret = rte_event_dev_xstats_names_get(evdev, 125 RTE_EVENT_DEV_XSTATS_PORT, 0, 126 xstats_names, ids, XSTATS_MAX); 127 ret = rte_event_dev_xstats_get(evdev, 128 RTE_EVENT_DEV_XSTATS_PORT, 1, 129 ids, values, ret); 130 if (ret > (signed int)XSTATS_MAX) 131 printf("%s %d: more xstats available than space\n", 132 __func__, __LINE__); 133 for (i = 0; (signed int)i < ret; i++) { 134 printf("%d : %s : %"PRIu64"\n", 135 i, xstats_names[i].name, values[i]); 136 } 137 138 /* Queue names / values */ 139 ret = rte_event_dev_xstats_names_get(evdev, 140 RTE_EVENT_DEV_XSTATS_QUEUE, 0, 141 xstats_names, ids, XSTATS_MAX); 142 ret = rte_event_dev_xstats_get(evdev, 143 RTE_EVENT_DEV_XSTATS_QUEUE, 144 1, ids, values, ret); 145 if (ret > (signed int)XSTATS_MAX) 146 printf("%s %d: more xstats available than space\n", 147 __func__, __LINE__); 148 for (i = 0; (signed int)i < ret; i++) { 149 printf("%d : %s : %"PRIu64"\n", 150 i, xstats_names[i].name, values[i]); 151 } 152 } 153 154 /* initialization and config */ 155 static inline int 156 init(struct test *t, int nb_queues, int nb_ports) 157 { 158 struct rte_event_dev_config config = { 159 .nb_event_queues = nb_queues, 160 .nb_event_ports = nb_ports, 161 .nb_event_queue_flows = 1024, 162 .nb_events_limit = 4096, 163 .nb_event_port_dequeue_depth = DEQUEUE_DEPTH, 164 .nb_event_port_enqueue_depth = 128, 165 }; 166 int ret; 167 168 void *temp = t->mbuf_pool; /* save and restore mbuf pool */ 169 170 memset(t, 0, sizeof(*t)); 171 t->mbuf_pool = temp; 172 173 ret = rte_event_dev_configure(evdev, &config); 174 if (ret < 0) 175 printf("%d: Error configuring device\n", __LINE__); 176 return ret; 177 }; 178 179 static inline int 180 create_ports(struct test *t, int num_ports) 181 { 182 int i; 183 static const struct rte_event_port_conf conf = { 184 .new_event_threshold = 1024, 185 .dequeue_depth = 32, 186 .enqueue_depth = 64, 187 }; 188 if (num_ports > MAX_PORTS) 189 return -1; 190 191 for (i = 0; i < num_ports; i++) { 192 if (rte_event_port_setup(evdev, i, &conf) < 0) { 193 printf("Error setting up port %d\n", i); 194 return -1; 195 } 196 t->port[i] = i; 197 } 198 199 return 0; 200 } 201 202 static inline int 203 create_lb_qids(struct test *t, int num_qids, uint32_t flags) 204 { 205 int i; 206 207 /* Q creation */ 208 const struct rte_event_queue_conf conf = { 209 .schedule_type = flags, 210 .priority = RTE_EVENT_DEV_PRIORITY_NORMAL, 211 .nb_atomic_flows = 1024, 212 .nb_atomic_order_sequences = 1024, 213 }; 214 215 for (i = t->nb_qids; i < t->nb_qids + num_qids; i++) { 216 if (rte_event_queue_setup(evdev, i, &conf) < 0) { 217 printf("%d: error creating qid %d\n", __LINE__, i); 218 return -1; 219 } 220 t->qid[i] = i; 221 } 222 t->nb_qids += num_qids; 223 if (t->nb_qids > MAX_QIDS) 224 return -1; 225 226 return 0; 227 } 228 229 static inline int 230 create_atomic_qids(struct test *t, int num_qids) 231 { 232 return create_lb_qids(t, num_qids, RTE_SCHED_TYPE_ATOMIC); 233 } 234 235 static inline int 236 create_ordered_qids(struct test *t, int num_qids) 237 { 238 return create_lb_qids(t, num_qids, RTE_SCHED_TYPE_ORDERED); 239 } 240 241 242 static inline int 243 create_unordered_qids(struct test *t, int num_qids) 244 { 245 return create_lb_qids(t, num_qids, RTE_SCHED_TYPE_PARALLEL); 246 } 247 248 static inline int 249 create_directed_qids(struct test *t, int num_qids, const uint8_t ports[]) 250 { 251 int i; 252 253 /* Q creation */ 254 static const struct rte_event_queue_conf conf = { 255 .priority = RTE_EVENT_DEV_PRIORITY_NORMAL, 256 .event_queue_cfg = RTE_EVENT_QUEUE_CFG_SINGLE_LINK, 257 }; 258 259 for (i = t->nb_qids; i < t->nb_qids + num_qids; i++) { 260 if (rte_event_queue_setup(evdev, i, &conf) < 0) { 261 printf("%d: error creating qid %d\n", __LINE__, i); 262 return -1; 263 } 264 t->qid[i] = i; 265 266 if (rte_event_port_link(evdev, ports[i - t->nb_qids], 267 &t->qid[i], NULL, 1) != 1) { 268 printf("%d: error creating link for qid %d\n", 269 __LINE__, i); 270 return -1; 271 } 272 } 273 t->nb_qids += num_qids; 274 if (t->nb_qids > MAX_QIDS) 275 return -1; 276 277 return 0; 278 } 279 280 /* destruction */ 281 static inline int 282 cleanup(struct test *t __rte_unused) 283 { 284 rte_event_dev_stop(evdev); 285 rte_event_dev_close(evdev); 286 return 0; 287 }; 288 289 struct test_event_dev_stats { 290 uint64_t rx_pkts; /**< Total packets received */ 291 uint64_t rx_dropped; /**< Total packets dropped (Eg Invalid QID) */ 292 uint64_t tx_pkts; /**< Total packets transmitted */ 293 294 /** Packets received on this port */ 295 uint64_t port_rx_pkts[MAX_PORTS]; 296 /** Packets dropped on this port */ 297 uint64_t port_rx_dropped[MAX_PORTS]; 298 /** Packets inflight on this port */ 299 uint64_t port_inflight[MAX_PORTS]; 300 /** Packets transmitted on this port */ 301 uint64_t port_tx_pkts[MAX_PORTS]; 302 /** Packets received on this qid */ 303 uint64_t qid_rx_pkts[MAX_QIDS]; 304 /** Packets dropped on this qid */ 305 uint64_t qid_rx_dropped[MAX_QIDS]; 306 /** Packets transmitted on this qid */ 307 uint64_t qid_tx_pkts[MAX_QIDS]; 308 }; 309 310 static inline int 311 test_event_dev_stats_get(int dev_id, struct test_event_dev_stats *stats) 312 { 313 static uint32_t i; 314 static uint64_t total_ids[3]; /* rx, tx and drop */ 315 static uint64_t port_rx_pkts_ids[MAX_PORTS]; 316 static uint64_t port_rx_dropped_ids[MAX_PORTS]; 317 static uint64_t port_inflight_ids[MAX_PORTS]; 318 static uint64_t port_tx_pkts_ids[MAX_PORTS]; 319 static uint64_t qid_rx_pkts_ids[MAX_QIDS]; 320 static uint64_t qid_rx_dropped_ids[MAX_QIDS]; 321 static uint64_t qid_tx_pkts_ids[MAX_QIDS]; 322 323 stats->rx_pkts = rte_event_dev_xstats_by_name_get(dev_id, 324 "dev_rx", &total_ids[0]); 325 stats->rx_dropped = rte_event_dev_xstats_by_name_get(dev_id, 326 "dev_drop", &total_ids[1]); 327 stats->tx_pkts = rte_event_dev_xstats_by_name_get(dev_id, 328 "dev_tx", &total_ids[2]); 329 for (i = 0; i < MAX_PORTS; i++) { 330 char name[32]; 331 snprintf(name, sizeof(name), "port_%u_rx", i); 332 stats->port_rx_pkts[i] = rte_event_dev_xstats_by_name_get( 333 dev_id, name, &port_rx_pkts_ids[i]); 334 snprintf(name, sizeof(name), "port_%u_drop", i); 335 stats->port_rx_dropped[i] = rte_event_dev_xstats_by_name_get( 336 dev_id, name, &port_rx_dropped_ids[i]); 337 snprintf(name, sizeof(name), "port_%u_inflight", i); 338 stats->port_inflight[i] = rte_event_dev_xstats_by_name_get( 339 dev_id, name, &port_inflight_ids[i]); 340 snprintf(name, sizeof(name), "port_%u_tx", i); 341 stats->port_tx_pkts[i] = rte_event_dev_xstats_by_name_get( 342 dev_id, name, &port_tx_pkts_ids[i]); 343 } 344 for (i = 0; i < MAX_QIDS; i++) { 345 char name[32]; 346 snprintf(name, sizeof(name), "qid_%u_rx", i); 347 stats->qid_rx_pkts[i] = rte_event_dev_xstats_by_name_get( 348 dev_id, name, &qid_rx_pkts_ids[i]); 349 snprintf(name, sizeof(name), "qid_%u_drop", i); 350 stats->qid_rx_dropped[i] = rte_event_dev_xstats_by_name_get( 351 dev_id, name, &qid_rx_dropped_ids[i]); 352 snprintf(name, sizeof(name), "qid_%u_tx", i); 353 stats->qid_tx_pkts[i] = rte_event_dev_xstats_by_name_get( 354 dev_id, name, &qid_tx_pkts_ids[i]); 355 } 356 357 return 0; 358 } 359 360 /* run_prio_packet_test 361 * This performs a basic packet priority check on the test instance passed in. 362 * It is factored out of the main priority tests as the same tests must be 363 * performed to ensure prioritization of each type of QID. 364 * 365 * Requirements: 366 * - An initialized test structure, including mempool 367 * - t->port[0] is initialized for both Enq / Deq of packets to the QID 368 * - t->qid[0] is the QID to be tested 369 * - if LB QID, the CQ must be mapped to the QID. 370 */ 371 static int 372 run_prio_packet_test(struct test *t) 373 { 374 int err; 375 const uint32_t MAGIC_SEQN[] = {4711, 1234}; 376 const uint32_t PRIORITY[] = { 377 RTE_EVENT_DEV_PRIORITY_NORMAL, 378 RTE_EVENT_DEV_PRIORITY_HIGHEST 379 }; 380 unsigned int i; 381 for (i = 0; i < RTE_DIM(MAGIC_SEQN); i++) { 382 /* generate pkt and enqueue */ 383 struct rte_event ev; 384 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 385 if (!arp) { 386 printf("%d: gen of pkt failed\n", __LINE__); 387 return -1; 388 } 389 *rte_event_pmd_selftest_seqn(arp) = MAGIC_SEQN[i]; 390 391 ev = (struct rte_event){ 392 .priority = PRIORITY[i], 393 .op = RTE_EVENT_OP_NEW, 394 .queue_id = t->qid[0], 395 .mbuf = arp 396 }; 397 err = rte_event_enqueue_burst(evdev, t->port[0], &ev, 1); 398 if (err != 1) { 399 printf("%d: error failed to enqueue\n", __LINE__); 400 return -1; 401 } 402 } 403 404 rte_service_run_iter_on_app_lcore(t->service_id, 1); 405 406 struct test_event_dev_stats stats; 407 err = test_event_dev_stats_get(evdev, &stats); 408 if (err) { 409 printf("%d: error failed to get stats\n", __LINE__); 410 return -1; 411 } 412 413 if (stats.port_rx_pkts[t->port[0]] != 2) { 414 printf("%d: error stats incorrect for directed port\n", 415 __LINE__); 416 rte_event_dev_dump(evdev, stdout); 417 return -1; 418 } 419 420 struct rte_event ev, ev2; 421 uint32_t deq_pkts; 422 deq_pkts = rte_event_dequeue_burst(evdev, t->port[0], &ev, 1, 0); 423 if (deq_pkts != 1) { 424 printf("%d: error failed to deq\n", __LINE__); 425 rte_event_dev_dump(evdev, stdout); 426 return -1; 427 } 428 if (*rte_event_pmd_selftest_seqn(ev.mbuf) != MAGIC_SEQN[1]) { 429 printf("%d: first packet out not highest priority\n", 430 __LINE__); 431 rte_event_dev_dump(evdev, stdout); 432 return -1; 433 } 434 rte_pktmbuf_free(ev.mbuf); 435 436 deq_pkts = rte_event_dequeue_burst(evdev, t->port[0], &ev2, 1, 0); 437 if (deq_pkts != 1) { 438 printf("%d: error failed to deq\n", __LINE__); 439 rte_event_dev_dump(evdev, stdout); 440 return -1; 441 } 442 if (*rte_event_pmd_selftest_seqn(ev2.mbuf) != MAGIC_SEQN[0]) { 443 printf("%d: second packet out not lower priority\n", 444 __LINE__); 445 rte_event_dev_dump(evdev, stdout); 446 return -1; 447 } 448 rte_pktmbuf_free(ev2.mbuf); 449 450 cleanup(t); 451 return 0; 452 } 453 454 static int 455 test_single_directed_packet(struct test *t) 456 { 457 const int rx_enq = 0; 458 const int wrk_enq = 2; 459 int err; 460 461 /* Create instance with 3 directed QIDs going to 3 ports */ 462 if (init(t, 3, 3) < 0 || 463 create_ports(t, 3) < 0 || 464 create_directed_qids(t, 3, t->port) < 0) 465 return -1; 466 467 if (rte_event_dev_start(evdev) < 0) { 468 printf("%d: Error with start call\n", __LINE__); 469 return -1; 470 } 471 472 /************** FORWARD ****************/ 473 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 474 struct rte_event ev = { 475 .op = RTE_EVENT_OP_NEW, 476 .queue_id = wrk_enq, 477 .mbuf = arp, 478 }; 479 480 if (!arp) { 481 printf("%d: gen of pkt failed\n", __LINE__); 482 return -1; 483 } 484 485 const uint32_t MAGIC_SEQN = 4711; 486 *rte_event_pmd_selftest_seqn(arp) = MAGIC_SEQN; 487 488 /* generate pkt and enqueue */ 489 err = rte_event_enqueue_burst(evdev, rx_enq, &ev, 1); 490 if (err != 1) { 491 printf("%d: error failed to enqueue\n", __LINE__); 492 return -1; 493 } 494 495 /* Run schedule() as dir packets may need to be re-ordered */ 496 rte_service_run_iter_on_app_lcore(t->service_id, 1); 497 498 struct test_event_dev_stats stats; 499 err = test_event_dev_stats_get(evdev, &stats); 500 if (err) { 501 printf("%d: error failed to get stats\n", __LINE__); 502 return -1; 503 } 504 505 if (stats.port_rx_pkts[rx_enq] != 1) { 506 printf("%d: error stats incorrect for directed port\n", 507 __LINE__); 508 return -1; 509 } 510 511 uint32_t deq_pkts; 512 deq_pkts = rte_event_dequeue_burst(evdev, wrk_enq, &ev, 1, 0); 513 if (deq_pkts != 1) { 514 printf("%d: error failed to deq\n", __LINE__); 515 return -1; 516 } 517 518 err = test_event_dev_stats_get(evdev, &stats); 519 if (stats.port_rx_pkts[wrk_enq] != 0 && 520 stats.port_rx_pkts[wrk_enq] != 1) { 521 printf("%d: error directed stats post-dequeue\n", __LINE__); 522 return -1; 523 } 524 525 if (*rte_event_pmd_selftest_seqn(ev.mbuf) != MAGIC_SEQN) { 526 printf("%d: error magic sequence number not dequeued\n", 527 __LINE__); 528 return -1; 529 } 530 531 rte_pktmbuf_free(ev.mbuf); 532 cleanup(t); 533 return 0; 534 } 535 536 static int 537 test_directed_forward_credits(struct test *t) 538 { 539 uint32_t i; 540 int32_t err; 541 542 if (init(t, 1, 1) < 0 || 543 create_ports(t, 1) < 0 || 544 create_directed_qids(t, 1, t->port) < 0) 545 return -1; 546 547 if (rte_event_dev_start(evdev) < 0) { 548 printf("%d: Error with start call\n", __LINE__); 549 return -1; 550 } 551 552 struct rte_event ev = { 553 .op = RTE_EVENT_OP_NEW, 554 .queue_id = 0, 555 }; 556 557 for (i = 0; i < 1000; i++) { 558 err = rte_event_enqueue_burst(evdev, 0, &ev, 1); 559 if (err != 1) { 560 printf("%d: error failed to enqueue\n", __LINE__); 561 return -1; 562 } 563 rte_service_run_iter_on_app_lcore(t->service_id, 1); 564 565 uint32_t deq_pkts; 566 deq_pkts = rte_event_dequeue_burst(evdev, 0, &ev, 1, 0); 567 if (deq_pkts != 1) { 568 printf("%d: error failed to deq\n", __LINE__); 569 return -1; 570 } 571 572 /* re-write event to be a forward, and continue looping it */ 573 ev.op = RTE_EVENT_OP_FORWARD; 574 } 575 576 cleanup(t); 577 return 0; 578 } 579 580 581 static int 582 test_priority_directed(struct test *t) 583 { 584 if (init(t, 1, 1) < 0 || 585 create_ports(t, 1) < 0 || 586 create_directed_qids(t, 1, t->port) < 0) { 587 printf("%d: Error initializing device\n", __LINE__); 588 return -1; 589 } 590 591 if (rte_event_dev_start(evdev) < 0) { 592 printf("%d: Error with start call\n", __LINE__); 593 return -1; 594 } 595 596 return run_prio_packet_test(t); 597 } 598 599 static int 600 test_priority_atomic(struct test *t) 601 { 602 if (init(t, 1, 1) < 0 || 603 create_ports(t, 1) < 0 || 604 create_atomic_qids(t, 1) < 0) { 605 printf("%d: Error initializing device\n", __LINE__); 606 return -1; 607 } 608 609 /* map the QID */ 610 if (rte_event_port_link(evdev, t->port[0], &t->qid[0], NULL, 1) != 1) { 611 printf("%d: error mapping qid to port\n", __LINE__); 612 return -1; 613 } 614 if (rte_event_dev_start(evdev) < 0) { 615 printf("%d: Error with start call\n", __LINE__); 616 return -1; 617 } 618 619 return run_prio_packet_test(t); 620 } 621 622 static int 623 test_priority_ordered(struct test *t) 624 { 625 if (init(t, 1, 1) < 0 || 626 create_ports(t, 1) < 0 || 627 create_ordered_qids(t, 1) < 0) { 628 printf("%d: Error initializing device\n", __LINE__); 629 return -1; 630 } 631 632 /* map the QID */ 633 if (rte_event_port_link(evdev, t->port[0], &t->qid[0], NULL, 1) != 1) { 634 printf("%d: error mapping qid to port\n", __LINE__); 635 return -1; 636 } 637 if (rte_event_dev_start(evdev) < 0) { 638 printf("%d: Error with start call\n", __LINE__); 639 return -1; 640 } 641 642 return run_prio_packet_test(t); 643 } 644 645 static int 646 test_priority_unordered(struct test *t) 647 { 648 if (init(t, 1, 1) < 0 || 649 create_ports(t, 1) < 0 || 650 create_unordered_qids(t, 1) < 0) { 651 printf("%d: Error initializing device\n", __LINE__); 652 return -1; 653 } 654 655 /* map the QID */ 656 if (rte_event_port_link(evdev, t->port[0], &t->qid[0], NULL, 1) != 1) { 657 printf("%d: error mapping qid to port\n", __LINE__); 658 return -1; 659 } 660 if (rte_event_dev_start(evdev) < 0) { 661 printf("%d: Error with start call\n", __LINE__); 662 return -1; 663 } 664 665 return run_prio_packet_test(t); 666 } 667 668 static int 669 burst_packets(struct test *t) 670 { 671 /************** CONFIG ****************/ 672 uint32_t i; 673 int err; 674 int ret; 675 676 /* Create instance with 2 ports and 2 queues */ 677 if (init(t, 2, 2) < 0 || 678 create_ports(t, 2) < 0 || 679 create_atomic_qids(t, 2) < 0) { 680 printf("%d: Error initializing device\n", __LINE__); 681 return -1; 682 } 683 684 /* CQ mapping to QID */ 685 ret = rte_event_port_link(evdev, t->port[0], &t->qid[0], NULL, 1); 686 if (ret != 1) { 687 printf("%d: error mapping lb qid0\n", __LINE__); 688 return -1; 689 } 690 ret = rte_event_port_link(evdev, t->port[1], &t->qid[1], NULL, 1); 691 if (ret != 1) { 692 printf("%d: error mapping lb qid1\n", __LINE__); 693 return -1; 694 } 695 696 if (rte_event_dev_start(evdev) < 0) { 697 printf("%d: Error with start call\n", __LINE__); 698 return -1; 699 } 700 701 /************** FORWARD ****************/ 702 const uint32_t rx_port = 0; 703 const uint32_t NUM_PKTS = 2; 704 705 for (i = 0; i < NUM_PKTS; i++) { 706 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 707 if (!arp) { 708 printf("%d: error generating pkt\n", __LINE__); 709 return -1; 710 } 711 712 struct rte_event ev = { 713 .op = RTE_EVENT_OP_NEW, 714 .queue_id = i % 2, 715 .flow_id = i % 3, 716 .mbuf = arp, 717 }; 718 /* generate pkt and enqueue */ 719 err = rte_event_enqueue_burst(evdev, t->port[rx_port], &ev, 1); 720 if (err != 1) { 721 printf("%d: Failed to enqueue\n", __LINE__); 722 return -1; 723 } 724 } 725 rte_service_run_iter_on_app_lcore(t->service_id, 1); 726 727 /* Check stats for all NUM_PKTS arrived to sched core */ 728 struct test_event_dev_stats stats; 729 730 err = test_event_dev_stats_get(evdev, &stats); 731 if (err) { 732 printf("%d: failed to get stats\n", __LINE__); 733 return -1; 734 } 735 if (stats.rx_pkts != NUM_PKTS || stats.tx_pkts != NUM_PKTS) { 736 printf("%d: Sched core didn't receive all %d pkts\n", 737 __LINE__, NUM_PKTS); 738 rte_event_dev_dump(evdev, stdout); 739 return -1; 740 } 741 742 uint32_t deq_pkts; 743 int p; 744 745 deq_pkts = 0; 746 /******** DEQ QID 1 *******/ 747 do { 748 struct rte_event ev; 749 p = rte_event_dequeue_burst(evdev, t->port[0], &ev, 1, 0); 750 deq_pkts += p; 751 rte_pktmbuf_free(ev.mbuf); 752 } while (p); 753 754 if (deq_pkts != NUM_PKTS/2) { 755 printf("%d: Half of NUM_PKTS didn't arrive at port 1\n", 756 __LINE__); 757 return -1; 758 } 759 760 /******** DEQ QID 2 *******/ 761 deq_pkts = 0; 762 do { 763 struct rte_event ev; 764 p = rte_event_dequeue_burst(evdev, t->port[1], &ev, 1, 0); 765 deq_pkts += p; 766 rte_pktmbuf_free(ev.mbuf); 767 } while (p); 768 if (deq_pkts != NUM_PKTS/2) { 769 printf("%d: Half of NUM_PKTS didn't arrive at port 2\n", 770 __LINE__); 771 return -1; 772 } 773 774 cleanup(t); 775 return 0; 776 } 777 778 static int 779 abuse_inflights(struct test *t) 780 { 781 const int rx_enq = 0; 782 const int wrk_enq = 2; 783 int err; 784 785 /* Create instance with 4 ports */ 786 if (init(t, 1, 4) < 0 || 787 create_ports(t, 4) < 0 || 788 create_atomic_qids(t, 1) < 0) { 789 printf("%d: Error initializing device\n", __LINE__); 790 return -1; 791 } 792 793 /* CQ mapping to QID */ 794 err = rte_event_port_link(evdev, t->port[wrk_enq], NULL, NULL, 0); 795 if (err != 1) { 796 printf("%d: error mapping lb qid\n", __LINE__); 797 cleanup(t); 798 return -1; 799 } 800 801 if (rte_event_dev_start(evdev) < 0) { 802 printf("%d: Error with start call\n", __LINE__); 803 return -1; 804 } 805 806 /* Enqueue op only */ 807 err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &release_ev, 1); 808 if (err != 1) { 809 printf("%d: Failed to enqueue\n", __LINE__); 810 return -1; 811 } 812 813 /* schedule */ 814 rte_service_run_iter_on_app_lcore(t->service_id, 1); 815 816 struct test_event_dev_stats stats; 817 818 err = test_event_dev_stats_get(evdev, &stats); 819 if (err) { 820 printf("%d: failed to get stats\n", __LINE__); 821 return -1; 822 } 823 824 if (stats.rx_pkts != 0 || 825 stats.tx_pkts != 0 || 826 stats.port_inflight[wrk_enq] != 0) { 827 printf("%d: Sched core didn't handle pkt as expected\n", 828 __LINE__); 829 return -1; 830 } 831 832 cleanup(t); 833 return 0; 834 } 835 836 static int 837 xstats_tests(struct test *t) 838 { 839 const int wrk_enq = 2; 840 int err; 841 842 /* Create instance with 4 ports */ 843 if (init(t, 1, 4) < 0 || 844 create_ports(t, 4) < 0 || 845 create_atomic_qids(t, 1) < 0) { 846 printf("%d: Error initializing device\n", __LINE__); 847 return -1; 848 } 849 850 /* CQ mapping to QID */ 851 err = rte_event_port_link(evdev, t->port[wrk_enq], NULL, NULL, 0); 852 if (err != 1) { 853 printf("%d: error mapping lb qid\n", __LINE__); 854 cleanup(t); 855 return -1; 856 } 857 858 if (rte_event_dev_start(evdev) < 0) { 859 printf("%d: Error with start call\n", __LINE__); 860 return -1; 861 } 862 863 const uint32_t XSTATS_MAX = 1024; 864 865 uint32_t i; 866 uint64_t ids[XSTATS_MAX]; 867 uint64_t values[XSTATS_MAX]; 868 struct rte_event_dev_xstats_name xstats_names[XSTATS_MAX]; 869 870 for (i = 0; i < XSTATS_MAX; i++) 871 ids[i] = i; 872 873 /* Device names / values */ 874 int ret = rte_event_dev_xstats_names_get(evdev, 875 RTE_EVENT_DEV_XSTATS_DEVICE, 876 0, xstats_names, ids, XSTATS_MAX); 877 if (ret != 8) { 878 printf("%d: expected 8 stats, got return %d\n", __LINE__, ret); 879 return -1; 880 } 881 ret = rte_event_dev_xstats_get(evdev, 882 RTE_EVENT_DEV_XSTATS_DEVICE, 883 0, ids, values, ret); 884 if (ret != 8) { 885 printf("%d: expected 8 stats, got return %d\n", __LINE__, ret); 886 return -1; 887 } 888 889 /* Port names / values */ 890 ret = rte_event_dev_xstats_names_get(evdev, 891 RTE_EVENT_DEV_XSTATS_PORT, 0, 892 xstats_names, ids, XSTATS_MAX); 893 if (ret != 21) { 894 printf("%d: expected 21 stats, got return %d\n", __LINE__, ret); 895 return -1; 896 } 897 ret = rte_event_dev_xstats_get(evdev, 898 RTE_EVENT_DEV_XSTATS_PORT, 0, 899 ids, values, ret); 900 if (ret != 21) { 901 printf("%d: expected 21 stats, got return %d\n", __LINE__, ret); 902 return -1; 903 } 904 905 /* Queue names / values */ 906 ret = rte_event_dev_xstats_names_get(evdev, 907 RTE_EVENT_DEV_XSTATS_QUEUE, 908 0, xstats_names, ids, XSTATS_MAX); 909 if (ret != 16) { 910 printf("%d: expected 16 stats, got return %d\n", __LINE__, ret); 911 return -1; 912 } 913 914 /* NEGATIVE TEST: with wrong queue passed, 0 stats should be returned */ 915 ret = rte_event_dev_xstats_get(evdev, 916 RTE_EVENT_DEV_XSTATS_QUEUE, 917 1, ids, values, ret); 918 if (ret != -EINVAL) { 919 printf("%d: expected 0 stats, got return %d\n", __LINE__, ret); 920 return -1; 921 } 922 923 ret = rte_event_dev_xstats_get(evdev, 924 RTE_EVENT_DEV_XSTATS_QUEUE, 925 0, ids, values, ret); 926 if (ret != 16) { 927 printf("%d: expected 16 stats, got return %d\n", __LINE__, ret); 928 return -1; 929 } 930 931 /* enqueue packets to check values */ 932 for (i = 0; i < 3; i++) { 933 struct rte_event ev; 934 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 935 if (!arp) { 936 printf("%d: gen of pkt failed\n", __LINE__); 937 return -1; 938 } 939 ev.queue_id = t->qid[i]; 940 ev.op = RTE_EVENT_OP_NEW; 941 ev.mbuf = arp; 942 ev.flow_id = 7; 943 *rte_event_pmd_selftest_seqn(arp) = i; 944 945 int err = rte_event_enqueue_burst(evdev, t->port[0], &ev, 1); 946 if (err != 1) { 947 printf("%d: Failed to enqueue\n", __LINE__); 948 return -1; 949 } 950 } 951 952 rte_service_run_iter_on_app_lcore(t->service_id, 1); 953 954 /* Device names / values */ 955 int num_stats = rte_event_dev_xstats_names_get(evdev, 956 RTE_EVENT_DEV_XSTATS_DEVICE, 0, 957 xstats_names, ids, XSTATS_MAX); 958 if (num_stats < 0) 959 goto fail; 960 ret = rte_event_dev_xstats_get(evdev, 961 RTE_EVENT_DEV_XSTATS_DEVICE, 962 0, ids, values, num_stats); 963 static const uint64_t expected[] = {3, 3, 0, 1, 0, 0, 4, 1}; 964 for (i = 0; (signed int)i < ret; i++) { 965 if (expected[i] != values[i]) { 966 printf("%d Error xstat %d (id %" PRIu64 967 ") %s : %" PRIu64 ", expect %" PRIu64 "\n", 968 __LINE__, i, ids[i], xstats_names[i].name, 969 values[i], expected[i]); 970 goto fail; 971 } 972 } 973 974 ret = rte_event_dev_xstats_reset(evdev, RTE_EVENT_DEV_XSTATS_DEVICE, 975 0, NULL, 0); 976 977 /* ensure reset statistics are zero-ed */ 978 static const uint64_t expected_zero[] = {0, 0, 0, 0, 0, 0, 0, 0}; 979 ret = rte_event_dev_xstats_get(evdev, 980 RTE_EVENT_DEV_XSTATS_DEVICE, 981 0, ids, values, num_stats); 982 for (i = 0; (signed int)i < ret; i++) { 983 if (expected_zero[i] != values[i]) { 984 printf("%d Error, xstat %d (id %" PRIu64 985 ") %s : %" PRIu64 ", expect %" PRIu64 "\n", 986 __LINE__, i, ids[i], xstats_names[i].name, 987 values[i], expected_zero[i]); 988 goto fail; 989 } 990 } 991 992 /* port reset checks */ 993 num_stats = rte_event_dev_xstats_names_get(evdev, 994 RTE_EVENT_DEV_XSTATS_PORT, 0, 995 xstats_names, ids, XSTATS_MAX); 996 if (num_stats < 0) 997 goto fail; 998 ret = rte_event_dev_xstats_get(evdev, RTE_EVENT_DEV_XSTATS_PORT, 999 0, ids, values, num_stats); 1000 1001 static const uint64_t port_expected[] = { 1002 3 /* rx */, 1003 0 /* tx */, 1004 0 /* drop */, 1005 0 /* inflights */, 1006 0 /* avg pkt cycles */, 1007 29 /* credits */, 1008 0 /* rx ring used */, 1009 4096 /* rx ring free */, 1010 0 /* cq ring used */, 1011 32 /* cq ring free */, 1012 0 /* dequeue calls */, 1013 /* 10 dequeue burst buckets */ 1014 0, 0, 0, 0, 0, 1015 0, 0, 0, 0, 0, 1016 }; 1017 if (ret != RTE_DIM(port_expected)) { 1018 printf( 1019 "%s %d: wrong number of port stats (%d), expected %zu\n", 1020 __func__, __LINE__, ret, RTE_DIM(port_expected)); 1021 } 1022 1023 for (i = 0; (signed int)i < ret; i++) { 1024 if (port_expected[i] != values[i]) { 1025 printf( 1026 "%s : %d: Error stat %s is %"PRIu64 1027 ", expected %"PRIu64"\n", 1028 __func__, __LINE__, xstats_names[i].name, 1029 values[i], port_expected[i]); 1030 goto fail; 1031 } 1032 } 1033 1034 ret = rte_event_dev_xstats_reset(evdev, RTE_EVENT_DEV_XSTATS_PORT, 1035 0, NULL, 0); 1036 1037 /* ensure reset statistics are zero-ed */ 1038 static const uint64_t port_expected_zero[] = { 1039 0 /* rx */, 1040 0 /* tx */, 1041 0 /* drop */, 1042 0 /* inflights */, 1043 0 /* avg pkt cycles */, 1044 29 /* credits */, 1045 0 /* rx ring used */, 1046 4096 /* rx ring free */, 1047 0 /* cq ring used */, 1048 32 /* cq ring free */, 1049 0 /* dequeue calls */, 1050 /* 10 dequeue burst buckets */ 1051 0, 0, 0, 0, 0, 1052 0, 0, 0, 0, 0, 1053 }; 1054 ret = rte_event_dev_xstats_get(evdev, 1055 RTE_EVENT_DEV_XSTATS_PORT, 1056 0, ids, values, num_stats); 1057 for (i = 0; (signed int)i < ret; i++) { 1058 if (port_expected_zero[i] != values[i]) { 1059 printf("%d, Error, xstat %d (id %" PRIu64 1060 ") %s : %" PRIu64 ", expect %" PRIu64 "\n", 1061 __LINE__, i, ids[i], xstats_names[i].name, 1062 values[i], port_expected_zero[i]); 1063 goto fail; 1064 } 1065 } 1066 1067 /* QUEUE STATS TESTS */ 1068 num_stats = rte_event_dev_xstats_names_get(evdev, 1069 RTE_EVENT_DEV_XSTATS_QUEUE, 0, 1070 xstats_names, ids, XSTATS_MAX); 1071 ret = rte_event_dev_xstats_get(evdev, RTE_EVENT_DEV_XSTATS_QUEUE, 1072 0, ids, values, num_stats); 1073 if (ret < 0) { 1074 printf("xstats get returned %d\n", ret); 1075 goto fail; 1076 } 1077 if ((unsigned int)ret > XSTATS_MAX) 1078 printf("%s %d: more xstats available than space\n", 1079 __func__, __LINE__); 1080 1081 static const uint64_t queue_expected[] = { 1082 3 /* rx */, 1083 3 /* tx */, 1084 0 /* drop */, 1085 3 /* inflights */, 1086 0, 0, 0, 0, /* iq 0, 1, 2, 3 used */ 1087 /* QID-to-Port: pinned_flows, packets */ 1088 0, 0, 1089 0, 0, 1090 1, 3, 1091 0, 0, 1092 }; 1093 for (i = 0; (signed int)i < ret; i++) { 1094 if (queue_expected[i] != values[i]) { 1095 printf("%d, Error, xstat %d (id %" PRIu64 1096 ") %s : %" PRIu64 ", expect %" PRIu64 "\n", 1097 __LINE__, i, ids[i], xstats_names[i].name, 1098 values[i], queue_expected[i]); 1099 goto fail; 1100 } 1101 } 1102 1103 /* Reset the queue stats here */ 1104 ret = rte_event_dev_xstats_reset(evdev, 1105 RTE_EVENT_DEV_XSTATS_QUEUE, 0, 1106 NULL, 1107 0); 1108 1109 /* Verify that the resettable stats are reset, and others are not */ 1110 static const uint64_t queue_expected_zero[] = { 1111 0 /* rx */, 1112 0 /* tx */, 1113 0 /* drop */, 1114 3 /* inflight */, 1115 0, 0, 0, 0, /* 4 iq used */ 1116 /* QID-to-Port: pinned_flows, packets */ 1117 0, 0, 1118 0, 0, 1119 1, 0, 1120 0, 0, 1121 }; 1122 1123 ret = rte_event_dev_xstats_get(evdev, RTE_EVENT_DEV_XSTATS_QUEUE, 0, 1124 ids, values, num_stats); 1125 int fails = 0; 1126 for (i = 0; (signed int)i < ret; i++) { 1127 if (queue_expected_zero[i] != values[i]) { 1128 printf("%d, Error, xstat %d (id %" PRIu64 1129 ") %s : %" PRIu64 ", expect %" PRIu64 "\n", 1130 __LINE__, i, ids[i], xstats_names[i].name, 1131 values[i], queue_expected_zero[i]); 1132 fails++; 1133 } 1134 } 1135 if (fails) { 1136 printf("%d : %d of values were not as expected above\n", 1137 __LINE__, fails); 1138 goto fail; 1139 } 1140 1141 cleanup(t); 1142 return 0; 1143 1144 fail: 1145 rte_event_dev_dump(0, stdout); 1146 cleanup(t); 1147 return -1; 1148 } 1149 1150 1151 static int 1152 xstats_id_abuse_tests(struct test *t) 1153 { 1154 int err; 1155 const uint32_t XSTATS_MAX = 1024; 1156 const uint32_t link_port = 2; 1157 1158 uint64_t ids[XSTATS_MAX]; 1159 struct rte_event_dev_xstats_name xstats_names[XSTATS_MAX]; 1160 1161 /* Create instance with 4 ports */ 1162 if (init(t, 1, 4) < 0 || 1163 create_ports(t, 4) < 0 || 1164 create_atomic_qids(t, 1) < 0) { 1165 printf("%d: Error initializing device\n", __LINE__); 1166 goto fail; 1167 } 1168 1169 err = rte_event_port_link(evdev, t->port[link_port], NULL, NULL, 0); 1170 if (err != 1) { 1171 printf("%d: error mapping lb qid\n", __LINE__); 1172 goto fail; 1173 } 1174 1175 if (rte_event_dev_start(evdev) < 0) { 1176 printf("%d: Error with start call\n", __LINE__); 1177 goto fail; 1178 } 1179 1180 /* no test for device, as it ignores the port/q number */ 1181 int num_stats = rte_event_dev_xstats_names_get(evdev, 1182 RTE_EVENT_DEV_XSTATS_PORT, 1183 UINT8_MAX-1, xstats_names, ids, 1184 XSTATS_MAX); 1185 if (num_stats != 0) { 1186 printf("%d: expected %d stats, got return %d\n", __LINE__, 1187 0, num_stats); 1188 goto fail; 1189 } 1190 1191 num_stats = rte_event_dev_xstats_names_get(evdev, 1192 RTE_EVENT_DEV_XSTATS_QUEUE, 1193 UINT8_MAX-1, xstats_names, ids, 1194 XSTATS_MAX); 1195 if (num_stats != 0) { 1196 printf("%d: expected %d stats, got return %d\n", __LINE__, 1197 0, num_stats); 1198 goto fail; 1199 } 1200 1201 cleanup(t); 1202 return 0; 1203 fail: 1204 cleanup(t); 1205 return -1; 1206 } 1207 1208 static int 1209 port_reconfig_credits(struct test *t) 1210 { 1211 if (init(t, 1, 1) < 0) { 1212 printf("%d: Error initializing device\n", __LINE__); 1213 return -1; 1214 } 1215 1216 uint32_t i; 1217 const uint32_t NUM_ITERS = 32; 1218 for (i = 0; i < NUM_ITERS; i++) { 1219 const struct rte_event_queue_conf conf = { 1220 .schedule_type = RTE_SCHED_TYPE_ATOMIC, 1221 .priority = RTE_EVENT_DEV_PRIORITY_NORMAL, 1222 .nb_atomic_flows = 1024, 1223 .nb_atomic_order_sequences = 1024, 1224 }; 1225 if (rte_event_queue_setup(evdev, 0, &conf) < 0) { 1226 printf("%d: error creating qid\n", __LINE__); 1227 return -1; 1228 } 1229 t->qid[0] = 0; 1230 1231 static const struct rte_event_port_conf port_conf = { 1232 .new_event_threshold = 128, 1233 .dequeue_depth = 32, 1234 .enqueue_depth = 64, 1235 }; 1236 if (rte_event_port_setup(evdev, 0, &port_conf) < 0) { 1237 printf("%d Error setting up port\n", __LINE__); 1238 return -1; 1239 } 1240 1241 int links = rte_event_port_link(evdev, 0, NULL, NULL, 0); 1242 if (links != 1) { 1243 printf("%d: error mapping lb qid\n", __LINE__); 1244 goto fail; 1245 } 1246 1247 if (rte_event_dev_start(evdev) < 0) { 1248 printf("%d: Error with start call\n", __LINE__); 1249 goto fail; 1250 } 1251 1252 const uint32_t NPKTS = 1; 1253 uint32_t j; 1254 for (j = 0; j < NPKTS; j++) { 1255 struct rte_event ev; 1256 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 1257 if (!arp) { 1258 printf("%d: gen of pkt failed\n", __LINE__); 1259 goto fail; 1260 } 1261 ev.queue_id = t->qid[0]; 1262 ev.op = RTE_EVENT_OP_NEW; 1263 ev.mbuf = arp; 1264 int err = rte_event_enqueue_burst(evdev, 0, &ev, 1); 1265 if (err != 1) { 1266 printf("%d: Failed to enqueue\n", __LINE__); 1267 rte_event_dev_dump(0, stdout); 1268 goto fail; 1269 } 1270 } 1271 1272 rte_service_run_iter_on_app_lcore(t->service_id, 1); 1273 1274 struct rte_event ev[NPKTS]; 1275 int deq = rte_event_dequeue_burst(evdev, t->port[0], ev, 1276 NPKTS, 0); 1277 if (deq != 1) 1278 printf("%d error; no packet dequeued\n", __LINE__); 1279 1280 /* let cleanup below stop the device on last iter */ 1281 if (i != NUM_ITERS-1) 1282 rte_event_dev_stop(evdev); 1283 } 1284 1285 cleanup(t); 1286 return 0; 1287 fail: 1288 cleanup(t); 1289 return -1; 1290 } 1291 1292 static int 1293 port_single_lb_reconfig(struct test *t) 1294 { 1295 if (init(t, 2, 2) < 0) { 1296 printf("%d: Error initializing device\n", __LINE__); 1297 goto fail; 1298 } 1299 1300 static const struct rte_event_queue_conf conf_lb_atomic = { 1301 .priority = RTE_EVENT_DEV_PRIORITY_NORMAL, 1302 .schedule_type = RTE_SCHED_TYPE_ATOMIC, 1303 .nb_atomic_flows = 1024, 1304 .nb_atomic_order_sequences = 1024, 1305 }; 1306 if (rte_event_queue_setup(evdev, 0, &conf_lb_atomic) < 0) { 1307 printf("%d: error creating qid\n", __LINE__); 1308 goto fail; 1309 } 1310 1311 static const struct rte_event_queue_conf conf_single_link = { 1312 .priority = RTE_EVENT_DEV_PRIORITY_NORMAL, 1313 .event_queue_cfg = RTE_EVENT_QUEUE_CFG_SINGLE_LINK, 1314 }; 1315 if (rte_event_queue_setup(evdev, 1, &conf_single_link) < 0) { 1316 printf("%d: error creating qid\n", __LINE__); 1317 goto fail; 1318 } 1319 1320 struct rte_event_port_conf port_conf = { 1321 .new_event_threshold = 128, 1322 .dequeue_depth = 32, 1323 .enqueue_depth = 64, 1324 }; 1325 if (rte_event_port_setup(evdev, 0, &port_conf) < 0) { 1326 printf("%d Error setting up port\n", __LINE__); 1327 goto fail; 1328 } 1329 if (rte_event_port_setup(evdev, 1, &port_conf) < 0) { 1330 printf("%d Error setting up port\n", __LINE__); 1331 goto fail; 1332 } 1333 1334 /* link port to lb queue */ 1335 uint8_t queue_id = 0; 1336 if (rte_event_port_link(evdev, 0, &queue_id, NULL, 1) != 1) { 1337 printf("%d: error creating link for qid\n", __LINE__); 1338 goto fail; 1339 } 1340 1341 int ret = rte_event_port_unlink(evdev, 0, &queue_id, 1); 1342 if (ret != 1) { 1343 printf("%d: Error unlinking lb port\n", __LINE__); 1344 goto fail; 1345 } 1346 1347 queue_id = 1; 1348 if (rte_event_port_link(evdev, 0, &queue_id, NULL, 1) != 1) { 1349 printf("%d: error creating link for qid\n", __LINE__); 1350 goto fail; 1351 } 1352 1353 queue_id = 0; 1354 int err = rte_event_port_link(evdev, 1, &queue_id, NULL, 1); 1355 if (err != 1) { 1356 printf("%d: error mapping lb qid\n", __LINE__); 1357 goto fail; 1358 } 1359 1360 if (rte_event_dev_start(evdev) < 0) { 1361 printf("%d: Error with start call\n", __LINE__); 1362 goto fail; 1363 } 1364 1365 cleanup(t); 1366 return 0; 1367 fail: 1368 cleanup(t); 1369 return -1; 1370 } 1371 1372 static int 1373 xstats_brute_force(struct test *t) 1374 { 1375 uint32_t i; 1376 const uint32_t XSTATS_MAX = 1024; 1377 uint64_t ids[XSTATS_MAX]; 1378 uint64_t values[XSTATS_MAX]; 1379 struct rte_event_dev_xstats_name xstats_names[XSTATS_MAX]; 1380 1381 1382 /* Create instance with 4 ports */ 1383 if (init(t, 1, 4) < 0 || 1384 create_ports(t, 4) < 0 || 1385 create_atomic_qids(t, 1) < 0) { 1386 printf("%d: Error initializing device\n", __LINE__); 1387 return -1; 1388 } 1389 1390 int err = rte_event_port_link(evdev, t->port[0], NULL, NULL, 0); 1391 if (err != 1) { 1392 printf("%d: error mapping lb qid\n", __LINE__); 1393 goto fail; 1394 } 1395 1396 if (rte_event_dev_start(evdev) < 0) { 1397 printf("%d: Error with start call\n", __LINE__); 1398 goto fail; 1399 } 1400 1401 for (i = 0; i < XSTATS_MAX; i++) 1402 ids[i] = i; 1403 1404 for (i = 0; i < 3; i++) { 1405 uint32_t mode = RTE_EVENT_DEV_XSTATS_DEVICE + i; 1406 uint32_t j; 1407 for (j = 0; j < UINT8_MAX; j++) { 1408 rte_event_dev_xstats_names_get(evdev, mode, 1409 j, xstats_names, ids, XSTATS_MAX); 1410 1411 rte_event_dev_xstats_get(evdev, mode, j, ids, 1412 values, XSTATS_MAX); 1413 } 1414 } 1415 1416 cleanup(t); 1417 return 0; 1418 fail: 1419 cleanup(t); 1420 return -1; 1421 } 1422 1423 static int 1424 xstats_id_reset_tests(struct test *t) 1425 { 1426 const int wrk_enq = 2; 1427 int err; 1428 1429 /* Create instance with 4 ports */ 1430 if (init(t, 1, 4) < 0 || 1431 create_ports(t, 4) < 0 || 1432 create_atomic_qids(t, 1) < 0) { 1433 printf("%d: Error initializing device\n", __LINE__); 1434 return -1; 1435 } 1436 1437 /* CQ mapping to QID */ 1438 err = rte_event_port_link(evdev, t->port[wrk_enq], NULL, NULL, 0); 1439 if (err != 1) { 1440 printf("%d: error mapping lb qid\n", __LINE__); 1441 goto fail; 1442 } 1443 1444 if (rte_event_dev_start(evdev) < 0) { 1445 printf("%d: Error with start call\n", __LINE__); 1446 goto fail; 1447 } 1448 1449 #define XSTATS_MAX 1024 1450 int ret; 1451 uint32_t i; 1452 uint64_t ids[XSTATS_MAX]; 1453 uint64_t values[XSTATS_MAX]; 1454 struct rte_event_dev_xstats_name xstats_names[XSTATS_MAX]; 1455 1456 for (i = 0; i < XSTATS_MAX; i++) 1457 ids[i] = i; 1458 1459 #define NUM_DEV_STATS 8 1460 /* Device names / values */ 1461 int num_stats = rte_event_dev_xstats_names_get(evdev, 1462 RTE_EVENT_DEV_XSTATS_DEVICE, 1463 0, xstats_names, ids, XSTATS_MAX); 1464 if (num_stats != NUM_DEV_STATS) { 1465 printf("%d: expected %d stats, got return %d\n", __LINE__, 1466 NUM_DEV_STATS, num_stats); 1467 goto fail; 1468 } 1469 ret = rte_event_dev_xstats_get(evdev, 1470 RTE_EVENT_DEV_XSTATS_DEVICE, 1471 0, ids, values, num_stats); 1472 if (ret != NUM_DEV_STATS) { 1473 printf("%d: expected %d stats, got return %d\n", __LINE__, 1474 NUM_DEV_STATS, ret); 1475 goto fail; 1476 } 1477 1478 #define NPKTS 7 1479 for (i = 0; i < NPKTS; i++) { 1480 struct rte_event ev; 1481 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 1482 if (!arp) { 1483 printf("%d: gen of pkt failed\n", __LINE__); 1484 goto fail; 1485 } 1486 ev.queue_id = t->qid[i]; 1487 ev.flow_id = 0; 1488 ev.op = RTE_EVENT_OP_NEW; 1489 ev.mbuf = arp; 1490 *rte_event_pmd_selftest_seqn(arp) = i; 1491 1492 int err = rte_event_enqueue_burst(evdev, t->port[0], &ev, 1); 1493 if (err != 1) { 1494 printf("%d: Failed to enqueue\n", __LINE__); 1495 goto fail; 1496 } 1497 } 1498 1499 rte_service_run_iter_on_app_lcore(t->service_id, 1); 1500 1501 static const char * const dev_names[] = { 1502 "dev_rx", "dev_tx", "dev_drop", "dev_sched_calls", 1503 "dev_sched_no_iq_enq", "dev_sched_no_cq_enq", 1504 "dev_sched_last_iter_bitmask", 1505 "dev_sched_progress_last_iter" 1506 }; 1507 uint64_t dev_expected[] = {NPKTS, NPKTS, 0, 1, 0, 0, 4, 1}; 1508 for (i = 0; (int)i < ret; i++) { 1509 uint64_t id; 1510 uint64_t val = rte_event_dev_xstats_by_name_get(evdev, 1511 dev_names[i], 1512 &id); 1513 if (id != i) { 1514 printf("%d: %s id incorrect, expected %d got %" PRIu64 1515 "\n", 1516 __LINE__, dev_names[i], i, id); 1517 goto fail; 1518 } 1519 if (val != dev_expected[i]) { 1520 printf("%d: %s value incorrect, expected %" 1521 PRIu64" got %"PRIu64"\n", __LINE__, 1522 dev_names[i], dev_expected[i], val); 1523 goto fail; 1524 } 1525 /* reset to zero */ 1526 int reset_ret = rte_event_dev_xstats_reset(evdev, 1527 RTE_EVENT_DEV_XSTATS_DEVICE, 0, 1528 &id, 1529 1); 1530 if (reset_ret) { 1531 printf("%d: failed to reset successfully\n", __LINE__); 1532 goto fail; 1533 } 1534 dev_expected[i] = 0; 1535 /* check value again */ 1536 val = rte_event_dev_xstats_by_name_get(evdev, dev_names[i], 0); 1537 if (val != dev_expected[i]) { 1538 printf("%d: %s value incorrect, expected %"PRIu64 1539 " got %"PRIu64"\n", __LINE__, dev_names[i], 1540 dev_expected[i], val); 1541 goto fail; 1542 } 1543 }; 1544 1545 /* 49 is stat offset from start of the devices whole xstats. 1546 * This WILL break every time we add a statistic to a port 1547 * or the device, but there is no other way to test 1548 */ 1549 #define PORT_OFF 50 1550 /* num stats for the tested port. CQ size adds more stats to a port */ 1551 #define NUM_PORT_STATS 21 1552 /* the port to test. */ 1553 #define PORT 2 1554 num_stats = rte_event_dev_xstats_names_get(evdev, 1555 RTE_EVENT_DEV_XSTATS_PORT, PORT, 1556 xstats_names, ids, XSTATS_MAX); 1557 if (num_stats != NUM_PORT_STATS) { 1558 printf("%d: expected %d stats, got return %d\n", 1559 __LINE__, NUM_PORT_STATS, num_stats); 1560 goto fail; 1561 } 1562 ret = rte_event_dev_xstats_get(evdev, RTE_EVENT_DEV_XSTATS_PORT, PORT, 1563 ids, values, num_stats); 1564 1565 if (ret != NUM_PORT_STATS) { 1566 printf("%d: expected %d stats, got return %d\n", 1567 __LINE__, NUM_PORT_STATS, ret); 1568 goto fail; 1569 } 1570 static const char * const port_names[] = { 1571 "port_2_rx", 1572 "port_2_tx", 1573 "port_2_drop", 1574 "port_2_inflight", 1575 "port_2_avg_pkt_cycles", 1576 "port_2_credits", 1577 "port_2_rx_ring_used", 1578 "port_2_rx_ring_free", 1579 "port_2_cq_ring_used", 1580 "port_2_cq_ring_free", 1581 "port_2_dequeue_calls", 1582 "port_2_dequeues_returning_0", 1583 "port_2_dequeues_returning_1-4", 1584 "port_2_dequeues_returning_5-8", 1585 "port_2_dequeues_returning_9-12", 1586 "port_2_dequeues_returning_13-16", 1587 "port_2_dequeues_returning_17-20", 1588 "port_2_dequeues_returning_21-24", 1589 "port_2_dequeues_returning_25-28", 1590 "port_2_dequeues_returning_29-32", 1591 "port_2_dequeues_returning_33-36", 1592 }; 1593 uint64_t port_expected[] = { 1594 0, /* rx */ 1595 NPKTS, /* tx */ 1596 0, /* drop */ 1597 NPKTS, /* inflight */ 1598 0, /* avg pkt cycles */ 1599 0, /* credits */ 1600 0, /* rx ring used */ 1601 4096, /* rx ring free */ 1602 NPKTS, /* cq ring used */ 1603 25, /* cq ring free */ 1604 0, /* dequeue zero calls */ 1605 0, 0, 0, 0, 0, /* 10 dequeue buckets */ 1606 0, 0, 0, 0, 0, 1607 }; 1608 uint64_t port_expected_zero[] = { 1609 0, /* rx */ 1610 0, /* tx */ 1611 0, /* drop */ 1612 NPKTS, /* inflight */ 1613 0, /* avg pkt cycles */ 1614 0, /* credits */ 1615 0, /* rx ring used */ 1616 4096, /* rx ring free */ 1617 NPKTS, /* cq ring used */ 1618 25, /* cq ring free */ 1619 0, /* dequeue zero calls */ 1620 0, 0, 0, 0, 0, /* 10 dequeue buckets */ 1621 0, 0, 0, 0, 0, 1622 }; 1623 if (RTE_DIM(port_expected) != NUM_PORT_STATS || 1624 RTE_DIM(port_names) != NUM_PORT_STATS) { 1625 printf("%d: port array of wrong size\n", __LINE__); 1626 goto fail; 1627 } 1628 1629 int failed = 0; 1630 for (i = 0; (int)i < ret; i++) { 1631 uint64_t id; 1632 uint64_t val = rte_event_dev_xstats_by_name_get(evdev, 1633 port_names[i], 1634 &id); 1635 if (id != i + PORT_OFF) { 1636 printf("%d: %s id incorrect, expected %d got %" PRIu64 1637 "\n", 1638 __LINE__, port_names[i], i + PORT_OFF, id); 1639 failed = 1; 1640 } 1641 if (val != port_expected[i]) { 1642 printf("%d: %s value incorrect, expected %" PRIu64 1643 " got %" PRIu64 "\n", 1644 __LINE__, port_names[i], port_expected[i], val); 1645 failed = 1; 1646 } 1647 /* reset to zero */ 1648 int reset_ret = rte_event_dev_xstats_reset(evdev, 1649 RTE_EVENT_DEV_XSTATS_PORT, PORT, 1650 &id, 1651 1); 1652 if (reset_ret) { 1653 printf("%d: failed to reset successfully\n", __LINE__); 1654 failed = 1; 1655 } 1656 /* check value again */ 1657 val = rte_event_dev_xstats_by_name_get(evdev, port_names[i], 0); 1658 if (val != port_expected_zero[i]) { 1659 printf("%d: %s value incorrect, expected %"PRIu64 1660 " got %"PRIu64"\n", __LINE__, port_names[i], 1661 port_expected_zero[i], val); 1662 failed = 1; 1663 } 1664 }; 1665 if (failed) 1666 goto fail; 1667 1668 /* num queue stats */ 1669 #define NUM_Q_STATS 16 1670 /* queue offset from start of the devices whole xstats. 1671 * This will break every time we add a statistic to a device/port/queue 1672 */ 1673 #define QUEUE_OFF 92 1674 const uint32_t queue = 0; 1675 num_stats = rte_event_dev_xstats_names_get(evdev, 1676 RTE_EVENT_DEV_XSTATS_QUEUE, queue, 1677 xstats_names, ids, XSTATS_MAX); 1678 if (num_stats != NUM_Q_STATS) { 1679 printf("%d: expected %d stats, got return %d\n", 1680 __LINE__, NUM_Q_STATS, num_stats); 1681 goto fail; 1682 } 1683 ret = rte_event_dev_xstats_get(evdev, RTE_EVENT_DEV_XSTATS_QUEUE, 1684 queue, ids, values, num_stats); 1685 if (ret != NUM_Q_STATS) { 1686 printf("%d: expected 21 stats, got return %d\n", __LINE__, ret); 1687 goto fail; 1688 } 1689 static const char * const queue_names[] = { 1690 "qid_0_rx", 1691 "qid_0_tx", 1692 "qid_0_drop", 1693 "qid_0_inflight", 1694 "qid_0_iq_0_used", 1695 "qid_0_iq_1_used", 1696 "qid_0_iq_2_used", 1697 "qid_0_iq_3_used", 1698 "qid_0_port_0_pinned_flows", 1699 "qid_0_port_0_packets", 1700 "qid_0_port_1_pinned_flows", 1701 "qid_0_port_1_packets", 1702 "qid_0_port_2_pinned_flows", 1703 "qid_0_port_2_packets", 1704 "qid_0_port_3_pinned_flows", 1705 "qid_0_port_3_packets", 1706 }; 1707 uint64_t queue_expected[] = { 1708 7, /* rx */ 1709 7, /* tx */ 1710 0, /* drop */ 1711 7, /* inflight */ 1712 0, /* iq 0 used */ 1713 0, /* iq 1 used */ 1714 0, /* iq 2 used */ 1715 0, /* iq 3 used */ 1716 /* QID-to-Port: pinned_flows, packets */ 1717 0, 0, 1718 0, 0, 1719 1, 7, 1720 0, 0, 1721 }; 1722 uint64_t queue_expected_zero[] = { 1723 0, /* rx */ 1724 0, /* tx */ 1725 0, /* drop */ 1726 7, /* inflight */ 1727 0, /* iq 0 used */ 1728 0, /* iq 1 used */ 1729 0, /* iq 2 used */ 1730 0, /* iq 3 used */ 1731 /* QID-to-Port: pinned_flows, packets */ 1732 0, 0, 1733 0, 0, 1734 1, 0, 1735 0, 0, 1736 }; 1737 if (RTE_DIM(queue_expected) != NUM_Q_STATS || 1738 RTE_DIM(queue_expected_zero) != NUM_Q_STATS || 1739 RTE_DIM(queue_names) != NUM_Q_STATS) { 1740 printf("%d : queue array of wrong size\n", __LINE__); 1741 goto fail; 1742 } 1743 1744 failed = 0; 1745 for (i = 0; (int)i < ret; i++) { 1746 uint64_t id; 1747 uint64_t val = rte_event_dev_xstats_by_name_get(evdev, 1748 queue_names[i], 1749 &id); 1750 if (id != i + QUEUE_OFF) { 1751 printf("%d: %s id incorrect, expected %d got %" PRIu64 1752 "\n", 1753 __LINE__, queue_names[i], i + QUEUE_OFF, id); 1754 failed = 1; 1755 } 1756 if (val != queue_expected[i]) { 1757 printf("%d: %d: %s value , expected %"PRIu64 1758 " got %"PRIu64"\n", i, __LINE__, 1759 queue_names[i], queue_expected[i], val); 1760 failed = 1; 1761 } 1762 /* reset to zero */ 1763 int reset_ret = rte_event_dev_xstats_reset(evdev, 1764 RTE_EVENT_DEV_XSTATS_QUEUE, 1765 queue, &id, 1); 1766 if (reset_ret) { 1767 printf("%d: failed to reset successfully\n", __LINE__); 1768 failed = 1; 1769 } 1770 /* check value again */ 1771 val = rte_event_dev_xstats_by_name_get(evdev, queue_names[i], 1772 0); 1773 if (val != queue_expected_zero[i]) { 1774 printf("%d: %s value incorrect, expected %"PRIu64 1775 " got %"PRIu64"\n", __LINE__, queue_names[i], 1776 queue_expected_zero[i], val); 1777 failed = 1; 1778 } 1779 }; 1780 1781 if (failed) 1782 goto fail; 1783 1784 cleanup(t); 1785 return 0; 1786 fail: 1787 cleanup(t); 1788 return -1; 1789 } 1790 1791 static int 1792 ordered_reconfigure(struct test *t) 1793 { 1794 if (init(t, 1, 1) < 0 || 1795 create_ports(t, 1) < 0) { 1796 printf("%d: Error initializing device\n", __LINE__); 1797 return -1; 1798 } 1799 1800 const struct rte_event_queue_conf conf = { 1801 .schedule_type = RTE_SCHED_TYPE_ORDERED, 1802 .priority = RTE_EVENT_DEV_PRIORITY_NORMAL, 1803 .nb_atomic_flows = 1024, 1804 .nb_atomic_order_sequences = 1024, 1805 }; 1806 1807 if (rte_event_queue_setup(evdev, 0, &conf) < 0) { 1808 printf("%d: error creating qid\n", __LINE__); 1809 goto failed; 1810 } 1811 1812 if (rte_event_queue_setup(evdev, 0, &conf) < 0) { 1813 printf("%d: error creating qid, for 2nd time\n", __LINE__); 1814 goto failed; 1815 } 1816 1817 rte_event_port_link(evdev, t->port[0], NULL, NULL, 0); 1818 if (rte_event_dev_start(evdev) < 0) { 1819 printf("%d: Error with start call\n", __LINE__); 1820 return -1; 1821 } 1822 1823 cleanup(t); 1824 return 0; 1825 failed: 1826 cleanup(t); 1827 return -1; 1828 } 1829 1830 static int 1831 qid_priorities(struct test *t) 1832 { 1833 /* Test works by having a CQ with enough empty space for all packets, 1834 * and enqueueing 3 packets to 3 QIDs. They must return based on the 1835 * priority of the QID, not the ingress order, to pass the test 1836 */ 1837 unsigned int i; 1838 /* Create instance with 1 ports, and 3 qids */ 1839 if (init(t, 3, 1) < 0 || 1840 create_ports(t, 1) < 0) { 1841 printf("%d: Error initializing device\n", __LINE__); 1842 return -1; 1843 } 1844 1845 for (i = 0; i < 3; i++) { 1846 /* Create QID */ 1847 const struct rte_event_queue_conf conf = { 1848 .schedule_type = RTE_SCHED_TYPE_ATOMIC, 1849 /* increase priority (0 == highest), as we go */ 1850 .priority = RTE_EVENT_DEV_PRIORITY_NORMAL - i, 1851 .nb_atomic_flows = 1024, 1852 .nb_atomic_order_sequences = 1024, 1853 }; 1854 1855 if (rte_event_queue_setup(evdev, i, &conf) < 0) { 1856 printf("%d: error creating qid %d\n", __LINE__, i); 1857 return -1; 1858 } 1859 t->qid[i] = i; 1860 } 1861 t->nb_qids = i; 1862 /* map all QIDs to port */ 1863 rte_event_port_link(evdev, t->port[0], NULL, NULL, 0); 1864 1865 if (rte_event_dev_start(evdev) < 0) { 1866 printf("%d: Error with start call\n", __LINE__); 1867 return -1; 1868 } 1869 1870 /* enqueue 3 packets, setting seqn and QID to check priority */ 1871 for (i = 0; i < 3; i++) { 1872 struct rte_event ev; 1873 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 1874 if (!arp) { 1875 printf("%d: gen of pkt failed\n", __LINE__); 1876 return -1; 1877 } 1878 ev.queue_id = t->qid[i]; 1879 ev.op = RTE_EVENT_OP_NEW; 1880 ev.mbuf = arp; 1881 *rte_event_pmd_selftest_seqn(arp) = i; 1882 1883 int err = rte_event_enqueue_burst(evdev, t->port[0], &ev, 1); 1884 if (err != 1) { 1885 printf("%d: Failed to enqueue\n", __LINE__); 1886 return -1; 1887 } 1888 } 1889 1890 rte_service_run_iter_on_app_lcore(t->service_id, 1); 1891 1892 /* dequeue packets, verify priority was upheld */ 1893 struct rte_event ev[32]; 1894 uint32_t deq_pkts = 1895 rte_event_dequeue_burst(evdev, t->port[0], ev, 32, 0); 1896 if (deq_pkts != 3) { 1897 printf("%d: failed to deq packets\n", __LINE__); 1898 rte_event_dev_dump(evdev, stdout); 1899 return -1; 1900 } 1901 for (i = 0; i < 3; i++) { 1902 if (*rte_event_pmd_selftest_seqn(ev[i].mbuf) != 2-i) { 1903 printf( 1904 "%d: qid priority test: seqn %d incorrectly prioritized\n", 1905 __LINE__, i); 1906 } 1907 } 1908 1909 cleanup(t); 1910 return 0; 1911 } 1912 1913 static int 1914 unlink_in_progress(struct test *t) 1915 { 1916 /* Test unlinking API, in particular that when an unlink request has 1917 * not yet been seen by the scheduler thread, that the 1918 * unlink_in_progress() function returns the number of unlinks. 1919 */ 1920 unsigned int i; 1921 /* Create instance with 1 ports, and 3 qids */ 1922 if (init(t, 3, 1) < 0 || 1923 create_ports(t, 1) < 0) { 1924 printf("%d: Error initializing device\n", __LINE__); 1925 return -1; 1926 } 1927 1928 for (i = 0; i < 3; i++) { 1929 /* Create QID */ 1930 const struct rte_event_queue_conf conf = { 1931 .schedule_type = RTE_SCHED_TYPE_ATOMIC, 1932 /* increase priority (0 == highest), as we go */ 1933 .priority = RTE_EVENT_DEV_PRIORITY_NORMAL - i, 1934 .nb_atomic_flows = 1024, 1935 .nb_atomic_order_sequences = 1024, 1936 }; 1937 1938 if (rte_event_queue_setup(evdev, i, &conf) < 0) { 1939 printf("%d: error creating qid %d\n", __LINE__, i); 1940 return -1; 1941 } 1942 t->qid[i] = i; 1943 } 1944 t->nb_qids = i; 1945 /* map all QIDs to port */ 1946 rte_event_port_link(evdev, t->port[0], NULL, NULL, 0); 1947 1948 if (rte_event_dev_start(evdev) < 0) { 1949 printf("%d: Error with start call\n", __LINE__); 1950 return -1; 1951 } 1952 1953 /* unlink all ports to have outstanding unlink requests */ 1954 int ret = rte_event_port_unlink(evdev, t->port[0], NULL, 0); 1955 if (ret < 0) { 1956 printf("%d: Failed to unlink queues\n", __LINE__); 1957 return -1; 1958 } 1959 1960 /* get active unlinks here, expect 3 */ 1961 int unlinks_in_progress = 1962 rte_event_port_unlinks_in_progress(evdev, t->port[0]); 1963 if (unlinks_in_progress != 3) { 1964 printf("%d: Expected num unlinks in progress == 3, got %d\n", 1965 __LINE__, unlinks_in_progress); 1966 return -1; 1967 } 1968 1969 /* run scheduler service on this thread to ack the unlinks */ 1970 rte_service_run_iter_on_app_lcore(t->service_id, 1); 1971 1972 /* active unlinks expected as 0 as scheduler thread has acked */ 1973 unlinks_in_progress = 1974 rte_event_port_unlinks_in_progress(evdev, t->port[0]); 1975 if (unlinks_in_progress != 0) { 1976 printf("%d: Expected num unlinks in progress == 0, got %d\n", 1977 __LINE__, unlinks_in_progress); 1978 } 1979 1980 cleanup(t); 1981 return 0; 1982 } 1983 1984 static int 1985 load_balancing(struct test *t) 1986 { 1987 const int rx_enq = 0; 1988 int err; 1989 uint32_t i; 1990 1991 if (init(t, 1, 4) < 0 || 1992 create_ports(t, 4) < 0 || 1993 create_atomic_qids(t, 1) < 0) { 1994 printf("%d: Error initializing device\n", __LINE__); 1995 return -1; 1996 } 1997 1998 for (i = 0; i < 3; i++) { 1999 /* map port 1 - 3 inclusive */ 2000 if (rte_event_port_link(evdev, t->port[i+1], &t->qid[0], 2001 NULL, 1) != 1) { 2002 printf("%d: error mapping qid to port %d\n", 2003 __LINE__, i); 2004 return -1; 2005 } 2006 } 2007 2008 if (rte_event_dev_start(evdev) < 0) { 2009 printf("%d: Error with start call\n", __LINE__); 2010 return -1; 2011 } 2012 2013 /************** FORWARD ****************/ 2014 /* 2015 * Create a set of flows that test the load-balancing operation of the 2016 * implementation. Fill CQ 0 and 1 with flows 0 and 1, and test 2017 * with a new flow, which should be sent to the 3rd mapped CQ 2018 */ 2019 static uint32_t flows[] = {0, 1, 1, 0, 0, 2, 2, 0, 2}; 2020 2021 for (i = 0; i < RTE_DIM(flows); i++) { 2022 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 2023 if (!arp) { 2024 printf("%d: gen of pkt failed\n", __LINE__); 2025 return -1; 2026 } 2027 2028 struct rte_event ev = { 2029 .op = RTE_EVENT_OP_NEW, 2030 .queue_id = t->qid[0], 2031 .flow_id = flows[i], 2032 .mbuf = arp, 2033 }; 2034 /* generate pkt and enqueue */ 2035 err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1); 2036 if (err != 1) { 2037 printf("%d: Failed to enqueue\n", __LINE__); 2038 return -1; 2039 } 2040 } 2041 2042 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2043 2044 struct test_event_dev_stats stats; 2045 err = test_event_dev_stats_get(evdev, &stats); 2046 if (err) { 2047 printf("%d: failed to get stats\n", __LINE__); 2048 return -1; 2049 } 2050 2051 if (stats.port_inflight[1] != 4) { 2052 printf("%d:%s: port 1 inflight not correct\n", __LINE__, 2053 __func__); 2054 return -1; 2055 } 2056 if (stats.port_inflight[2] != 2) { 2057 printf("%d:%s: port 2 inflight not correct\n", __LINE__, 2058 __func__); 2059 return -1; 2060 } 2061 if (stats.port_inflight[3] != 3) { 2062 printf("%d:%s: port 3 inflight not correct\n", __LINE__, 2063 __func__); 2064 return -1; 2065 } 2066 2067 cleanup(t); 2068 return 0; 2069 } 2070 2071 static int 2072 load_balancing_history(struct test *t) 2073 { 2074 struct test_event_dev_stats stats = {0}; 2075 const int rx_enq = 0; 2076 int err; 2077 uint32_t i; 2078 2079 /* Create instance with 1 atomic QID going to 3 ports + 1 prod port */ 2080 if (init(t, 1, 4) < 0 || 2081 create_ports(t, 4) < 0 || 2082 create_atomic_qids(t, 1) < 0) 2083 return -1; 2084 2085 /* CQ mapping to QID */ 2086 if (rte_event_port_link(evdev, t->port[1], &t->qid[0], NULL, 1) != 1) { 2087 printf("%d: error mapping port 1 qid\n", __LINE__); 2088 return -1; 2089 } 2090 if (rte_event_port_link(evdev, t->port[2], &t->qid[0], NULL, 1) != 1) { 2091 printf("%d: error mapping port 2 qid\n", __LINE__); 2092 return -1; 2093 } 2094 if (rte_event_port_link(evdev, t->port[3], &t->qid[0], NULL, 1) != 1) { 2095 printf("%d: error mapping port 3 qid\n", __LINE__); 2096 return -1; 2097 } 2098 if (rte_event_dev_start(evdev) < 0) { 2099 printf("%d: Error with start call\n", __LINE__); 2100 return -1; 2101 } 2102 2103 /* 2104 * Create a set of flows that test the load-balancing operation of the 2105 * implementation. Fill CQ 0, 1 and 2 with flows 0, 1 and 2, drop 2106 * the packet from CQ 0, send in a new set of flows. Ensure that: 2107 * 1. The new flow 3 gets into the empty CQ0 2108 * 2. packets for existing flow gets added into CQ1 2109 * 3. Next flow 0 pkt is now onto CQ2, since CQ0 and CQ1 now contain 2110 * more outstanding pkts 2111 * 2112 * This test makes sure that when a flow ends (i.e. all packets 2113 * have been completed for that flow), that the flow can be moved 2114 * to a different CQ when new packets come in for that flow. 2115 */ 2116 static uint32_t flows1[] = {0, 1, 1, 2}; 2117 2118 for (i = 0; i < RTE_DIM(flows1); i++) { 2119 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 2120 struct rte_event ev = { 2121 .flow_id = flows1[i], 2122 .op = RTE_EVENT_OP_NEW, 2123 .queue_id = t->qid[0], 2124 .event_type = RTE_EVENT_TYPE_CPU, 2125 .priority = RTE_EVENT_DEV_PRIORITY_NORMAL, 2126 .mbuf = arp 2127 }; 2128 2129 if (!arp) { 2130 printf("%d: gen of pkt failed\n", __LINE__); 2131 return -1; 2132 } 2133 arp->hash.rss = flows1[i]; 2134 err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1); 2135 if (err != 1) { 2136 printf("%d: Failed to enqueue\n", __LINE__); 2137 return -1; 2138 } 2139 } 2140 2141 /* call the scheduler */ 2142 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2143 2144 /* Dequeue the flow 0 packet from port 1, so that we can then drop */ 2145 struct rte_event ev; 2146 if (!rte_event_dequeue_burst(evdev, t->port[1], &ev, 1, 0)) { 2147 printf("%d: failed to dequeue\n", __LINE__); 2148 return -1; 2149 } 2150 if (ev.mbuf->hash.rss != flows1[0]) { 2151 printf("%d: unexpected flow received\n", __LINE__); 2152 return -1; 2153 } 2154 2155 /* drop the flow 0 packet from port 1 */ 2156 rte_event_enqueue_burst(evdev, t->port[1], &release_ev, 1); 2157 2158 /* call the scheduler */ 2159 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2160 2161 /* 2162 * Set up the next set of flows, first a new flow to fill up 2163 * CQ 0, so that the next flow 0 packet should go to CQ2 2164 */ 2165 static uint32_t flows2[] = { 3, 3, 3, 1, 1, 0 }; 2166 2167 for (i = 0; i < RTE_DIM(flows2); i++) { 2168 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 2169 struct rte_event ev = { 2170 .flow_id = flows2[i], 2171 .op = RTE_EVENT_OP_NEW, 2172 .queue_id = t->qid[0], 2173 .event_type = RTE_EVENT_TYPE_CPU, 2174 .priority = RTE_EVENT_DEV_PRIORITY_NORMAL, 2175 .mbuf = arp 2176 }; 2177 2178 if (!arp) { 2179 printf("%d: gen of pkt failed\n", __LINE__); 2180 return -1; 2181 } 2182 arp->hash.rss = flows2[i]; 2183 2184 err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1); 2185 if (err != 1) { 2186 printf("%d: Failed to enqueue\n", __LINE__); 2187 return -1; 2188 } 2189 } 2190 2191 /* schedule */ 2192 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2193 2194 err = test_event_dev_stats_get(evdev, &stats); 2195 if (err) { 2196 printf("%d:failed to get stats\n", __LINE__); 2197 return -1; 2198 } 2199 2200 /* 2201 * Now check the resulting inflights on each port. 2202 */ 2203 if (stats.port_inflight[1] != 3) { 2204 printf("%d:%s: port 1 inflight not correct\n", __LINE__, 2205 __func__); 2206 printf("Inflights, ports 1, 2, 3: %u, %u, %u\n", 2207 (unsigned int)stats.port_inflight[1], 2208 (unsigned int)stats.port_inflight[2], 2209 (unsigned int)stats.port_inflight[3]); 2210 return -1; 2211 } 2212 if (stats.port_inflight[2] != 4) { 2213 printf("%d:%s: port 2 inflight not correct\n", __LINE__, 2214 __func__); 2215 printf("Inflights, ports 1, 2, 3: %u, %u, %u\n", 2216 (unsigned int)stats.port_inflight[1], 2217 (unsigned int)stats.port_inflight[2], 2218 (unsigned int)stats.port_inflight[3]); 2219 return -1; 2220 } 2221 if (stats.port_inflight[3] != 2) { 2222 printf("%d:%s: port 3 inflight not correct\n", __LINE__, 2223 __func__); 2224 printf("Inflights, ports 1, 2, 3: %u, %u, %u\n", 2225 (unsigned int)stats.port_inflight[1], 2226 (unsigned int)stats.port_inflight[2], 2227 (unsigned int)stats.port_inflight[3]); 2228 return -1; 2229 } 2230 2231 for (i = 1; i <= 3; i++) { 2232 struct rte_event ev; 2233 while (rte_event_dequeue_burst(evdev, i, &ev, 1, 0)) 2234 rte_event_enqueue_burst(evdev, i, &release_ev, 1); 2235 } 2236 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2237 2238 cleanup(t); 2239 return 0; 2240 } 2241 2242 static int 2243 invalid_qid(struct test *t) 2244 { 2245 struct test_event_dev_stats stats; 2246 const int rx_enq = 0; 2247 int err; 2248 uint32_t i; 2249 2250 if (init(t, 1, 4) < 0 || 2251 create_ports(t, 4) < 0 || 2252 create_atomic_qids(t, 1) < 0) { 2253 printf("%d: Error initializing device\n", __LINE__); 2254 return -1; 2255 } 2256 2257 /* CQ mapping to QID */ 2258 for (i = 0; i < 4; i++) { 2259 err = rte_event_port_link(evdev, t->port[i], &t->qid[0], 2260 NULL, 1); 2261 if (err != 1) { 2262 printf("%d: error mapping port 1 qid\n", __LINE__); 2263 return -1; 2264 } 2265 } 2266 2267 if (rte_event_dev_start(evdev) < 0) { 2268 printf("%d: Error with start call\n", __LINE__); 2269 return -1; 2270 } 2271 2272 /* 2273 * Send in a packet with an invalid qid to the scheduler. 2274 * We should see the packed enqueued OK, but the inflights for 2275 * that packet should not be incremented, and the rx_dropped 2276 * should be incremented. 2277 */ 2278 static uint32_t flows1[] = {20}; 2279 2280 for (i = 0; i < RTE_DIM(flows1); i++) { 2281 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 2282 if (!arp) { 2283 printf("%d: gen of pkt failed\n", __LINE__); 2284 return -1; 2285 } 2286 2287 struct rte_event ev = { 2288 .op = RTE_EVENT_OP_NEW, 2289 .queue_id = t->qid[0] + flows1[i], 2290 .flow_id = i, 2291 .mbuf = arp, 2292 }; 2293 /* generate pkt and enqueue */ 2294 err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1); 2295 if (err != 1) { 2296 printf("%d: Failed to enqueue\n", __LINE__); 2297 return -1; 2298 } 2299 } 2300 2301 /* call the scheduler */ 2302 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2303 2304 err = test_event_dev_stats_get(evdev, &stats); 2305 if (err) { 2306 printf("%d: failed to get stats\n", __LINE__); 2307 return -1; 2308 } 2309 2310 /* 2311 * Now check the resulting inflights on the port, and the rx_dropped. 2312 */ 2313 if (stats.port_inflight[0] != 0) { 2314 printf("%d:%s: port 1 inflight count not correct\n", __LINE__, 2315 __func__); 2316 rte_event_dev_dump(evdev, stdout); 2317 return -1; 2318 } 2319 if (stats.port_rx_dropped[0] != 1) { 2320 printf("%d:%s: port 1 drops\n", __LINE__, __func__); 2321 rte_event_dev_dump(evdev, stdout); 2322 return -1; 2323 } 2324 /* each packet drop should only be counted in one place - port or dev */ 2325 if (stats.rx_dropped != 0) { 2326 printf("%d:%s: port 1 dropped count not correct\n", __LINE__, 2327 __func__); 2328 rte_event_dev_dump(evdev, stdout); 2329 return -1; 2330 } 2331 2332 cleanup(t); 2333 return 0; 2334 } 2335 2336 static int 2337 single_packet(struct test *t) 2338 { 2339 const uint32_t MAGIC_SEQN = 7321; 2340 struct rte_event ev; 2341 struct test_event_dev_stats stats; 2342 const int rx_enq = 0; 2343 const int wrk_enq = 2; 2344 int err; 2345 2346 /* Create instance with 4 ports */ 2347 if (init(t, 1, 4) < 0 || 2348 create_ports(t, 4) < 0 || 2349 create_atomic_qids(t, 1) < 0) { 2350 printf("%d: Error initializing device\n", __LINE__); 2351 return -1; 2352 } 2353 2354 /* CQ mapping to QID */ 2355 err = rte_event_port_link(evdev, t->port[wrk_enq], NULL, NULL, 0); 2356 if (err != 1) { 2357 printf("%d: error mapping lb qid\n", __LINE__); 2358 cleanup(t); 2359 return -1; 2360 } 2361 2362 if (rte_event_dev_start(evdev) < 0) { 2363 printf("%d: Error with start call\n", __LINE__); 2364 return -1; 2365 } 2366 2367 /************** Gen pkt and enqueue ****************/ 2368 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 2369 if (!arp) { 2370 printf("%d: gen of pkt failed\n", __LINE__); 2371 return -1; 2372 } 2373 2374 ev.op = RTE_EVENT_OP_NEW; 2375 ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL; 2376 ev.mbuf = arp; 2377 ev.queue_id = 0; 2378 ev.flow_id = 3; 2379 *rte_event_pmd_selftest_seqn(arp) = MAGIC_SEQN; 2380 2381 err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1); 2382 if (err != 1) { 2383 printf("%d: Failed to enqueue\n", __LINE__); 2384 return -1; 2385 } 2386 2387 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2388 2389 err = test_event_dev_stats_get(evdev, &stats); 2390 if (err) { 2391 printf("%d: failed to get stats\n", __LINE__); 2392 return -1; 2393 } 2394 2395 if (stats.rx_pkts != 1 || 2396 stats.tx_pkts != 1 || 2397 stats.port_inflight[wrk_enq] != 1) { 2398 printf("%d: Sched core didn't handle pkt as expected\n", 2399 __LINE__); 2400 rte_event_dev_dump(evdev, stdout); 2401 return -1; 2402 } 2403 2404 uint32_t deq_pkts; 2405 2406 deq_pkts = rte_event_dequeue_burst(evdev, t->port[wrk_enq], &ev, 1, 0); 2407 if (deq_pkts < 1) { 2408 printf("%d: Failed to deq\n", __LINE__); 2409 return -1; 2410 } 2411 2412 err = test_event_dev_stats_get(evdev, &stats); 2413 if (err) { 2414 printf("%d: failed to get stats\n", __LINE__); 2415 return -1; 2416 } 2417 2418 err = test_event_dev_stats_get(evdev, &stats); 2419 if (*rte_event_pmd_selftest_seqn(ev.mbuf) != MAGIC_SEQN) { 2420 printf("%d: magic sequence number not dequeued\n", __LINE__); 2421 return -1; 2422 } 2423 2424 rte_pktmbuf_free(ev.mbuf); 2425 err = rte_event_enqueue_burst(evdev, t->port[wrk_enq], &release_ev, 1); 2426 if (err != 1) { 2427 printf("%d: Failed to enqueue\n", __LINE__); 2428 return -1; 2429 } 2430 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2431 2432 err = test_event_dev_stats_get(evdev, &stats); 2433 if (stats.port_inflight[wrk_enq] != 0) { 2434 printf("%d: port inflight not correct\n", __LINE__); 2435 return -1; 2436 } 2437 2438 cleanup(t); 2439 return 0; 2440 } 2441 2442 static int 2443 inflight_counts(struct test *t) 2444 { 2445 struct rte_event ev; 2446 struct test_event_dev_stats stats; 2447 const int rx_enq = 0; 2448 const int p1 = 1; 2449 const int p2 = 2; 2450 int err; 2451 int i; 2452 2453 /* Create instance with 4 ports */ 2454 if (init(t, 2, 3) < 0 || 2455 create_ports(t, 3) < 0 || 2456 create_atomic_qids(t, 2) < 0) { 2457 printf("%d: Error initializing device\n", __LINE__); 2458 return -1; 2459 } 2460 2461 /* CQ mapping to QID */ 2462 err = rte_event_port_link(evdev, t->port[p1], &t->qid[0], NULL, 1); 2463 if (err != 1) { 2464 printf("%d: error mapping lb qid\n", __LINE__); 2465 cleanup(t); 2466 return -1; 2467 } 2468 err = rte_event_port_link(evdev, t->port[p2], &t->qid[1], NULL, 1); 2469 if (err != 1) { 2470 printf("%d: error mapping lb qid\n", __LINE__); 2471 cleanup(t); 2472 return -1; 2473 } 2474 2475 if (rte_event_dev_start(evdev) < 0) { 2476 printf("%d: Error with start call\n", __LINE__); 2477 return -1; 2478 } 2479 2480 /************** FORWARD ****************/ 2481 #define QID1_NUM 5 2482 for (i = 0; i < QID1_NUM; i++) { 2483 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 2484 2485 if (!arp) { 2486 printf("%d: gen of pkt failed\n", __LINE__); 2487 goto err; 2488 } 2489 2490 ev.queue_id = t->qid[0]; 2491 ev.op = RTE_EVENT_OP_NEW; 2492 ev.mbuf = arp; 2493 err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1); 2494 if (err != 1) { 2495 printf("%d: Failed to enqueue\n", __LINE__); 2496 goto err; 2497 } 2498 } 2499 #define QID2_NUM 3 2500 for (i = 0; i < QID2_NUM; i++) { 2501 struct rte_mbuf *arp = rte_gen_arp(0, t->mbuf_pool); 2502 2503 if (!arp) { 2504 printf("%d: gen of pkt failed\n", __LINE__); 2505 goto err; 2506 } 2507 ev.queue_id = t->qid[1]; 2508 ev.op = RTE_EVENT_OP_NEW; 2509 ev.mbuf = arp; 2510 err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1); 2511 if (err != 1) { 2512 printf("%d: Failed to enqueue\n", __LINE__); 2513 goto err; 2514 } 2515 } 2516 2517 /* schedule */ 2518 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2519 2520 err = test_event_dev_stats_get(evdev, &stats); 2521 if (err) { 2522 printf("%d: failed to get stats\n", __LINE__); 2523 goto err; 2524 } 2525 2526 if (stats.rx_pkts != QID1_NUM + QID2_NUM || 2527 stats.tx_pkts != QID1_NUM + QID2_NUM) { 2528 printf("%d: Sched core didn't handle pkt as expected\n", 2529 __LINE__); 2530 goto err; 2531 } 2532 2533 if (stats.port_inflight[p1] != QID1_NUM) { 2534 printf("%d: %s port 1 inflight not correct\n", __LINE__, 2535 __func__); 2536 goto err; 2537 } 2538 if (stats.port_inflight[p2] != QID2_NUM) { 2539 printf("%d: %s port 2 inflight not correct\n", __LINE__, 2540 __func__); 2541 goto err; 2542 } 2543 2544 /************** DEQUEUE INFLIGHT COUNT CHECKS ****************/ 2545 /* port 1 */ 2546 struct rte_event events[QID1_NUM + QID2_NUM]; 2547 uint32_t deq_pkts = rte_event_dequeue_burst(evdev, t->port[p1], events, 2548 RTE_DIM(events), 0); 2549 2550 if (deq_pkts != QID1_NUM) { 2551 printf("%d: Port 1: DEQUEUE inflight failed\n", __LINE__); 2552 goto err; 2553 } 2554 err = test_event_dev_stats_get(evdev, &stats); 2555 if (stats.port_inflight[p1] != QID1_NUM) { 2556 printf("%d: port 1 inflight decrement after DEQ != 0\n", 2557 __LINE__); 2558 goto err; 2559 } 2560 for (i = 0; i < QID1_NUM; i++) { 2561 err = rte_event_enqueue_burst(evdev, t->port[p1], &release_ev, 2562 1); 2563 if (err != 1) { 2564 printf("%d: %s rte enqueue of inf release failed\n", 2565 __LINE__, __func__); 2566 goto err; 2567 } 2568 } 2569 2570 /* 2571 * As the scheduler core decrements inflights, it needs to run to 2572 * process packets to act on the drop messages 2573 */ 2574 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2575 2576 err = test_event_dev_stats_get(evdev, &stats); 2577 if (stats.port_inflight[p1] != 0) { 2578 printf("%d: port 1 inflight NON NULL after DROP\n", __LINE__); 2579 goto err; 2580 } 2581 2582 /* port2 */ 2583 deq_pkts = rte_event_dequeue_burst(evdev, t->port[p2], events, 2584 RTE_DIM(events), 0); 2585 if (deq_pkts != QID2_NUM) { 2586 printf("%d: Port 2: DEQUEUE inflight failed\n", __LINE__); 2587 goto err; 2588 } 2589 err = test_event_dev_stats_get(evdev, &stats); 2590 if (stats.port_inflight[p2] != QID2_NUM) { 2591 printf("%d: port 1 inflight decrement after DEQ != 0\n", 2592 __LINE__); 2593 goto err; 2594 } 2595 for (i = 0; i < QID2_NUM; i++) { 2596 err = rte_event_enqueue_burst(evdev, t->port[p2], &release_ev, 2597 1); 2598 if (err != 1) { 2599 printf("%d: %s rte enqueue of inf release failed\n", 2600 __LINE__, __func__); 2601 goto err; 2602 } 2603 } 2604 2605 /* 2606 * As the scheduler core decrements inflights, it needs to run to 2607 * process packets to act on the drop messages 2608 */ 2609 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2610 2611 err = test_event_dev_stats_get(evdev, &stats); 2612 if (stats.port_inflight[p2] != 0) { 2613 printf("%d: port 2 inflight NON NULL after DROP\n", __LINE__); 2614 goto err; 2615 } 2616 cleanup(t); 2617 return 0; 2618 2619 err: 2620 rte_event_dev_dump(evdev, stdout); 2621 cleanup(t); 2622 return -1; 2623 } 2624 2625 static int 2626 parallel_basic(struct test *t, int check_order) 2627 { 2628 const uint8_t rx_port = 0; 2629 const uint8_t w1_port = 1; 2630 const uint8_t w3_port = 3; 2631 const uint8_t tx_port = 4; 2632 int err; 2633 int i; 2634 uint32_t deq_pkts, j; 2635 struct rte_mbuf *mbufs[3]; 2636 struct rte_mbuf *mbufs_out[3] = { 0 }; 2637 const uint32_t MAGIC_SEQN = 1234; 2638 2639 /* Create instance with 4 ports */ 2640 if (init(t, 2, tx_port + 1) < 0 || 2641 create_ports(t, tx_port + 1) < 0 || 2642 (check_order ? create_ordered_qids(t, 1) : 2643 create_unordered_qids(t, 1)) < 0 || 2644 create_directed_qids(t, 1, &tx_port)) { 2645 printf("%d: Error initializing device\n", __LINE__); 2646 return -1; 2647 } 2648 2649 /* 2650 * CQ mapping to QID 2651 * We need three ports, all mapped to the same ordered qid0. Then we'll 2652 * take a packet out to each port, re-enqueue in reverse order, 2653 * then make sure the reordering has taken place properly when we 2654 * dequeue from the tx_port. 2655 * 2656 * Simplified test setup diagram: 2657 * 2658 * rx_port w1_port 2659 * \ / \ 2660 * qid0 - w2_port - qid1 2661 * \ / \ 2662 * w3_port tx_port 2663 */ 2664 /* CQ mapping to QID for LB ports (directed mapped on create) */ 2665 for (i = w1_port; i <= w3_port; i++) { 2666 err = rte_event_port_link(evdev, t->port[i], &t->qid[0], NULL, 2667 1); 2668 if (err != 1) { 2669 printf("%d: error mapping lb qid\n", __LINE__); 2670 cleanup(t); 2671 return -1; 2672 } 2673 } 2674 2675 if (rte_event_dev_start(evdev) < 0) { 2676 printf("%d: Error with start call\n", __LINE__); 2677 return -1; 2678 } 2679 2680 /* Enqueue 3 packets to the rx port */ 2681 for (i = 0; i < 3; i++) { 2682 struct rte_event ev; 2683 mbufs[i] = rte_gen_arp(0, t->mbuf_pool); 2684 if (!mbufs[i]) { 2685 printf("%d: gen of pkt failed\n", __LINE__); 2686 return -1; 2687 } 2688 2689 ev.queue_id = t->qid[0]; 2690 ev.op = RTE_EVENT_OP_NEW; 2691 ev.mbuf = mbufs[i]; 2692 *rte_event_pmd_selftest_seqn(mbufs[i]) = MAGIC_SEQN + i; 2693 2694 /* generate pkt and enqueue */ 2695 err = rte_event_enqueue_burst(evdev, t->port[rx_port], &ev, 1); 2696 if (err != 1) { 2697 printf("%d: Failed to enqueue pkt %u, retval = %u\n", 2698 __LINE__, i, err); 2699 return -1; 2700 } 2701 } 2702 2703 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2704 2705 /* use extra slot to make logic in loops easier */ 2706 struct rte_event deq_ev[w3_port + 1]; 2707 2708 /* Dequeue the 3 packets, one from each worker port */ 2709 for (i = w1_port; i <= w3_port; i++) { 2710 deq_pkts = rte_event_dequeue_burst(evdev, t->port[i], 2711 &deq_ev[i], 1, 0); 2712 if (deq_pkts != 1) { 2713 printf("%d: Failed to deq\n", __LINE__); 2714 rte_event_dev_dump(evdev, stdout); 2715 return -1; 2716 } 2717 } 2718 2719 /* Enqueue each packet in reverse order, flushing after each one */ 2720 for (i = w3_port; i >= w1_port; i--) { 2721 2722 deq_ev[i].op = RTE_EVENT_OP_FORWARD; 2723 deq_ev[i].queue_id = t->qid[1]; 2724 err = rte_event_enqueue_burst(evdev, t->port[i], &deq_ev[i], 1); 2725 if (err != 1) { 2726 printf("%d: Failed to enqueue\n", __LINE__); 2727 return -1; 2728 } 2729 } 2730 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2731 2732 /* dequeue from the tx ports, we should get 3 packets */ 2733 deq_pkts = rte_event_dequeue_burst(evdev, t->port[tx_port], deq_ev, 2734 3, 0); 2735 2736 /* Check to see if we've got all 3 packets */ 2737 if (deq_pkts != 3) { 2738 printf("%d: expected 3 pkts at tx port got %d from port %d\n", 2739 __LINE__, deq_pkts, tx_port); 2740 rte_event_dev_dump(evdev, stdout); 2741 return 1; 2742 } 2743 2744 /* Check to see if the sequence numbers are in expected order */ 2745 if (check_order) { 2746 for (j = 0 ; j < deq_pkts ; j++) { 2747 if (*rte_event_pmd_selftest_seqn(deq_ev[j].mbuf) != 2748 MAGIC_SEQN + j) { 2749 printf("%d: Incorrect sequence number(%d) from port %d\n", 2750 __LINE__, 2751 *rte_event_pmd_selftest_seqn(mbufs_out[j]), 2752 tx_port); 2753 return -1; 2754 } 2755 } 2756 } 2757 2758 /* Destroy the instance */ 2759 cleanup(t); 2760 return 0; 2761 } 2762 2763 static int 2764 ordered_basic(struct test *t) 2765 { 2766 return parallel_basic(t, 1); 2767 } 2768 2769 static int 2770 unordered_basic(struct test *t) 2771 { 2772 return parallel_basic(t, 0); 2773 } 2774 2775 static int 2776 holb(struct test *t) /* test to check we avoid basic head-of-line blocking */ 2777 { 2778 const struct rte_event new_ev = { 2779 .op = RTE_EVENT_OP_NEW 2780 /* all other fields zero */ 2781 }; 2782 struct rte_event ev = new_ev; 2783 unsigned int rx_port = 0; /* port we get the first flow on */ 2784 char rx_port_used_stat[64]; 2785 char rx_port_free_stat[64]; 2786 char other_port_used_stat[64]; 2787 2788 if (init(t, 1, 2) < 0 || 2789 create_ports(t, 2) < 0 || 2790 create_atomic_qids(t, 1) < 0) { 2791 printf("%d: Error initializing device\n", __LINE__); 2792 return -1; 2793 } 2794 int nb_links = rte_event_port_link(evdev, t->port[1], NULL, NULL, 0); 2795 if (rte_event_port_link(evdev, t->port[0], NULL, NULL, 0) != 1 || 2796 nb_links != 1) { 2797 printf("%d: Error links queue to ports\n", __LINE__); 2798 goto err; 2799 } 2800 if (rte_event_dev_start(evdev) < 0) { 2801 printf("%d: Error with start call\n", __LINE__); 2802 goto err; 2803 } 2804 2805 /* send one packet and see where it goes, port 0 or 1 */ 2806 if (rte_event_enqueue_burst(evdev, t->port[0], &ev, 1) != 1) { 2807 printf("%d: Error doing first enqueue\n", __LINE__); 2808 goto err; 2809 } 2810 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2811 2812 if (rte_event_dev_xstats_by_name_get(evdev, "port_0_cq_ring_used", NULL) 2813 != 1) 2814 rx_port = 1; 2815 2816 snprintf(rx_port_used_stat, sizeof(rx_port_used_stat), 2817 "port_%u_cq_ring_used", rx_port); 2818 snprintf(rx_port_free_stat, sizeof(rx_port_free_stat), 2819 "port_%u_cq_ring_free", rx_port); 2820 snprintf(other_port_used_stat, sizeof(other_port_used_stat), 2821 "port_%u_cq_ring_used", rx_port ^ 1); 2822 if (rte_event_dev_xstats_by_name_get(evdev, rx_port_used_stat, NULL) 2823 != 1) { 2824 printf("%d: Error, first event not scheduled\n", __LINE__); 2825 goto err; 2826 } 2827 2828 /* now fill up the rx port's queue with one flow to cause HOLB */ 2829 do { 2830 ev = new_ev; 2831 if (rte_event_enqueue_burst(evdev, t->port[0], &ev, 1) != 1) { 2832 printf("%d: Error with enqueue\n", __LINE__); 2833 goto err; 2834 } 2835 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2836 } while (rte_event_dev_xstats_by_name_get(evdev, 2837 rx_port_free_stat, NULL) != 0); 2838 2839 /* one more packet, which needs to stay in IQ - i.e. HOLB */ 2840 ev = new_ev; 2841 if (rte_event_enqueue_burst(evdev, t->port[0], &ev, 1) != 1) { 2842 printf("%d: Error with enqueue\n", __LINE__); 2843 goto err; 2844 } 2845 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2846 2847 /* check that the other port still has an empty CQ */ 2848 if (rte_event_dev_xstats_by_name_get(evdev, other_port_used_stat, NULL) 2849 != 0) { 2850 printf("%d: Error, second port CQ is not empty\n", __LINE__); 2851 goto err; 2852 } 2853 /* check IQ now has one packet */ 2854 if (rte_event_dev_xstats_by_name_get(evdev, "qid_0_iq_0_used", NULL) 2855 != 1) { 2856 printf("%d: Error, QID does not have exactly 1 packet\n", 2857 __LINE__); 2858 goto err; 2859 } 2860 2861 /* send another flow, which should pass the other IQ entry */ 2862 ev = new_ev; 2863 ev.flow_id = 1; 2864 if (rte_event_enqueue_burst(evdev, t->port[0], &ev, 1) != 1) { 2865 printf("%d: Error with enqueue\n", __LINE__); 2866 goto err; 2867 } 2868 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2869 2870 if (rte_event_dev_xstats_by_name_get(evdev, other_port_used_stat, NULL) 2871 != 1) { 2872 printf("%d: Error, second flow did not pass out first\n", 2873 __LINE__); 2874 goto err; 2875 } 2876 2877 if (rte_event_dev_xstats_by_name_get(evdev, "qid_0_iq_0_used", NULL) 2878 != 1) { 2879 printf("%d: Error, QID does not have exactly 1 packet\n", 2880 __LINE__); 2881 goto err; 2882 } 2883 cleanup(t); 2884 return 0; 2885 err: 2886 rte_event_dev_dump(evdev, stdout); 2887 cleanup(t); 2888 return -1; 2889 } 2890 2891 static void 2892 flush(uint8_t dev_id __rte_unused, struct rte_event event, void *arg) 2893 { 2894 *((uint8_t *) arg) += (event.u64 == 0xCA11BACC) ? 1 : 0; 2895 } 2896 2897 static int 2898 dev_stop_flush(struct test *t) /* test to check we can properly flush events */ 2899 { 2900 const struct rte_event new_ev = { 2901 .op = RTE_EVENT_OP_NEW, 2902 .u64 = 0xCA11BACC, 2903 .queue_id = 0 2904 }; 2905 struct rte_event ev = new_ev; 2906 uint8_t count = 0; 2907 int i; 2908 2909 if (init(t, 1, 1) < 0 || 2910 create_ports(t, 1) < 0 || 2911 create_atomic_qids(t, 1) < 0) { 2912 printf("%d: Error initializing device\n", __LINE__); 2913 return -1; 2914 } 2915 2916 /* Link the queue so *_start() doesn't error out */ 2917 if (rte_event_port_link(evdev, t->port[0], NULL, NULL, 0) != 1) { 2918 printf("%d: Error linking queue to port\n", __LINE__); 2919 goto err; 2920 } 2921 2922 if (rte_event_dev_start(evdev) < 0) { 2923 printf("%d: Error with start call\n", __LINE__); 2924 goto err; 2925 } 2926 2927 for (i = 0; i < DEQUEUE_DEPTH + 1; i++) { 2928 if (rte_event_enqueue_burst(evdev, t->port[0], &ev, 1) != 1) { 2929 printf("%d: Error enqueuing events\n", __LINE__); 2930 goto err; 2931 } 2932 } 2933 2934 /* Schedule the events from the port to the IQ. At least one event 2935 * should be remaining in the queue. 2936 */ 2937 rte_service_run_iter_on_app_lcore(t->service_id, 1); 2938 2939 if (rte_event_dev_stop_flush_callback_register(evdev, flush, &count)) { 2940 printf("%d: Error installing the flush callback\n", __LINE__); 2941 goto err; 2942 } 2943 2944 cleanup(t); 2945 2946 if (count == 0) { 2947 printf("%d: Error executing the flush callback\n", __LINE__); 2948 goto err; 2949 } 2950 2951 if (rte_event_dev_stop_flush_callback_register(evdev, NULL, NULL)) { 2952 printf("%d: Error uninstalling the flush callback\n", __LINE__); 2953 goto err; 2954 } 2955 2956 return 0; 2957 err: 2958 rte_event_dev_dump(evdev, stdout); 2959 cleanup(t); 2960 return -1; 2961 } 2962 2963 static int 2964 ordered_atomic_hist_completion(struct test *t) 2965 { 2966 const int rx_enq = 0; 2967 int err; 2968 2969 /* Create instance with 1 atomic QID going to 3 ports + 1 prod port */ 2970 if (init(t, 2, 2) < 0 || 2971 create_ports(t, 2) < 0 || 2972 create_ordered_qids(t, 1) < 0 || 2973 create_atomic_qids(t, 1) < 0) 2974 return -1; 2975 2976 /* Helpers to identify queues */ 2977 const uint8_t qid_ordered = t->qid[0]; 2978 const uint8_t qid_atomic = t->qid[1]; 2979 2980 /* CQ mapping to QID */ 2981 if (rte_event_port_link(evdev, t->port[1], &t->qid[0], NULL, 1) != 1) { 2982 printf("%d: error mapping port 1 qid\n", __LINE__); 2983 return -1; 2984 } 2985 if (rte_event_port_link(evdev, t->port[1], &t->qid[1], NULL, 1) != 1) { 2986 printf("%d: error mapping port 1 qid\n", __LINE__); 2987 return -1; 2988 } 2989 if (rte_event_dev_start(evdev) < 0) { 2990 printf("%d: Error with start call\n", __LINE__); 2991 return -1; 2992 } 2993 2994 /* Enqueue 1x ordered event, to be RELEASE-ed by the worker 2995 * CPU, which may cause hist-list corruption (by not comleting) 2996 */ 2997 struct rte_event ord_ev = { 2998 .op = RTE_EVENT_OP_NEW, 2999 .queue_id = qid_ordered, 3000 .event_type = RTE_EVENT_TYPE_CPU, 3001 .priority = RTE_EVENT_DEV_PRIORITY_NORMAL, 3002 }; 3003 err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ord_ev, 1); 3004 if (err != 1) { 3005 printf("%d: Failed to enqueue\n", __LINE__); 3006 return -1; 3007 } 3008 3009 /* call the scheduler. This schedules the above event as a single 3010 * event in an ORDERED queue, to the worker. 3011 */ 3012 rte_service_run_iter_on_app_lcore(t->service_id, 1); 3013 3014 /* Dequeue ORDERED event 0 from port 1, so that we can then drop */ 3015 struct rte_event ev; 3016 if (!rte_event_dequeue_burst(evdev, t->port[1], &ev, 1, 0)) { 3017 printf("%d: failed to dequeue\n", __LINE__); 3018 return -1; 3019 } 3020 3021 /* drop the ORDERED event. Here the history list should be completed, 3022 * but might not be if the hist-list bug exists. Call scheduler to make 3023 * it act on the RELEASE that was enqueued. 3024 */ 3025 rte_event_enqueue_burst(evdev, t->port[1], &release_ev, 1); 3026 rte_service_run_iter_on_app_lcore(t->service_id, 1); 3027 3028 /* Enqueue 1x atomic event, to then FORWARD to trigger atomic hist-list 3029 * completion. If the bug exists, the ORDERED entry may be completed in 3030 * error (aka, using the ORDERED-ROB for the ATOMIC event). This is the 3031 * main focus of this unit test. 3032 */ 3033 { 3034 struct rte_event ev = { 3035 .op = RTE_EVENT_OP_NEW, 3036 .queue_id = qid_atomic, 3037 .event_type = RTE_EVENT_TYPE_CPU, 3038 .priority = RTE_EVENT_DEV_PRIORITY_NORMAL, 3039 .flow_id = 123, 3040 }; 3041 3042 err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1); 3043 if (err != 1) { 3044 printf("%d: Failed to enqueue\n", __LINE__); 3045 return -1; 3046 } 3047 } 3048 rte_service_run_iter_on_app_lcore(t->service_id, 1); 3049 3050 /* Deq ATM event, then forward it for more than HIST_LIST_SIZE times, 3051 * to re-use the history list entry that may be corrupted previously. 3052 */ 3053 for (int i = 0; i < SW_PORT_HIST_LIST + 2; i++) { 3054 if (!rte_event_dequeue_burst(evdev, t->port[1], &ev, 1, 0)) { 3055 printf("%d: failed to dequeue, did corrupt ORD hist " 3056 "list steal this ATM event?\n", __LINE__); 3057 return -1; 3058 } 3059 3060 /* Re-enqueue the ATM event as FWD, trigger hist-list. */ 3061 ev.op = RTE_EVENT_OP_FORWARD; 3062 err = rte_event_enqueue_burst(evdev, t->port[1], &ev, 1); 3063 if (err != 1) { 3064 printf("%d: Failed to enqueue\n", __LINE__); 3065 return -1; 3066 } 3067 3068 rte_service_run_iter_on_app_lcore(t->service_id, 1); 3069 } 3070 3071 /* If HIST-LIST + N count of dequeues succeed above, the hist list 3072 * has not been corrupted. If it is corrupted, the ATM event is pushed 3073 * into the ORDERED-ROB and will not dequeue. 3074 */ 3075 3076 /* release the ATM event that's been forwarded HIST_LIST times */ 3077 err = rte_event_enqueue_burst(evdev, t->port[1], &release_ev, 1); 3078 if (err != 1) { 3079 printf("%d: Failed to enqueue\n", __LINE__); 3080 return -1; 3081 } 3082 3083 rte_service_run_iter_on_app_lcore(t->service_id, 1); 3084 3085 cleanup(t); 3086 return 0; 3087 } 3088 3089 static int 3090 worker_loopback_worker_fn(void *arg) 3091 { 3092 struct test *t = arg; 3093 uint8_t port = t->port[1]; 3094 int count = 0; 3095 int enqd; 3096 3097 /* 3098 * Takes packets from the input port and then loops them back through 3099 * the Eventdev. Each packet gets looped through QIDs 0-8, 16 times 3100 * so each packet goes through 8*16 = 128 times. 3101 */ 3102 printf("%d: \tWorker function started\n", __LINE__); 3103 while (count < NUM_PACKETS) { 3104 #define BURST_SIZE 32 3105 struct rte_event ev[BURST_SIZE]; 3106 uint16_t i, nb_rx = rte_event_dequeue_burst(evdev, port, ev, 3107 BURST_SIZE, 0); 3108 if (nb_rx == 0) { 3109 rte_pause(); 3110 continue; 3111 } 3112 3113 for (i = 0; i < nb_rx; i++) { 3114 ev[i].queue_id++; 3115 if (ev[i].queue_id != 8) { 3116 ev[i].op = RTE_EVENT_OP_FORWARD; 3117 enqd = rte_event_enqueue_burst(evdev, port, 3118 &ev[i], 1); 3119 if (enqd != 1) { 3120 printf("%d: Can't enqueue FWD!!\n", 3121 __LINE__); 3122 return -1; 3123 } 3124 continue; 3125 } 3126 3127 ev[i].queue_id = 0; 3128 (*counter_field(ev[i].mbuf))++; 3129 if (*counter_field(ev[i].mbuf) != 16) { 3130 ev[i].op = RTE_EVENT_OP_FORWARD; 3131 enqd = rte_event_enqueue_burst(evdev, port, 3132 &ev[i], 1); 3133 if (enqd != 1) { 3134 printf("%d: Can't enqueue FWD!!\n", 3135 __LINE__); 3136 return -1; 3137 } 3138 continue; 3139 } 3140 /* we have hit 16 iterations through system - drop */ 3141 rte_pktmbuf_free(ev[i].mbuf); 3142 count++; 3143 ev[i].op = RTE_EVENT_OP_RELEASE; 3144 enqd = rte_event_enqueue_burst(evdev, port, &ev[i], 1); 3145 if (enqd != 1) { 3146 printf("%d drop enqueue failed\n", __LINE__); 3147 return -1; 3148 } 3149 } 3150 } 3151 3152 return 0; 3153 } 3154 3155 static int 3156 worker_loopback_producer_fn(void *arg) 3157 { 3158 struct test *t = arg; 3159 uint8_t port = t->port[0]; 3160 uint64_t count = 0; 3161 3162 printf("%d: \tProducer function started\n", __LINE__); 3163 while (count < NUM_PACKETS) { 3164 struct rte_mbuf *m = 0; 3165 do { 3166 m = rte_pktmbuf_alloc(t->mbuf_pool); 3167 } while (m == NULL); 3168 3169 *counter_field(m) = 0; 3170 3171 struct rte_event ev = { 3172 .op = RTE_EVENT_OP_NEW, 3173 .queue_id = t->qid[0], 3174 .flow_id = (uintptr_t)m & 0xFFFF, 3175 .mbuf = m, 3176 }; 3177 3178 if (rte_event_enqueue_burst(evdev, port, &ev, 1) != 1) { 3179 while (rte_event_enqueue_burst(evdev, port, &ev, 1) != 3180 1) 3181 rte_pause(); 3182 } 3183 3184 count++; 3185 } 3186 3187 return 0; 3188 } 3189 3190 static int 3191 worker_loopback(struct test *t, uint8_t disable_implicit_release) 3192 { 3193 /* use a single producer core, and a worker core to see what happens 3194 * if the worker loops packets back multiple times 3195 */ 3196 struct test_event_dev_stats stats; 3197 uint64_t print_cycles = 0, cycles = 0; 3198 uint64_t tx_pkts = 0; 3199 int err; 3200 int w_lcore, p_lcore; 3201 3202 static const struct rte_mbuf_dynfield counter_dynfield_desc = { 3203 .name = "rte_event_sw_dynfield_selftest_counter", 3204 .size = sizeof(counter_dynfield_t), 3205 .align = alignof(counter_dynfield_t), 3206 }; 3207 counter_dynfield_offset = 3208 rte_mbuf_dynfield_register(&counter_dynfield_desc); 3209 if (counter_dynfield_offset < 0) { 3210 printf("Error registering mbuf field\n"); 3211 return -rte_errno; 3212 } 3213 3214 if (init(t, 8, 2) < 0 || 3215 create_atomic_qids(t, 8) < 0) { 3216 printf("%d: Error initializing device\n", __LINE__); 3217 return -1; 3218 } 3219 3220 /* RX with low max events */ 3221 static struct rte_event_port_conf conf = { 3222 .dequeue_depth = 32, 3223 .enqueue_depth = 64, 3224 }; 3225 /* beware: this cannot be initialized in the static above as it would 3226 * only be initialized once - and this needs to be set for multiple runs 3227 */ 3228 conf.new_event_threshold = 512; 3229 conf.event_port_cfg = disable_implicit_release ? 3230 RTE_EVENT_PORT_CFG_DISABLE_IMPL_REL : 0; 3231 3232 if (rte_event_port_setup(evdev, 0, &conf) < 0) { 3233 printf("Error setting up RX port\n"); 3234 return -1; 3235 } 3236 t->port[0] = 0; 3237 /* TX with higher max events */ 3238 conf.new_event_threshold = 4096; 3239 if (rte_event_port_setup(evdev, 1, &conf) < 0) { 3240 printf("Error setting up TX port\n"); 3241 return -1; 3242 } 3243 t->port[1] = 1; 3244 3245 /* CQ mapping to QID */ 3246 err = rte_event_port_link(evdev, t->port[1], NULL, NULL, 0); 3247 if (err != 8) { /* should have mapped all queues*/ 3248 printf("%d: error mapping port 2 to all qids\n", __LINE__); 3249 return -1; 3250 } 3251 3252 if (rte_event_dev_start(evdev) < 0) { 3253 printf("%d: Error with start call\n", __LINE__); 3254 return -1; 3255 } 3256 3257 p_lcore = rte_get_next_lcore( 3258 /* start core */ -1, 3259 /* skip main */ 1, 3260 /* wrap */ 0); 3261 w_lcore = rte_get_next_lcore(p_lcore, 1, 0); 3262 3263 rte_eal_remote_launch(worker_loopback_producer_fn, t, p_lcore); 3264 rte_eal_remote_launch(worker_loopback_worker_fn, t, w_lcore); 3265 3266 print_cycles = cycles = rte_get_timer_cycles(); 3267 while (rte_eal_get_lcore_state(p_lcore) != WAIT || 3268 rte_eal_get_lcore_state(w_lcore) != WAIT) { 3269 3270 rte_service_run_iter_on_app_lcore(t->service_id, 1); 3271 3272 uint64_t new_cycles = rte_get_timer_cycles(); 3273 3274 if (new_cycles - print_cycles > rte_get_timer_hz()) { 3275 test_event_dev_stats_get(evdev, &stats); 3276 printf( 3277 "%d: \tSched Rx = %"PRIu64", Tx = %"PRIu64"\n", 3278 __LINE__, stats.rx_pkts, stats.tx_pkts); 3279 3280 print_cycles = new_cycles; 3281 } 3282 if (new_cycles - cycles > rte_get_timer_hz() * 3) { 3283 test_event_dev_stats_get(evdev, &stats); 3284 if (stats.tx_pkts == tx_pkts) { 3285 rte_event_dev_dump(evdev, stdout); 3286 printf("Dumping xstats:\n"); 3287 xstats_print(); 3288 printf( 3289 "%d: No schedules for seconds, deadlock\n", 3290 __LINE__); 3291 return -1; 3292 } 3293 tx_pkts = stats.tx_pkts; 3294 cycles = new_cycles; 3295 } 3296 } 3297 rte_service_run_iter_on_app_lcore(t->service_id, 1); 3298 /* ensure all completions are flushed */ 3299 3300 rte_eal_mp_wait_lcore(); 3301 3302 cleanup(t); 3303 return 0; 3304 } 3305 3306 static struct rte_mempool *eventdev_func_mempool; 3307 3308 int 3309 test_sw_eventdev(void) 3310 { 3311 struct test *t; 3312 int ret; 3313 3314 t = malloc(sizeof(struct test)); 3315 if (t == NULL) 3316 return -1; 3317 /* manually initialize the op, older gcc's complain on static 3318 * initialization of struct elements that are a bitfield. 3319 */ 3320 release_ev.op = RTE_EVENT_OP_RELEASE; 3321 3322 const char *eventdev_name = "event_sw"; 3323 evdev = rte_event_dev_get_dev_id(eventdev_name); 3324 if (evdev < 0) { 3325 printf("%d: Eventdev %s not found - creating.\n", 3326 __LINE__, eventdev_name); 3327 if (rte_vdev_init(eventdev_name, NULL) < 0) { 3328 printf("Error creating eventdev\n"); 3329 goto test_fail; 3330 } 3331 evdev = rte_event_dev_get_dev_id(eventdev_name); 3332 if (evdev < 0) { 3333 printf("Error finding newly created eventdev\n"); 3334 goto test_fail; 3335 } 3336 } 3337 3338 if (rte_event_dev_service_id_get(evdev, &t->service_id) < 0) { 3339 printf("Failed to get service ID for software event dev\n"); 3340 goto test_fail; 3341 } 3342 3343 rte_service_runstate_set(t->service_id, 1); 3344 rte_service_set_runstate_mapped_check(t->service_id, 0); 3345 3346 /* Only create mbuf pool once, reuse for each test run */ 3347 if (!eventdev_func_mempool) { 3348 eventdev_func_mempool = rte_pktmbuf_pool_create( 3349 "EVENTDEV_SW_SA_MBUF_POOL", 3350 (1<<12), /* 4k buffers */ 3351 32 /*MBUF_CACHE_SIZE*/, 3352 0, 3353 512, /* use very small mbufs */ 3354 rte_socket_id()); 3355 if (!eventdev_func_mempool) { 3356 printf("ERROR creating mempool\n"); 3357 goto test_fail; 3358 } 3359 } 3360 t->mbuf_pool = eventdev_func_mempool; 3361 printf("*** Running Single Directed Packet test...\n"); 3362 ret = test_single_directed_packet(t); 3363 if (ret != 0) { 3364 printf("ERROR - Single Directed Packet test FAILED.\n"); 3365 goto test_fail; 3366 } 3367 printf("*** Running Directed Forward Credit test...\n"); 3368 ret = test_directed_forward_credits(t); 3369 if (ret != 0) { 3370 printf("ERROR - Directed Forward Credit test FAILED.\n"); 3371 goto test_fail; 3372 } 3373 printf("*** Running Single Load Balanced Packet test...\n"); 3374 ret = single_packet(t); 3375 if (ret != 0) { 3376 printf("ERROR - Single Packet test FAILED.\n"); 3377 goto test_fail; 3378 } 3379 printf("*** Running Unordered Basic test...\n"); 3380 ret = unordered_basic(t); 3381 if (ret != 0) { 3382 printf("ERROR - Unordered Basic test FAILED.\n"); 3383 goto test_fail; 3384 } 3385 printf("*** Running Ordered Basic test...\n"); 3386 ret = ordered_basic(t); 3387 if (ret != 0) { 3388 printf("ERROR - Ordered Basic test FAILED.\n"); 3389 goto test_fail; 3390 } 3391 printf("*** Running Burst Packets test...\n"); 3392 ret = burst_packets(t); 3393 if (ret != 0) { 3394 printf("ERROR - Burst Packets test FAILED.\n"); 3395 goto test_fail; 3396 } 3397 printf("*** Running Load Balancing test...\n"); 3398 ret = load_balancing(t); 3399 if (ret != 0) { 3400 printf("ERROR - Load Balancing test FAILED.\n"); 3401 goto test_fail; 3402 } 3403 printf("*** Running Prioritized Directed test...\n"); 3404 ret = test_priority_directed(t); 3405 if (ret != 0) { 3406 printf("ERROR - Prioritized Directed test FAILED.\n"); 3407 goto test_fail; 3408 } 3409 printf("*** Running Prioritized Atomic test...\n"); 3410 ret = test_priority_atomic(t); 3411 if (ret != 0) { 3412 printf("ERROR - Prioritized Atomic test FAILED.\n"); 3413 goto test_fail; 3414 } 3415 3416 printf("*** Running Prioritized Ordered test...\n"); 3417 ret = test_priority_ordered(t); 3418 if (ret != 0) { 3419 printf("ERROR - Prioritized Ordered test FAILED.\n"); 3420 goto test_fail; 3421 } 3422 printf("*** Running Prioritized Unordered test...\n"); 3423 ret = test_priority_unordered(t); 3424 if (ret != 0) { 3425 printf("ERROR - Prioritized Unordered test FAILED.\n"); 3426 goto test_fail; 3427 } 3428 printf("*** Running Invalid QID test...\n"); 3429 ret = invalid_qid(t); 3430 if (ret != 0) { 3431 printf("ERROR - Invalid QID test FAILED.\n"); 3432 goto test_fail; 3433 } 3434 printf("*** Running Load Balancing History test...\n"); 3435 ret = load_balancing_history(t); 3436 if (ret != 0) { 3437 printf("ERROR - Load Balancing History test FAILED.\n"); 3438 goto test_fail; 3439 } 3440 printf("*** Running Inflight Count test...\n"); 3441 ret = inflight_counts(t); 3442 if (ret != 0) { 3443 printf("ERROR - Inflight Count test FAILED.\n"); 3444 goto test_fail; 3445 } 3446 printf("*** Running Abuse Inflights test...\n"); 3447 ret = abuse_inflights(t); 3448 if (ret != 0) { 3449 printf("ERROR - Abuse Inflights test FAILED.\n"); 3450 goto test_fail; 3451 } 3452 printf("*** Running XStats test...\n"); 3453 ret = xstats_tests(t); 3454 if (ret != 0) { 3455 printf("ERROR - XStats test FAILED.\n"); 3456 goto test_fail; 3457 } 3458 printf("*** Running XStats ID Reset test...\n"); 3459 ret = xstats_id_reset_tests(t); 3460 if (ret != 0) { 3461 printf("ERROR - XStats ID Reset test FAILED.\n"); 3462 goto test_fail; 3463 } 3464 printf("*** Running XStats Brute Force test...\n"); 3465 ret = xstats_brute_force(t); 3466 if (ret != 0) { 3467 printf("ERROR - XStats Brute Force test FAILED.\n"); 3468 goto test_fail; 3469 } 3470 printf("*** Running XStats ID Abuse test...\n"); 3471 ret = xstats_id_abuse_tests(t); 3472 if (ret != 0) { 3473 printf("ERROR - XStats ID Abuse test FAILED.\n"); 3474 goto test_fail; 3475 } 3476 printf("*** Running QID Priority test...\n"); 3477 ret = qid_priorities(t); 3478 if (ret != 0) { 3479 printf("ERROR - QID Priority test FAILED.\n"); 3480 goto test_fail; 3481 } 3482 printf("*** Running Unlink-in-progress test...\n"); 3483 ret = unlink_in_progress(t); 3484 if (ret != 0) { 3485 printf("ERROR - Unlink in progress test FAILED.\n"); 3486 goto test_fail; 3487 } 3488 printf("*** Running Ordered Reconfigure test...\n"); 3489 ret = ordered_reconfigure(t); 3490 if (ret != 0) { 3491 printf("ERROR - Ordered Reconfigure test FAILED.\n"); 3492 goto test_fail; 3493 } 3494 printf("*** Running Port LB Single Reconfig test...\n"); 3495 ret = port_single_lb_reconfig(t); 3496 if (ret != 0) { 3497 printf("ERROR - Port LB Single Reconfig test FAILED.\n"); 3498 goto test_fail; 3499 } 3500 printf("*** Running Port Reconfig Credits test...\n"); 3501 ret = port_reconfig_credits(t); 3502 if (ret != 0) { 3503 printf("ERROR - Port Reconfig Credits Reset test FAILED.\n"); 3504 goto test_fail; 3505 } 3506 printf("*** Running Head-of-line-blocking test...\n"); 3507 ret = holb(t); 3508 if (ret != 0) { 3509 printf("ERROR - Head-of-line-blocking test FAILED.\n"); 3510 goto test_fail; 3511 } 3512 printf("*** Running Stop Flush test...\n"); 3513 ret = dev_stop_flush(t); 3514 if (ret != 0) { 3515 printf("ERROR - Stop Flush test FAILED.\n"); 3516 goto test_fail; 3517 } 3518 printf("*** Running Ordered & Atomic hist-list completion test...\n"); 3519 ret = ordered_atomic_hist_completion(t); 3520 if (ret != 0) { 3521 printf("ERROR - Ordered & Atomic hist-list test FAILED.\n"); 3522 goto test_fail; 3523 } 3524 if (rte_lcore_count() >= 3) { 3525 printf("*** Running Worker loopback test...\n"); 3526 ret = worker_loopback(t, 0); 3527 if (ret != 0) { 3528 printf("ERROR - Worker loopback test FAILED.\n"); 3529 return ret; 3530 } 3531 3532 printf("*** Running Worker loopback test (implicit release disabled)...\n"); 3533 ret = worker_loopback(t, 1); 3534 if (ret != 0) { 3535 printf("ERROR - Worker loopback test FAILED.\n"); 3536 goto test_fail; 3537 } 3538 } else { 3539 printf("### Not enough cores for worker loopback tests.\n"); 3540 printf("### Need at least 3 cores for the tests.\n"); 3541 } 3542 3543 /* 3544 * Free test instance, leaving mempool initialized, and a pointer to it 3545 * in static eventdev_func_mempool, as it is re-used on re-runs 3546 */ 3547 free(t); 3548 3549 printf("SW Eventdev Selftest Successful.\n"); 3550 return 0; 3551 test_fail: 3552 free(t); 3553 printf("SW Eventdev Selftest Failed.\n"); 3554 return -1; 3555 } 3556