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