Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2017 Cavium, Inc.
3 : : */
4 : :
5 : : #include "test_pipeline_common.h"
6 : :
7 : : /* See http://doc.dpdk.org/guides/tools/testeventdev.html for test details */
8 : :
9 : : static __rte_always_inline int
10 : : pipeline_queue_nb_event_queues(struct evt_options *opt)
11 : : {
12 : 0 : uint16_t eth_count = rte_eth_dev_count_avail();
13 : :
14 : 0 : return (eth_count * opt->nb_stages) + eth_count;
15 : : }
16 : :
17 : : typedef int (*pipeline_queue_worker_t)(void *arg);
18 : :
19 : : static __rte_noinline int
20 : 0 : pipeline_queue_worker_single_stage_tx(void *arg)
21 : : {
22 : 0 : PIPELINE_WORKER_SINGLE_STAGE_INIT;
23 : : uint8_t enq = 0, deq = 0;
24 : :
25 : 0 : while (t->done == false) {
26 : 0 : deq = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
27 : :
28 : 0 : if (!deq) {
29 : : rte_pause();
30 : 0 : continue;
31 : : }
32 : :
33 : 0 : if (ev.sched_type == RTE_SCHED_TYPE_ATOMIC) {
34 : : enq = pipeline_event_tx(dev, port, &ev, t);
35 : 0 : ev.op = RTE_EVENT_OP_RELEASE;
36 : 0 : w->processed_pkts++;
37 : : } else {
38 : 0 : ev.queue_id++;
39 : : pipeline_fwd_event(&ev, RTE_SCHED_TYPE_ATOMIC);
40 : : enq = pipeline_event_enqueue(dev, port, &ev, t);
41 : : }
42 : : }
43 : 0 : pipeline_worker_cleanup(dev, port, &ev, enq, deq);
44 : :
45 : 0 : return 0;
46 : : }
47 : :
48 : : static __rte_noinline int
49 : 0 : pipeline_queue_worker_single_stage_fwd(void *arg)
50 : : {
51 : 0 : PIPELINE_WORKER_SINGLE_STAGE_INIT;
52 : 0 : const uint8_t *tx_queue = t->tx_evqueue_id;
53 : : uint8_t enq = 0, deq = 0;
54 : :
55 : 0 : while (t->done == false) {
56 : 0 : deq = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
57 : :
58 : 0 : if (!deq) {
59 : : rte_pause();
60 : 0 : continue;
61 : : }
62 : :
63 : 0 : ev.queue_id = tx_queue[ev.mbuf->port];
64 : : rte_event_eth_tx_adapter_txq_set(ev.mbuf, 0);
65 : : pipeline_fwd_event(&ev, RTE_SCHED_TYPE_ATOMIC);
66 : : enq = pipeline_event_enqueue(dev, port, &ev, t);
67 : 0 : w->processed_pkts++;
68 : : }
69 : 0 : pipeline_worker_cleanup(dev, port, &ev, enq, deq);
70 : :
71 : 0 : return 0;
72 : : }
73 : :
74 : : static __rte_noinline int
75 : 0 : pipeline_queue_worker_single_stage_burst_tx(void *arg)
76 : : {
77 : 0 : PIPELINE_WORKER_SINGLE_STAGE_BURST_INIT;
78 : : uint16_t nb_rx = 0, nb_tx = 0;
79 : :
80 : 0 : while (t->done == false) {
81 : 0 : nb_rx = rte_event_dequeue_burst(dev, port, ev, BURST_SIZE, 0);
82 : :
83 : 0 : if (!nb_rx) {
84 : : rte_pause();
85 : 0 : continue;
86 : : }
87 : :
88 : 0 : for (i = 0; i < nb_rx; i++) {
89 : 0 : rte_prefetch0(ev[i + 1].mbuf);
90 : 0 : if (ev[i].sched_type == RTE_SCHED_TYPE_ATOMIC) {
91 : 0 : pipeline_event_tx(dev, port, &ev[i], t);
92 : 0 : ev[i].op = RTE_EVENT_OP_RELEASE;
93 : 0 : w->processed_pkts++;
94 : : } else {
95 : 0 : ev[i].queue_id++;
96 : : pipeline_fwd_event(&ev[i],
97 : : RTE_SCHED_TYPE_ATOMIC);
98 : : }
99 : : }
100 : : nb_tx = pipeline_event_enqueue_burst(dev, port, ev, nb_rx, t);
101 : : }
102 : 0 : pipeline_worker_cleanup(dev, port, ev, nb_tx, nb_rx);
103 : :
104 : 0 : return 0;
105 : : }
106 : :
107 : : static __rte_noinline int
108 : 0 : pipeline_queue_worker_single_stage_burst_fwd(void *arg)
109 : : {
110 : 0 : PIPELINE_WORKER_SINGLE_STAGE_BURST_INIT;
111 : 0 : const uint8_t *tx_queue = t->tx_evqueue_id;
112 : : uint16_t nb_rx = 0, nb_tx = 0;
113 : :
114 : 0 : while (t->done == false) {
115 : 0 : nb_rx = rte_event_dequeue_burst(dev, port, ev, BURST_SIZE, 0);
116 : :
117 : 0 : if (!nb_rx) {
118 : : rte_pause();
119 : 0 : continue;
120 : : }
121 : :
122 : 0 : for (i = 0; i < nb_rx; i++) {
123 : 0 : rte_prefetch0(ev[i + 1].mbuf);
124 : 0 : ev[i].queue_id = tx_queue[ev[i].mbuf->port];
125 : : rte_event_eth_tx_adapter_txq_set(ev[i].mbuf, 0);
126 : : pipeline_fwd_event(&ev[i], RTE_SCHED_TYPE_ATOMIC);
127 : : }
128 : :
129 : : nb_tx = pipeline_event_enqueue_burst(dev, port, ev, nb_rx, t);
130 : 0 : w->processed_pkts += nb_rx;
131 : : }
132 : 0 : pipeline_worker_cleanup(dev, port, ev, nb_tx, nb_rx);
133 : :
134 : 0 : return 0;
135 : : }
136 : :
137 : : static __rte_noinline int
138 : 0 : pipeline_queue_worker_single_stage_tx_vector(void *arg)
139 : : {
140 : 0 : PIPELINE_WORKER_SINGLE_STAGE_INIT;
141 : : uint8_t enq = 0, deq = 0;
142 : : uint16_t vector_sz;
143 : :
144 : 0 : while (!t->done) {
145 : 0 : deq = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
146 : :
147 : 0 : if (!deq) {
148 : : rte_pause();
149 : 0 : continue;
150 : : }
151 : :
152 : 0 : if (ev.sched_type == RTE_SCHED_TYPE_ATOMIC) {
153 : 0 : vector_sz = ev.vec->nb_elem;
154 : : enq = pipeline_event_tx_vector(dev, port, &ev, t);
155 : 0 : ev.op = RTE_EVENT_OP_RELEASE;
156 : 0 : w->processed_pkts += vector_sz;
157 : : } else {
158 : 0 : ev.queue_id++;
159 : : pipeline_fwd_event_vector(&ev, RTE_SCHED_TYPE_ATOMIC);
160 : : enq = pipeline_event_enqueue(dev, port, &ev, t);
161 : : }
162 : : }
163 : 0 : pipeline_worker_cleanup(dev, port, &ev, enq, deq);
164 : :
165 : 0 : return 0;
166 : : }
167 : :
168 : : static __rte_noinline int
169 : 0 : pipeline_queue_worker_single_stage_fwd_vector(void *arg)
170 : : {
171 : 0 : PIPELINE_WORKER_SINGLE_STAGE_INIT;
172 : 0 : const uint8_t *tx_queue = t->tx_evqueue_id;
173 : : uint8_t enq = 0, deq = 0;
174 : : uint16_t vector_sz;
175 : :
176 : 0 : while (!t->done) {
177 : 0 : deq = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
178 : :
179 : 0 : if (!deq) {
180 : : rte_pause();
181 : 0 : continue;
182 : : }
183 : :
184 : 0 : ev.queue_id = tx_queue[ev.vec->port];
185 : 0 : ev.vec->queue = 0;
186 : 0 : vector_sz = ev.vec->nb_elem;
187 : : pipeline_fwd_event_vector(&ev, RTE_SCHED_TYPE_ATOMIC);
188 : : enq = pipeline_event_enqueue(dev, port, &ev, t);
189 : 0 : w->processed_pkts += vector_sz;
190 : : }
191 : 0 : pipeline_worker_cleanup(dev, port, &ev, enq, deq);
192 : :
193 : 0 : return 0;
194 : : }
195 : :
196 : : static __rte_noinline int
197 : 0 : pipeline_queue_worker_single_stage_burst_tx_vector(void *arg)
198 : : {
199 : 0 : PIPELINE_WORKER_SINGLE_STAGE_BURST_INIT;
200 : : uint16_t nb_rx = 0, nb_tx = 0;
201 : : uint16_t vector_sz;
202 : :
203 : 0 : while (!t->done) {
204 : 0 : nb_rx = rte_event_dequeue_burst(dev, port, ev, BURST_SIZE, 0);
205 : :
206 : 0 : if (!nb_rx) {
207 : : rte_pause();
208 : 0 : continue;
209 : : }
210 : :
211 : 0 : for (i = 0; i < nb_rx; i++) {
212 : 0 : if (ev[i].sched_type == RTE_SCHED_TYPE_ATOMIC) {
213 : 0 : vector_sz = ev[i].vec->nb_elem;
214 : 0 : pipeline_event_tx_vector(dev, port, &ev[i], t);
215 : 0 : ev[i].op = RTE_EVENT_OP_RELEASE;
216 : 0 : w->processed_pkts += vector_sz;
217 : : } else {
218 : 0 : ev[i].queue_id++;
219 : : pipeline_fwd_event_vector(
220 : : &ev[i], RTE_SCHED_TYPE_ATOMIC);
221 : : }
222 : : }
223 : :
224 : : nb_tx = pipeline_event_enqueue_burst(dev, port, ev, nb_rx, t);
225 : : }
226 : 0 : pipeline_worker_cleanup(dev, port, ev, nb_tx, nb_rx);
227 : :
228 : 0 : return 0;
229 : : }
230 : :
231 : : static __rte_noinline int
232 : 0 : pipeline_queue_worker_single_stage_burst_fwd_vector(void *arg)
233 : : {
234 : 0 : PIPELINE_WORKER_SINGLE_STAGE_BURST_INIT;
235 : 0 : const uint8_t *tx_queue = t->tx_evqueue_id;
236 : : uint16_t nb_rx = 0, nb_tx = 0;
237 : : uint16_t vector_sz;
238 : :
239 : 0 : while (!t->done) {
240 : 0 : nb_rx = rte_event_dequeue_burst(dev, port, ev, BURST_SIZE, 0);
241 : :
242 : 0 : if (!nb_rx) {
243 : : rte_pause();
244 : 0 : continue;
245 : : }
246 : :
247 : : vector_sz = 0;
248 : 0 : for (i = 0; i < nb_rx; i++) {
249 : 0 : ev[i].queue_id = tx_queue[ev[i].vec->port];
250 : 0 : ev[i].vec->queue = 0;
251 : 0 : vector_sz += ev[i].vec->nb_elem;
252 : : pipeline_fwd_event_vector(&ev[i],
253 : : RTE_SCHED_TYPE_ATOMIC);
254 : : }
255 : :
256 : : nb_tx = pipeline_event_enqueue_burst(dev, port, ev, nb_rx, t);
257 : 0 : w->processed_pkts += vector_sz;
258 : : }
259 : 0 : pipeline_worker_cleanup(dev, port, ev, nb_tx, nb_rx);
260 : :
261 : 0 : return 0;
262 : : }
263 : :
264 : : static __rte_noinline int
265 : 0 : pipeline_queue_worker_multi_stage_tx(void *arg)
266 : : {
267 : 0 : PIPELINE_WORKER_MULTI_STAGE_INIT;
268 : 0 : const uint8_t *tx_queue = t->tx_evqueue_id;
269 : : uint8_t enq = 0, deq = 0;
270 : :
271 : 0 : while (t->done == false) {
272 : 0 : deq = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
273 : :
274 : 0 : if (!deq) {
275 : : rte_pause();
276 : 0 : continue;
277 : : }
278 : :
279 : 0 : cq_id = ev.queue_id % nb_stages;
280 : :
281 : 0 : if (ev.queue_id == tx_queue[ev.mbuf->port]) {
282 : : enq = pipeline_event_tx(dev, port, &ev, t);
283 : 0 : ev.op = RTE_EVENT_OP_RELEASE;
284 : 0 : w->processed_pkts++;
285 : 0 : continue;
286 : : }
287 : :
288 : 0 : ev.queue_id++;
289 : 0 : pipeline_fwd_event(&ev, cq_id != last_queue ?
290 : 0 : sched_type_list[cq_id] :
291 : : RTE_SCHED_TYPE_ATOMIC);
292 : : enq = pipeline_event_enqueue(dev, port, &ev, t);
293 : : }
294 : 0 : pipeline_worker_cleanup(dev, port, &ev, enq, deq);
295 : :
296 : 0 : return 0;
297 : : }
298 : :
299 : : static __rte_noinline int
300 : 0 : pipeline_queue_worker_multi_stage_fwd(void *arg)
301 : : {
302 : 0 : PIPELINE_WORKER_MULTI_STAGE_INIT;
303 : 0 : const uint8_t *tx_queue = t->tx_evqueue_id;
304 : : uint8_t enq = 0, deq = 0;
305 : :
306 : 0 : while (t->done == false) {
307 : 0 : deq = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
308 : :
309 : 0 : if (!deq) {
310 : : rte_pause();
311 : 0 : continue;
312 : : }
313 : :
314 : 0 : cq_id = ev.queue_id % nb_stages;
315 : :
316 : 0 : if (cq_id == last_queue) {
317 : 0 : ev.queue_id = tx_queue[ev.mbuf->port];
318 : : rte_event_eth_tx_adapter_txq_set(ev.mbuf, 0);
319 : : pipeline_fwd_event(&ev, RTE_SCHED_TYPE_ATOMIC);
320 : : enq = pipeline_event_enqueue(dev, port, &ev, t);
321 : 0 : w->processed_pkts++;
322 : : } else {
323 : 0 : ev.queue_id++;
324 : 0 : pipeline_fwd_event(&ev, sched_type_list[cq_id]);
325 : : enq = pipeline_event_enqueue(dev, port, &ev, t);
326 : : }
327 : : }
328 : 0 : pipeline_worker_cleanup(dev, port, &ev, enq, deq);
329 : :
330 : 0 : return 0;
331 : : }
332 : :
333 : : static __rte_noinline int
334 : 0 : pipeline_queue_worker_multi_stage_burst_tx(void *arg)
335 : : {
336 : 0 : PIPELINE_WORKER_MULTI_STAGE_BURST_INIT;
337 : 0 : const uint8_t *tx_queue = t->tx_evqueue_id;
338 : : uint16_t nb_rx = 0, nb_tx = 0;
339 : :
340 : 0 : while (t->done == false) {
341 : 0 : nb_rx = rte_event_dequeue_burst(dev, port, ev, BURST_SIZE, 0);
342 : :
343 : 0 : if (!nb_rx) {
344 : : rte_pause();
345 : 0 : continue;
346 : : }
347 : :
348 : 0 : for (i = 0; i < nb_rx; i++) {
349 : 0 : rte_prefetch0(ev[i + 1].mbuf);
350 : 0 : cq_id = ev[i].queue_id % nb_stages;
351 : :
352 : 0 : if (ev[i].queue_id == tx_queue[ev[i].mbuf->port]) {
353 : 0 : pipeline_event_tx(dev, port, &ev[i], t);
354 : 0 : ev[i].op = RTE_EVENT_OP_RELEASE;
355 : 0 : w->processed_pkts++;
356 : 0 : continue;
357 : : }
358 : :
359 : 0 : ev[i].queue_id++;
360 : 0 : pipeline_fwd_event(&ev[i], cq_id != last_queue ?
361 : 0 : sched_type_list[cq_id] :
362 : : RTE_SCHED_TYPE_ATOMIC);
363 : : }
364 : : nb_tx = pipeline_event_enqueue_burst(dev, port, ev, nb_rx, t);
365 : : }
366 : 0 : pipeline_worker_cleanup(dev, port, ev, nb_tx, nb_rx);
367 : :
368 : 0 : return 0;
369 : : }
370 : :
371 : : static __rte_noinline int
372 : 0 : pipeline_queue_worker_multi_stage_burst_fwd(void *arg)
373 : : {
374 : 0 : PIPELINE_WORKER_MULTI_STAGE_BURST_INIT;
375 : 0 : const uint8_t *tx_queue = t->tx_evqueue_id;
376 : : uint16_t nb_rx = 0, nb_tx = 0;
377 : :
378 : 0 : while (t->done == false) {
379 : : uint16_t processed_pkts = 0;
380 : 0 : nb_rx = rte_event_dequeue_burst(dev, port, ev, BURST_SIZE, 0);
381 : :
382 : 0 : if (!nb_rx) {
383 : : rte_pause();
384 : 0 : continue;
385 : : }
386 : :
387 : 0 : for (i = 0; i < nb_rx; i++) {
388 : 0 : rte_prefetch0(ev[i + 1].mbuf);
389 : 0 : cq_id = ev[i].queue_id % nb_stages;
390 : :
391 : 0 : if (cq_id == last_queue) {
392 : 0 : ev[i].queue_id = tx_queue[ev[i].mbuf->port];
393 : : rte_event_eth_tx_adapter_txq_set(ev[i].mbuf, 0);
394 : : pipeline_fwd_event(&ev[i],
395 : : RTE_SCHED_TYPE_ATOMIC);
396 : 0 : processed_pkts++;
397 : : } else {
398 : 0 : ev[i].queue_id++;
399 : : pipeline_fwd_event(&ev[i],
400 : 0 : sched_type_list[cq_id]);
401 : : }
402 : : }
403 : :
404 : : nb_tx = pipeline_event_enqueue_burst(dev, port, ev, nb_rx, t);
405 : 0 : w->processed_pkts += processed_pkts;
406 : : }
407 : 0 : pipeline_worker_cleanup(dev, port, ev, nb_tx, nb_rx);
408 : :
409 : 0 : return 0;
410 : : }
411 : :
412 : : static __rte_noinline int
413 : 0 : pipeline_queue_worker_multi_stage_tx_vector(void *arg)
414 : : {
415 : 0 : PIPELINE_WORKER_MULTI_STAGE_INIT;
416 : 0 : const uint8_t *tx_queue = t->tx_evqueue_id;
417 : : uint8_t enq = 0, deq = 0;
418 : : uint16_t vector_sz;
419 : :
420 : 0 : while (!t->done) {
421 : 0 : deq = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
422 : :
423 : 0 : if (!deq) {
424 : : rte_pause();
425 : 0 : continue;
426 : : }
427 : :
428 : 0 : cq_id = ev.queue_id % nb_stages;
429 : :
430 : 0 : if (ev.queue_id == tx_queue[ev.vec->port]) {
431 : 0 : vector_sz = ev.vec->nb_elem;
432 : : enq = pipeline_event_tx_vector(dev, port, &ev, t);
433 : 0 : w->processed_pkts += vector_sz;
434 : 0 : ev.op = RTE_EVENT_OP_RELEASE;
435 : 0 : continue;
436 : : }
437 : :
438 : 0 : ev.queue_id++;
439 : 0 : pipeline_fwd_event_vector(&ev, cq_id != last_queue
440 : 0 : ? sched_type_list[cq_id]
441 : : : RTE_SCHED_TYPE_ATOMIC);
442 : : enq = pipeline_event_enqueue(dev, port, &ev, t);
443 : : }
444 : 0 : pipeline_worker_cleanup(dev, port, &ev, enq, deq);
445 : :
446 : 0 : return 0;
447 : : }
448 : :
449 : : static __rte_noinline int
450 : 0 : pipeline_queue_worker_multi_stage_fwd_vector(void *arg)
451 : : {
452 : 0 : PIPELINE_WORKER_MULTI_STAGE_INIT;
453 : 0 : const uint8_t *tx_queue = t->tx_evqueue_id;
454 : : uint8_t enq = 0, deq = 0;
455 : : uint16_t vector_sz;
456 : :
457 : 0 : while (!t->done) {
458 : 0 : deq = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
459 : :
460 : 0 : if (!deq) {
461 : : rte_pause();
462 : 0 : continue;
463 : : }
464 : :
465 : 0 : cq_id = ev.queue_id % nb_stages;
466 : :
467 : 0 : if (cq_id == last_queue) {
468 : 0 : vector_sz = ev.vec->nb_elem;
469 : 0 : ev.queue_id = tx_queue[ev.vec->port];
470 : : pipeline_fwd_event_vector(&ev, RTE_SCHED_TYPE_ATOMIC);
471 : 0 : w->processed_pkts += vector_sz;
472 : : } else {
473 : 0 : ev.queue_id++;
474 : 0 : pipeline_fwd_event_vector(&ev, sched_type_list[cq_id]);
475 : : }
476 : :
477 : : enq = pipeline_event_enqueue(dev, port, &ev, t);
478 : : }
479 : 0 : pipeline_worker_cleanup(dev, port, &ev, enq, deq);
480 : :
481 : 0 : return 0;
482 : : }
483 : :
484 : : static __rte_noinline int
485 : 0 : pipeline_queue_worker_multi_stage_burst_tx_vector(void *arg)
486 : : {
487 : 0 : PIPELINE_WORKER_MULTI_STAGE_BURST_INIT;
488 : 0 : const uint8_t *tx_queue = t->tx_evqueue_id;
489 : : uint16_t nb_rx = 0, nb_tx = 0;
490 : : uint16_t vector_sz;
491 : :
492 : 0 : while (!t->done) {
493 : 0 : nb_rx = rte_event_dequeue_burst(dev, port, ev, BURST_SIZE, 0);
494 : :
495 : 0 : if (!nb_rx) {
496 : : rte_pause();
497 : 0 : continue;
498 : : }
499 : :
500 : 0 : for (i = 0; i < nb_rx; i++) {
501 : 0 : cq_id = ev[i].queue_id % nb_stages;
502 : :
503 : 0 : if (ev[i].queue_id == tx_queue[ev[i].vec->port]) {
504 : 0 : vector_sz = ev[i].vec->nb_elem;
505 : 0 : pipeline_event_tx_vector(dev, port, &ev[i], t);
506 : 0 : ev[i].op = RTE_EVENT_OP_RELEASE;
507 : 0 : w->processed_pkts += vector_sz;
508 : 0 : continue;
509 : : }
510 : :
511 : 0 : ev[i].queue_id++;
512 : 0 : pipeline_fwd_event_vector(
513 : : &ev[i], cq_id != last_queue
514 : 0 : ? sched_type_list[cq_id]
515 : : : RTE_SCHED_TYPE_ATOMIC);
516 : : }
517 : :
518 : : nb_tx = pipeline_event_enqueue_burst(dev, port, ev, nb_rx, t);
519 : : }
520 : 0 : pipeline_worker_cleanup(dev, port, ev, nb_tx, nb_rx);
521 : :
522 : 0 : return 0;
523 : : }
524 : :
525 : : static __rte_noinline int
526 : 0 : pipeline_queue_worker_multi_stage_burst_fwd_vector(void *arg)
527 : : {
528 : 0 : PIPELINE_WORKER_MULTI_STAGE_BURST_INIT;
529 : 0 : const uint8_t *tx_queue = t->tx_evqueue_id;
530 : : uint16_t nb_rx = 0, nb_tx = 0;
531 : : uint16_t vector_sz;
532 : :
533 : 0 : while (!t->done) {
534 : 0 : nb_rx = rte_event_dequeue_burst(dev, port, ev, BURST_SIZE, 0);
535 : :
536 : 0 : if (!nb_rx) {
537 : : rte_pause();
538 : 0 : continue;
539 : : }
540 : :
541 : 0 : for (i = 0; i < nb_rx; i++) {
542 : 0 : cq_id = ev[i].queue_id % nb_stages;
543 : :
544 : 0 : if (cq_id == last_queue) {
545 : 0 : ev[i].queue_id = tx_queue[ev[i].vec->port];
546 : 0 : vector_sz = ev[i].vec->nb_elem;
547 : : pipeline_fwd_event_vector(
548 : : &ev[i], RTE_SCHED_TYPE_ATOMIC);
549 : 0 : w->processed_pkts += vector_sz;
550 : : } else {
551 : 0 : ev[i].queue_id++;
552 : : pipeline_fwd_event_vector(
553 : 0 : &ev[i], sched_type_list[cq_id]);
554 : : }
555 : : }
556 : :
557 : : nb_tx = pipeline_event_enqueue_burst(dev, port, ev, nb_rx, t);
558 : : }
559 : 0 : pipeline_worker_cleanup(dev, port, ev, nb_tx, nb_rx);
560 : :
561 : 0 : return 0;
562 : : }
563 : :
564 : : static int
565 : 0 : worker_wrapper(void *arg)
566 : : {
567 : : struct worker_data *w = arg;
568 : 0 : struct evt_options *opt = w->t->opt;
569 : 0 : const bool burst = evt_has_burst_mode(w->dev_id);
570 : 0 : const bool internal_port = w->t->internal_port;
571 : 0 : const uint8_t nb_stages = opt->nb_stages;
572 : : /*vector/burst/internal_port*/
573 : : const pipeline_queue_worker_t
574 : 0 : pipeline_queue_worker_single_stage[2][2][2] = {
575 : : [0][0][0] = pipeline_queue_worker_single_stage_fwd,
576 : : [0][0][1] = pipeline_queue_worker_single_stage_tx,
577 : : [0][1][0] = pipeline_queue_worker_single_stage_burst_fwd,
578 : : [0][1][1] = pipeline_queue_worker_single_stage_burst_tx,
579 : : [1][0][0] = pipeline_queue_worker_single_stage_fwd_vector,
580 : : [1][0][1] = pipeline_queue_worker_single_stage_tx_vector,
581 : : [1][1][0] = pipeline_queue_worker_single_stage_burst_fwd_vector,
582 : : [1][1][1] = pipeline_queue_worker_single_stage_burst_tx_vector,
583 : : };
584 : : const pipeline_queue_worker_t
585 : 0 : pipeline_queue_worker_multi_stage[2][2][2] = {
586 : : [0][0][0] = pipeline_queue_worker_multi_stage_fwd,
587 : : [0][0][1] = pipeline_queue_worker_multi_stage_tx,
588 : : [0][1][0] = pipeline_queue_worker_multi_stage_burst_fwd,
589 : : [0][1][1] = pipeline_queue_worker_multi_stage_burst_tx,
590 : : [1][0][0] = pipeline_queue_worker_multi_stage_fwd_vector,
591 : : [1][0][1] = pipeline_queue_worker_multi_stage_tx_vector,
592 : : [1][1][0] = pipeline_queue_worker_multi_stage_burst_fwd_vector,
593 : : [1][1][1] = pipeline_queue_worker_multi_stage_burst_tx_vector,
594 : : };
595 : :
596 : 0 : if (nb_stages == 1)
597 : 0 : return (pipeline_queue_worker_single_stage[opt->ena_vector]
598 : : [burst]
599 : 0 : [internal_port])(arg);
600 : : else
601 : 0 : return (pipeline_queue_worker_multi_stage[opt->ena_vector]
602 : : [burst]
603 : 0 : [internal_port])(arg);
604 : :
605 : : rte_panic("invalid worker\n");
606 : : }
607 : :
608 : : static int
609 : 0 : pipeline_queue_launch_lcores(struct evt_test *test, struct evt_options *opt)
610 : : {
611 : 0 : return pipeline_launch_lcores(test, opt, worker_wrapper);
612 : : }
613 : :
614 : : static int
615 : 0 : pipeline_queue_eventdev_setup(struct evt_test *test, struct evt_options *opt)
616 : : {
617 : : int ret;
618 : : int nb_ports;
619 : : int nb_queues;
620 : 0 : int nb_stages = opt->nb_stages;
621 : : uint8_t queue;
622 : 0 : uint8_t tx_evport_id = 0;
623 : : uint8_t tx_evqueue_id[RTE_MAX_ETHPORTS];
624 : : uint8_t queue_arr[RTE_EVENT_MAX_QUEUES_PER_DEV];
625 : : uint8_t nb_worker_queues = 0;
626 : : uint16_t prod = 0;
627 : : struct rte_event_dev_info info;
628 : : struct test_pipeline *t = evt_test_priv(test);
629 : :
630 : 0 : nb_ports = evt_nr_active_lcores(opt->wlcores);
631 : 0 : nb_queues = rte_eth_dev_count_avail() * (nb_stages);
632 : :
633 : : /* One queue for Tx adapter per port */
634 : 0 : nb_queues += rte_eth_dev_count_avail();
635 : :
636 : : memset(tx_evqueue_id, 0, sizeof(uint8_t) * RTE_MAX_ETHPORTS);
637 : : memset(queue_arr, 0, sizeof(uint8_t) * RTE_EVENT_MAX_QUEUES_PER_DEV);
638 : :
639 : 0 : rte_event_dev_info_get(opt->dev_id, &info);
640 : 0 : ret = evt_configure_eventdev(opt, nb_queues, nb_ports);
641 : 0 : if (ret) {
642 : 0 : evt_err("failed to configure eventdev %d", opt->dev_id);
643 : 0 : return ret;
644 : : }
645 : :
646 : 0 : struct rte_event_queue_conf q_conf = {
647 : : .priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
648 : 0 : .nb_atomic_flows = opt->nb_flows,
649 : : .nb_atomic_order_sequences = opt->nb_flows,
650 : : };
651 : : /* queue configurations */
652 : 0 : for (queue = 0; queue < nb_queues; queue++) {
653 : : uint8_t slot;
654 : :
655 : 0 : q_conf.event_queue_cfg = 0;
656 : 0 : slot = queue % (nb_stages + 1);
657 : 0 : if (slot == nb_stages) {
658 : 0 : q_conf.schedule_type = RTE_SCHED_TYPE_ATOMIC;
659 : 0 : if (!t->internal_port) {
660 : 0 : q_conf.event_queue_cfg =
661 : : RTE_EVENT_QUEUE_CFG_SINGLE_LINK;
662 : : }
663 : 0 : tx_evqueue_id[prod++] = queue;
664 : : } else {
665 : 0 : q_conf.schedule_type = opt->sched_type_list[slot];
666 : 0 : queue_arr[nb_worker_queues] = queue;
667 : 0 : nb_worker_queues++;
668 : : }
669 : :
670 : 0 : ret = rte_event_queue_setup(opt->dev_id, queue, &q_conf);
671 : 0 : if (ret) {
672 : 0 : evt_err("failed to setup queue=%d", queue);
673 : 0 : return ret;
674 : : }
675 : : }
676 : :
677 : 0 : if (opt->wkr_deq_dep > info.max_event_port_dequeue_depth)
678 : 0 : opt->wkr_deq_dep = info.max_event_port_dequeue_depth;
679 : :
680 : : /* port configuration */
681 : 0 : const struct rte_event_port_conf p_conf = {
682 : 0 : .dequeue_depth = opt->wkr_deq_dep,
683 : : .enqueue_depth = info.max_event_port_dequeue_depth,
684 : 0 : .new_event_threshold = info.max_num_events,
685 : : };
686 : :
687 : 0 : if (!t->internal_port) {
688 : 0 : ret = pipeline_event_port_setup(test, opt, queue_arr,
689 : : nb_worker_queues, p_conf);
690 : 0 : if (ret)
691 : : return ret;
692 : : } else
693 : 0 : ret = pipeline_event_port_setup(test, opt, NULL, nb_queues,
694 : : p_conf);
695 : :
696 : 0 : if (ret)
697 : : return ret;
698 : : /*
699 : : * The pipelines are setup in the following manner:
700 : : *
701 : : * eth_dev_count = 2, nb_stages = 2.
702 : : *
703 : : * queues = 6
704 : : * stride = 3
705 : : *
706 : : * event queue pipelines:
707 : : * eth0 -> q0 -> q1 -> (q2->tx)
708 : : * eth1 -> q3 -> q4 -> (q5->tx)
709 : : *
710 : : * q2, q5 configured as ATOMIC | SINGLE_LINK
711 : : *
712 : : */
713 : 0 : ret = pipeline_event_rx_adapter_setup(opt, nb_stages + 1, p_conf);
714 : 0 : if (ret)
715 : : return ret;
716 : :
717 : 0 : ret = pipeline_event_tx_adapter_setup(opt, p_conf);
718 : 0 : if (ret)
719 : : return ret;
720 : :
721 : 0 : if (!evt_has_distributed_sched(opt->dev_id)) {
722 : : uint32_t service_id;
723 : 0 : rte_event_dev_service_id_get(opt->dev_id, &service_id);
724 : 0 : ret = evt_service_setup(service_id);
725 : 0 : if (ret) {
726 : 0 : evt_err("No service lcore found to run event dev.");
727 : 0 : return ret;
728 : : }
729 : : }
730 : :
731 : : /* Connect the tx_evqueue_id to the Tx adapter port */
732 : 0 : if (!t->internal_port) {
733 : 0 : RTE_ETH_FOREACH_DEV(prod) {
734 : 0 : ret = rte_event_eth_tx_adapter_event_port_get(prod,
735 : : &tx_evport_id);
736 : 0 : if (ret) {
737 : 0 : evt_err("Unable to get Tx adptr[%d] evprt[%d]",
738 : : prod, tx_evport_id);
739 : 0 : return ret;
740 : : }
741 : :
742 : 0 : if (rte_event_port_link(opt->dev_id, tx_evport_id,
743 : 0 : &tx_evqueue_id[prod],
744 : : NULL, 1) != 1) {
745 : 0 : evt_err("Unable to link Tx adptr[%d] evprt[%d]",
746 : : prod, tx_evport_id);
747 : 0 : return ret;
748 : : }
749 : : }
750 : : }
751 : :
752 : 0 : ret = rte_event_dev_start(opt->dev_id);
753 : 0 : if (ret) {
754 : 0 : evt_err("failed to start eventdev %d", opt->dev_id);
755 : 0 : return ret;
756 : : }
757 : :
758 : :
759 : 0 : RTE_ETH_FOREACH_DEV(prod) {
760 : 0 : ret = rte_eth_dev_start(prod);
761 : 0 : if (ret) {
762 : 0 : evt_err("Ethernet dev [%d] failed to start."
763 : : " Using synthetic producer", prod);
764 : 0 : return ret;
765 : : }
766 : :
767 : : }
768 : :
769 : 0 : RTE_ETH_FOREACH_DEV(prod) {
770 : 0 : ret = rte_event_eth_rx_adapter_start(prod);
771 : 0 : if (ret) {
772 : 0 : evt_err("Rx adapter[%d] start failed", prod);
773 : 0 : return ret;
774 : : }
775 : :
776 : 0 : ret = rte_event_eth_tx_adapter_start(prod);
777 : 0 : if (ret) {
778 : 0 : evt_err("Tx adapter[%d] start failed", prod);
779 : 0 : return ret;
780 : : }
781 : : }
782 : :
783 : 0 : memcpy(t->tx_evqueue_id, tx_evqueue_id, sizeof(uint8_t) *
784 : : RTE_MAX_ETHPORTS);
785 : :
786 : 0 : return 0;
787 : : }
788 : :
789 : : static void
790 : 0 : pipeline_queue_opt_dump(struct evt_options *opt)
791 : : {
792 : 0 : pipeline_opt_dump(opt, pipeline_queue_nb_event_queues(opt));
793 : 0 : }
794 : :
795 : : static int
796 : 0 : pipeline_queue_opt_check(struct evt_options *opt)
797 : : {
798 : 0 : return pipeline_opt_check(opt, pipeline_queue_nb_event_queues(opt));
799 : : }
800 : :
801 : : static bool
802 : 0 : pipeline_queue_capability_check(struct evt_options *opt)
803 : : {
804 : : struct rte_event_dev_info dev_info;
805 : :
806 : 0 : rte_event_dev_info_get(opt->dev_id, &dev_info);
807 : 0 : if (dev_info.max_event_queues < pipeline_queue_nb_event_queues(opt) ||
808 : 0 : dev_info.max_event_ports <
809 : 0 : evt_nr_active_lcores(opt->wlcores)) {
810 : 0 : evt_err("not enough eventdev queues=%d/%d or ports=%d/%d",
811 : : pipeline_queue_nb_event_queues(opt),
812 : : dev_info.max_event_queues,
813 : : evt_nr_active_lcores(opt->wlcores),
814 : : dev_info.max_event_ports);
815 : : }
816 : :
817 : 0 : return true;
818 : : }
819 : :
820 : : static const struct evt_test_ops pipeline_queue = {
821 : : .cap_check = pipeline_queue_capability_check,
822 : : .opt_check = pipeline_queue_opt_check,
823 : : .opt_dump = pipeline_queue_opt_dump,
824 : : .test_setup = pipeline_test_setup,
825 : : .mempool_setup = pipeline_mempool_setup,
826 : : .ethdev_setup = pipeline_ethdev_setup,
827 : : .eventdev_setup = pipeline_queue_eventdev_setup,
828 : : .launch_lcores = pipeline_queue_launch_lcores,
829 : : .ethdev_rx_stop = pipeline_ethdev_rx_stop,
830 : : .eventdev_destroy = pipeline_eventdev_destroy,
831 : : .mempool_destroy = pipeline_mempool_destroy,
832 : : .ethdev_destroy = pipeline_ethdev_destroy,
833 : : .test_result = pipeline_test_result,
834 : : .test_destroy = pipeline_test_destroy,
835 : : };
836 : :
837 : 0 : EVT_TEST_REGISTER(pipeline_queue);
|