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