Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : : #include <string.h>
5 : : #include <stdint.h>
6 : :
7 : : #include <rte_mbuf.h>
8 : : #include <rte_ring.h>
9 : : #include <rte_malloc.h>
10 : :
11 : : #include "rte_port_ring.h"
12 : :
13 : : #include "port_log.h"
14 : :
15 : : /*
16 : : * Port RING Reader
17 : : */
18 : : #ifdef RTE_PORT_STATS_COLLECT
19 : :
20 : : #define RTE_PORT_RING_READER_STATS_PKTS_IN_ADD(port, val) \
21 : : port->stats.n_pkts_in += val
22 : : #define RTE_PORT_RING_READER_STATS_PKTS_DROP_ADD(port, val) \
23 : : port->stats.n_pkts_drop += val
24 : :
25 : : #else
26 : :
27 : : #define RTE_PORT_RING_READER_STATS_PKTS_IN_ADD(port, val)
28 : : #define RTE_PORT_RING_READER_STATS_PKTS_DROP_ADD(port, val)
29 : :
30 : : #endif
31 : :
32 : : struct rte_port_ring_reader {
33 : : struct rte_port_in_stats stats;
34 : :
35 : : struct rte_ring *ring;
36 : : };
37 : :
38 : : static void *
39 : 49 : rte_port_ring_reader_create_internal(void *params, int socket_id,
40 : : uint32_t is_multi)
41 : : {
42 : : struct rte_port_ring_reader_params *conf =
43 : : params;
44 : : struct rte_port_ring_reader *port;
45 : :
46 : : /* Check input parameters */
47 [ + + ]: 49 : if ((conf == NULL) ||
48 [ + - + - ]: 48 : (conf->ring == NULL) ||
49 [ + - - + ]: 48 : (rte_ring_is_cons_single(conf->ring) && is_multi) ||
50 [ # # ]: 0 : (!rte_ring_is_cons_single(conf->ring) && !is_multi)) {
51 : 1 : PORT_LOG(ERR, "%s: Invalid Parameters", __func__);
52 : 1 : return NULL;
53 : : }
54 : :
55 : : /* Memory allocation */
56 : 48 : port = rte_zmalloc_socket("PORT", sizeof(*port),
57 : : RTE_CACHE_LINE_SIZE, socket_id);
58 [ - + ]: 48 : if (port == NULL) {
59 : 0 : PORT_LOG(ERR, "%s: Failed to allocate port", __func__);
60 : 0 : return NULL;
61 : : }
62 : :
63 : : /* Initialization */
64 : 48 : port->ring = conf->ring;
65 : :
66 : 48 : return port;
67 : : }
68 : :
69 : : static void *
70 : 49 : rte_port_ring_reader_create(void *params, int socket_id)
71 : : {
72 : 49 : return rte_port_ring_reader_create_internal(params, socket_id, 0);
73 : : }
74 : :
75 : : static void *
76 : 0 : rte_port_ring_multi_reader_create(void *params, int socket_id)
77 : : {
78 : 0 : return rte_port_ring_reader_create_internal(params, socket_id, 1);
79 : : }
80 : :
81 : : static int
82 : 86 : rte_port_ring_reader_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts)
83 : : {
84 : : struct rte_port_ring_reader *p = port;
85 : : uint32_t nb_rx;
86 : :
87 : 86 : nb_rx = rte_ring_sc_dequeue_burst(p->ring, (void **) pkts,
88 : : n_pkts, NULL);
89 : : RTE_PORT_RING_READER_STATS_PKTS_IN_ADD(p, nb_rx);
90 : :
91 : 86 : return nb_rx;
92 : : }
93 : :
94 : : static int
95 : 0 : rte_port_ring_multi_reader_rx(void *port, struct rte_mbuf **pkts,
96 : : uint32_t n_pkts)
97 : : {
98 : : struct rte_port_ring_reader *p = port;
99 : : uint32_t nb_rx;
100 : :
101 : 0 : nb_rx = rte_ring_mc_dequeue_burst(p->ring, (void **) pkts,
102 : : n_pkts, NULL);
103 : : RTE_PORT_RING_READER_STATS_PKTS_IN_ADD(p, nb_rx);
104 : :
105 : 0 : return nb_rx;
106 : : }
107 : :
108 : : static int
109 : 48 : rte_port_ring_reader_free(void *port)
110 : : {
111 [ + + ]: 48 : if (port == NULL) {
112 : 1 : PORT_LOG(ERR, "%s: port is NULL", __func__);
113 : 1 : return -EINVAL;
114 : : }
115 : :
116 : 47 : rte_free(port);
117 : :
118 : 47 : return 0;
119 : : }
120 : :
121 : : static int
122 : 0 : rte_port_ring_reader_stats_read(void *port,
123 : : struct rte_port_in_stats *stats, int clear)
124 : : {
125 : : struct rte_port_ring_reader *p =
126 : : port;
127 : :
128 [ # # ]: 0 : if (stats != NULL)
129 : 0 : memcpy(stats, &p->stats, sizeof(p->stats));
130 : :
131 [ # # ]: 0 : if (clear)
132 : 0 : memset(&p->stats, 0, sizeof(p->stats));
133 : :
134 : 0 : return 0;
135 : : }
136 : :
137 : : /*
138 : : * Port RING Writer
139 : : */
140 : : #ifdef RTE_PORT_STATS_COLLECT
141 : :
142 : : #define RTE_PORT_RING_WRITER_STATS_PKTS_IN_ADD(port, val) \
143 : : port->stats.n_pkts_in += val
144 : : #define RTE_PORT_RING_WRITER_STATS_PKTS_DROP_ADD(port, val) \
145 : : port->stats.n_pkts_drop += val
146 : :
147 : : #else
148 : :
149 : : #define RTE_PORT_RING_WRITER_STATS_PKTS_IN_ADD(port, val)
150 : : #define RTE_PORT_RING_WRITER_STATS_PKTS_DROP_ADD(port, val)
151 : :
152 : : #endif
153 : :
154 : : struct rte_port_ring_writer {
155 : : struct rte_port_out_stats stats;
156 : :
157 : : struct rte_mbuf *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX];
158 : : struct rte_ring *ring;
159 : : uint32_t tx_burst_sz;
160 : : uint32_t tx_buf_count;
161 : : uint64_t bsz_mask;
162 : : uint32_t is_multi;
163 : : };
164 : :
165 : : static void *
166 : 47 : rte_port_ring_writer_create_internal(void *params, int socket_id,
167 : : uint32_t is_multi)
168 : : {
169 : : struct rte_port_ring_writer_params *conf =
170 : : params;
171 : : struct rte_port_ring_writer *port;
172 : :
173 : : /* Check input parameters */
174 [ + + ]: 47 : if ((conf == NULL) ||
175 [ + + + - ]: 46 : (conf->ring == NULL) ||
176 [ + - - + ]: 45 : (rte_ring_is_prod_single(conf->ring) && is_multi) ||
177 [ # # ]: 0 : (!rte_ring_is_prod_single(conf->ring) && !is_multi) ||
178 [ + + ]: 45 : (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX)) {
179 : 3 : PORT_LOG(ERR, "%s: Invalid Parameters", __func__);
180 : 3 : return NULL;
181 : : }
182 : :
183 : : /* Memory allocation */
184 : 44 : port = rte_zmalloc_socket("PORT", sizeof(*port),
185 : : RTE_CACHE_LINE_SIZE, socket_id);
186 [ - + ]: 44 : if (port == NULL) {
187 : 0 : PORT_LOG(ERR, "%s: Failed to allocate port", __func__);
188 : 0 : return NULL;
189 : : }
190 : :
191 : : /* Initialization */
192 : 44 : port->ring = conf->ring;
193 : 44 : port->tx_burst_sz = conf->tx_burst_sz;
194 : 44 : port->tx_buf_count = 0;
195 : 44 : port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1);
196 : 44 : port->is_multi = is_multi;
197 : :
198 : 44 : return port;
199 : : }
200 : :
201 : : static void *
202 : 47 : rte_port_ring_writer_create(void *params, int socket_id)
203 : : {
204 : 47 : return rte_port_ring_writer_create_internal(params, socket_id, 0);
205 : : }
206 : :
207 : : static void *
208 : 0 : rte_port_ring_multi_writer_create(void *params, int socket_id)
209 : : {
210 : 0 : return rte_port_ring_writer_create_internal(params, socket_id, 1);
211 : : }
212 : :
213 : : static inline void
214 : 53 : send_burst(struct rte_port_ring_writer *p)
215 : : {
216 : : uint32_t nb_tx;
217 : :
218 : 53 : nb_tx = rte_ring_sp_enqueue_burst(p->ring, (void **)p->tx_buf,
219 : : p->tx_buf_count, NULL);
220 : :
221 : : RTE_PORT_RING_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx);
222 [ - + ]: 53 : for ( ; nb_tx < p->tx_buf_count; nb_tx++)
223 : 0 : rte_pktmbuf_free(p->tx_buf[nb_tx]);
224 : :
225 : 53 : p->tx_buf_count = 0;
226 : 53 : }
227 : :
228 : : static inline void
229 : 0 : send_burst_mp(struct rte_port_ring_writer *p)
230 : : {
231 : : uint32_t nb_tx;
232 : :
233 : 0 : nb_tx = rte_ring_mp_enqueue_burst(p->ring, (void **)p->tx_buf,
234 : : p->tx_buf_count, NULL);
235 : :
236 : : RTE_PORT_RING_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx);
237 [ # # ]: 0 : for ( ; nb_tx < p->tx_buf_count; nb_tx++)
238 : 0 : rte_pktmbuf_free(p->tx_buf[nb_tx]);
239 : :
240 : 0 : p->tx_buf_count = 0;
241 : 0 : }
242 : :
243 : : static int
244 : 1209 : rte_port_ring_writer_tx(void *port, struct rte_mbuf *pkt)
245 : : {
246 : : struct rte_port_ring_writer *p = port;
247 : :
248 : 1209 : p->tx_buf[p->tx_buf_count++] = pkt;
249 : : RTE_PORT_RING_WRITER_STATS_PKTS_IN_ADD(p, 1);
250 [ + + ]: 1209 : if (p->tx_buf_count >= p->tx_burst_sz)
251 : 1 : send_burst(p);
252 : :
253 : 1209 : return 0;
254 : : }
255 : :
256 : : static int
257 : 0 : rte_port_ring_multi_writer_tx(void *port, struct rte_mbuf *pkt)
258 : : {
259 : : struct rte_port_ring_writer *p = port;
260 : :
261 : 0 : p->tx_buf[p->tx_buf_count++] = pkt;
262 : : RTE_PORT_RING_WRITER_STATS_PKTS_IN_ADD(p, 1);
263 [ # # ]: 0 : if (p->tx_buf_count >= p->tx_burst_sz)
264 : 0 : send_burst_mp(p);
265 : :
266 : 0 : return 0;
267 : : }
268 : :
269 : : static __rte_always_inline int
270 : : rte_port_ring_writer_tx_bulk_internal(void *port,
271 : : struct rte_mbuf **pkts,
272 : : uint64_t pkts_mask,
273 : : uint32_t is_multi)
274 : : {
275 : : struct rte_port_ring_writer *p =
276 : : port;
277 : :
278 : 15 : uint64_t bsz_mask = p->bsz_mask;
279 : 15 : uint32_t tx_buf_count = p->tx_buf_count;
280 : 15 : uint64_t expr = (pkts_mask & (pkts_mask + 1)) |
281 : : ((pkts_mask & bsz_mask) ^ bsz_mask);
282 : :
283 : 15 : if (expr == 0) {
284 : 1 : uint64_t n_pkts = rte_popcount64(pkts_mask);
285 : : uint32_t n_pkts_ok;
286 : :
287 [ - - - + ]: 1 : if (tx_buf_count) {
288 : : if (is_multi)
289 : 0 : send_burst_mp(p);
290 : : else
291 : 0 : send_burst(p);
292 : : }
293 : :
294 : : RTE_PORT_RING_WRITER_STATS_PKTS_IN_ADD(p, n_pkts);
295 : : if (is_multi)
296 : 0 : n_pkts_ok = rte_ring_mp_enqueue_burst(p->ring,
297 : : (void **)pkts, n_pkts, NULL);
298 : : else
299 : 1 : n_pkts_ok = rte_ring_sp_enqueue_burst(p->ring,
300 : : (void **)pkts, n_pkts, NULL);
301 : :
302 : : RTE_PORT_RING_WRITER_STATS_PKTS_DROP_ADD(p, n_pkts - n_pkts_ok);
303 [ - - - + ]: 1 : for ( ; n_pkts_ok < n_pkts; n_pkts_ok++) {
304 : 0 : struct rte_mbuf *pkt = pkts[n_pkts_ok];
305 : :
306 : 0 : rte_pktmbuf_free(pkt);
307 : : }
308 : : } else {
309 [ - - + + ]: 96 : for ( ; pkts_mask; ) {
310 : 82 : uint32_t pkt_index = rte_ctz64(pkts_mask);
311 : 82 : uint64_t pkt_mask = 1LLU << pkt_index;
312 : 82 : struct rte_mbuf *pkt = pkts[pkt_index];
313 : :
314 : 82 : p->tx_buf[tx_buf_count++] = pkt;
315 : : RTE_PORT_RING_WRITER_STATS_PKTS_IN_ADD(p, 1);
316 : 82 : pkts_mask &= ~pkt_mask;
317 : : }
318 : :
319 : 14 : p->tx_buf_count = tx_buf_count;
320 [ - - + + ]: 14 : if (tx_buf_count >= p->tx_burst_sz) {
321 : : if (is_multi)
322 : 0 : send_burst_mp(p);
323 : : else
324 : 1 : send_burst(p);
325 : : }
326 : : }
327 : :
328 : : return 0;
329 : : }
330 : :
331 : : static int
332 [ + + ]: 15 : rte_port_ring_writer_tx_bulk(void *port,
333 : : struct rte_mbuf **pkts,
334 : : uint64_t pkts_mask)
335 : : {
336 : 15 : return rte_port_ring_writer_tx_bulk_internal(port, pkts, pkts_mask, 0);
337 : : }
338 : :
339 : : static int
340 [ # # ]: 0 : rte_port_ring_multi_writer_tx_bulk(void *port,
341 : : struct rte_mbuf **pkts,
342 : : uint64_t pkts_mask)
343 : : {
344 : 0 : return rte_port_ring_writer_tx_bulk_internal(port, pkts, pkts_mask, 1);
345 : : }
346 : :
347 : : static int
348 : 125 : rte_port_ring_writer_flush(void *port)
349 : : {
350 : : struct rte_port_ring_writer *p = port;
351 : :
352 [ - + + + ]: 168 : if (p->tx_buf_count > 0)
353 : 51 : send_burst(p);
354 : :
355 : 125 : return 0;
356 : : }
357 : :
358 : : static int
359 : 0 : rte_port_ring_multi_writer_flush(void *port)
360 : : {
361 : : struct rte_port_ring_writer *p = port;
362 : :
363 [ # # # # ]: 0 : if (p->tx_buf_count > 0)
364 : 0 : send_burst_mp(p);
365 : :
366 : 0 : return 0;
367 : : }
368 : :
369 : : static int
370 : 44 : rte_port_ring_writer_free(void *port)
371 : : {
372 : : struct rte_port_ring_writer *p = port;
373 : :
374 [ + + ]: 44 : if (port == NULL) {
375 : 1 : PORT_LOG(ERR, "%s: Port is NULL", __func__);
376 : 1 : return -EINVAL;
377 : : }
378 : :
379 [ - + ]: 43 : if (p->is_multi)
380 : : rte_port_ring_multi_writer_flush(port);
381 : : else
382 : : rte_port_ring_writer_flush(port);
383 : :
384 : 43 : rte_free(port);
385 : :
386 : 43 : return 0;
387 : : }
388 : :
389 : : static int
390 : 0 : rte_port_ring_writer_stats_read(void *port,
391 : : struct rte_port_out_stats *stats, int clear)
392 : : {
393 : : struct rte_port_ring_writer *p =
394 : : port;
395 : :
396 [ # # ]: 0 : if (stats != NULL)
397 : 0 : memcpy(stats, &p->stats, sizeof(p->stats));
398 : :
399 [ # # ]: 0 : if (clear)
400 : 0 : memset(&p->stats, 0, sizeof(p->stats));
401 : :
402 : 0 : return 0;
403 : : }
404 : :
405 : : /*
406 : : * Port RING Writer Nodrop
407 : : */
408 : : #ifdef RTE_PORT_STATS_COLLECT
409 : :
410 : : #define RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val) \
411 : : port->stats.n_pkts_in += val
412 : : #define RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val) \
413 : : port->stats.n_pkts_drop += val
414 : :
415 : : #else
416 : :
417 : : #define RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val)
418 : : #define RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val)
419 : :
420 : : #endif
421 : :
422 : : struct rte_port_ring_writer_nodrop {
423 : : struct rte_port_out_stats stats;
424 : :
425 : : struct rte_mbuf *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX];
426 : : struct rte_ring *ring;
427 : : uint32_t tx_burst_sz;
428 : : uint32_t tx_buf_count;
429 : : uint64_t bsz_mask;
430 : : uint64_t n_retries;
431 : : uint32_t is_multi;
432 : : };
433 : :
434 : : static void *
435 : 0 : rte_port_ring_writer_nodrop_create_internal(void *params, int socket_id,
436 : : uint32_t is_multi)
437 : : {
438 : : struct rte_port_ring_writer_nodrop_params *conf =
439 : : params;
440 : : struct rte_port_ring_writer_nodrop *port;
441 : :
442 : : /* Check input parameters */
443 [ # # ]: 0 : if ((conf == NULL) ||
444 [ # # # # ]: 0 : (conf->ring == NULL) ||
445 [ # # # # ]: 0 : (rte_ring_is_prod_single(conf->ring) && is_multi) ||
446 [ # # ]: 0 : (!rte_ring_is_prod_single(conf->ring) && !is_multi) ||
447 [ # # ]: 0 : (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX)) {
448 : 0 : PORT_LOG(ERR, "%s: Invalid Parameters", __func__);
449 : 0 : return NULL;
450 : : }
451 : :
452 : : /* Memory allocation */
453 : 0 : port = rte_zmalloc_socket("PORT", sizeof(*port),
454 : : RTE_CACHE_LINE_SIZE, socket_id);
455 [ # # ]: 0 : if (port == NULL) {
456 : 0 : PORT_LOG(ERR, "%s: Failed to allocate port", __func__);
457 : 0 : return NULL;
458 : : }
459 : :
460 : : /* Initialization */
461 : 0 : port->ring = conf->ring;
462 : 0 : port->tx_burst_sz = conf->tx_burst_sz;
463 : 0 : port->tx_buf_count = 0;
464 : 0 : port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1);
465 : 0 : port->is_multi = is_multi;
466 : :
467 : : /*
468 : : * When n_retries is 0 it means that we should wait for every packet to
469 : : * send no matter how many retries should it take. To limit number of
470 : : * branches in fast path, we use UINT64_MAX instead of branching.
471 : : */
472 [ # # ]: 0 : port->n_retries = (conf->n_retries == 0) ? UINT64_MAX : conf->n_retries;
473 : :
474 : 0 : return port;
475 : : }
476 : :
477 : : static void *
478 : 0 : rte_port_ring_writer_nodrop_create(void *params, int socket_id)
479 : : {
480 : 0 : return rte_port_ring_writer_nodrop_create_internal(params, socket_id, 0);
481 : : }
482 : :
483 : : static void *
484 : 0 : rte_port_ring_multi_writer_nodrop_create(void *params, int socket_id)
485 : : {
486 : 0 : return rte_port_ring_writer_nodrop_create_internal(params, socket_id, 1);
487 : : }
488 : :
489 : : static inline void
490 : 0 : send_burst_nodrop(struct rte_port_ring_writer_nodrop *p)
491 : : {
492 : : uint32_t nb_tx = 0, i;
493 : :
494 : 0 : nb_tx = rte_ring_sp_enqueue_burst(p->ring, (void **)p->tx_buf,
495 : : p->tx_buf_count, NULL);
496 : :
497 : : /* We sent all the packets in a first try */
498 [ # # ]: 0 : if (nb_tx >= p->tx_buf_count) {
499 : 0 : p->tx_buf_count = 0;
500 : 0 : return;
501 : : }
502 : :
503 [ # # ]: 0 : for (i = 0; i < p->n_retries; i++) {
504 : 0 : nb_tx += rte_ring_sp_enqueue_burst(p->ring,
505 : 0 : (void **) (p->tx_buf + nb_tx),
506 : 0 : p->tx_buf_count - nb_tx, NULL);
507 : :
508 : : /* We sent all the packets in more than one try */
509 [ # # ]: 0 : if (nb_tx >= p->tx_buf_count) {
510 : 0 : p->tx_buf_count = 0;
511 : 0 : return;
512 : : }
513 : : }
514 : :
515 : : /* We didn't send the packets in maximum allowed attempts */
516 : : RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx);
517 [ # # ]: 0 : for ( ; nb_tx < p->tx_buf_count; nb_tx++)
518 : 0 : rte_pktmbuf_free(p->tx_buf[nb_tx]);
519 : :
520 : 0 : p->tx_buf_count = 0;
521 : : }
522 : :
523 : : static inline void
524 : 0 : send_burst_mp_nodrop(struct rte_port_ring_writer_nodrop *p)
525 : : {
526 : : uint32_t nb_tx = 0, i;
527 : :
528 : 0 : nb_tx = rte_ring_mp_enqueue_burst(p->ring, (void **)p->tx_buf,
529 : : p->tx_buf_count, NULL);
530 : :
531 : : /* We sent all the packets in a first try */
532 [ # # ]: 0 : if (nb_tx >= p->tx_buf_count) {
533 : 0 : p->tx_buf_count = 0;
534 : 0 : return;
535 : : }
536 : :
537 [ # # ]: 0 : for (i = 0; i < p->n_retries; i++) {
538 : 0 : nb_tx += rte_ring_mp_enqueue_burst(p->ring,
539 : 0 : (void **) (p->tx_buf + nb_tx),
540 : 0 : p->tx_buf_count - nb_tx, NULL);
541 : :
542 : : /* We sent all the packets in more than one try */
543 [ # # ]: 0 : if (nb_tx >= p->tx_buf_count) {
544 : 0 : p->tx_buf_count = 0;
545 : 0 : return;
546 : : }
547 : : }
548 : :
549 : : /* We didn't send the packets in maximum allowed attempts */
550 : : RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx);
551 [ # # ]: 0 : for ( ; nb_tx < p->tx_buf_count; nb_tx++)
552 : 0 : rte_pktmbuf_free(p->tx_buf[nb_tx]);
553 : :
554 : 0 : p->tx_buf_count = 0;
555 : : }
556 : :
557 : : static int
558 : 0 : rte_port_ring_writer_nodrop_tx(void *port, struct rte_mbuf *pkt)
559 : : {
560 : : struct rte_port_ring_writer_nodrop *p =
561 : : port;
562 : :
563 : 0 : p->tx_buf[p->tx_buf_count++] = pkt;
564 : : RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_IN_ADD(p, 1);
565 [ # # ]: 0 : if (p->tx_buf_count >= p->tx_burst_sz)
566 : 0 : send_burst_nodrop(p);
567 : :
568 : 0 : return 0;
569 : : }
570 : :
571 : : static int
572 : 0 : rte_port_ring_multi_writer_nodrop_tx(void *port, struct rte_mbuf *pkt)
573 : : {
574 : : struct rte_port_ring_writer_nodrop *p =
575 : : port;
576 : :
577 : 0 : p->tx_buf[p->tx_buf_count++] = pkt;
578 : : RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_IN_ADD(p, 1);
579 [ # # ]: 0 : if (p->tx_buf_count >= p->tx_burst_sz)
580 : 0 : send_burst_mp_nodrop(p);
581 : :
582 : 0 : return 0;
583 : : }
584 : :
585 : : static __rte_always_inline int
586 : : rte_port_ring_writer_nodrop_tx_bulk_internal(void *port,
587 : : struct rte_mbuf **pkts,
588 : : uint64_t pkts_mask,
589 : : uint32_t is_multi)
590 : : {
591 : : struct rte_port_ring_writer_nodrop *p =
592 : : port;
593 : :
594 : 0 : uint64_t bsz_mask = p->bsz_mask;
595 : 0 : uint32_t tx_buf_count = p->tx_buf_count;
596 : 0 : uint64_t expr = (pkts_mask & (pkts_mask + 1)) |
597 : : ((pkts_mask & bsz_mask) ^ bsz_mask);
598 : :
599 : 0 : if (expr == 0) {
600 : 0 : uint64_t n_pkts = rte_popcount64(pkts_mask);
601 : : uint32_t n_pkts_ok;
602 : :
603 [ # # # # ]: 0 : if (tx_buf_count) {
604 : : if (is_multi)
605 : 0 : send_burst_mp_nodrop(p);
606 : : else
607 : 0 : send_burst_nodrop(p);
608 : : }
609 : :
610 : : RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_IN_ADD(p, n_pkts);
611 : : if (is_multi)
612 : : n_pkts_ok =
613 : 0 : rte_ring_mp_enqueue_burst(p->ring,
614 : : (void **)pkts, n_pkts, NULL);
615 : : else
616 : : n_pkts_ok =
617 : 0 : rte_ring_sp_enqueue_burst(p->ring,
618 : : (void **)pkts, n_pkts, NULL);
619 : :
620 [ # # # # ]: 0 : if (n_pkts_ok >= n_pkts)
621 : : return 0;
622 : :
623 : : /*
624 : : * If we didn't manage to send all packets in single burst, move
625 : : * remaining packets to the buffer and call send burst.
626 : : */
627 [ # # # # ]: 0 : for (; n_pkts_ok < n_pkts; n_pkts_ok++) {
628 : 0 : struct rte_mbuf *pkt = pkts[n_pkts_ok];
629 : :
630 : 0 : p->tx_buf[p->tx_buf_count++] = pkt;
631 : : }
632 : : if (is_multi)
633 : 0 : send_burst_mp_nodrop(p);
634 : : else
635 : 0 : send_burst_nodrop(p);
636 : : } else {
637 [ # # # # ]: 0 : for ( ; pkts_mask; ) {
638 : 0 : uint32_t pkt_index = rte_ctz64(pkts_mask);
639 : 0 : uint64_t pkt_mask = 1LLU << pkt_index;
640 : 0 : struct rte_mbuf *pkt = pkts[pkt_index];
641 : :
642 : 0 : p->tx_buf[tx_buf_count++] = pkt;
643 : : RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_IN_ADD(p, 1);
644 : 0 : pkts_mask &= ~pkt_mask;
645 : : }
646 : :
647 : 0 : p->tx_buf_count = tx_buf_count;
648 [ # # # # ]: 0 : if (tx_buf_count >= p->tx_burst_sz) {
649 : : if (is_multi)
650 : 0 : send_burst_mp_nodrop(p);
651 : : else
652 : 0 : send_burst_nodrop(p);
653 : : }
654 : : }
655 : :
656 : : return 0;
657 : : }
658 : :
659 : : static int
660 [ # # ]: 0 : rte_port_ring_writer_nodrop_tx_bulk(void *port,
661 : : struct rte_mbuf **pkts,
662 : : uint64_t pkts_mask)
663 : : {
664 : : return
665 : 0 : rte_port_ring_writer_nodrop_tx_bulk_internal(port, pkts, pkts_mask, 0);
666 : : }
667 : :
668 : : static int
669 [ # # ]: 0 : rte_port_ring_multi_writer_nodrop_tx_bulk(void *port,
670 : : struct rte_mbuf **pkts,
671 : : uint64_t pkts_mask)
672 : : {
673 : : return
674 : 0 : rte_port_ring_writer_nodrop_tx_bulk_internal(port, pkts, pkts_mask, 1);
675 : : }
676 : :
677 : : static int
678 : 0 : rte_port_ring_writer_nodrop_flush(void *port)
679 : : {
680 : : struct rte_port_ring_writer_nodrop *p =
681 : : port;
682 : :
683 [ # # # # ]: 0 : if (p->tx_buf_count > 0)
684 : 0 : send_burst_nodrop(p);
685 : :
686 : 0 : return 0;
687 : : }
688 : :
689 : : static int
690 : 0 : rte_port_ring_multi_writer_nodrop_flush(void *port)
691 : : {
692 : : struct rte_port_ring_writer_nodrop *p =
693 : : port;
694 : :
695 [ # # # # ]: 0 : if (p->tx_buf_count > 0)
696 : 0 : send_burst_mp_nodrop(p);
697 : :
698 : 0 : return 0;
699 : : }
700 : :
701 : : static int
702 : 0 : rte_port_ring_writer_nodrop_free(void *port)
703 : : {
704 : : struct rte_port_ring_writer_nodrop *p =
705 : : port;
706 : :
707 [ # # ]: 0 : if (port == NULL) {
708 : 0 : PORT_LOG(ERR, "%s: Port is NULL", __func__);
709 : 0 : return -EINVAL;
710 : : }
711 : :
712 [ # # ]: 0 : if (p->is_multi)
713 : : rte_port_ring_multi_writer_nodrop_flush(port);
714 : : else
715 : : rte_port_ring_writer_nodrop_flush(port);
716 : :
717 : 0 : rte_free(port);
718 : :
719 : 0 : return 0;
720 : : }
721 : :
722 : : static int
723 : 0 : rte_port_ring_writer_nodrop_stats_read(void *port,
724 : : struct rte_port_out_stats *stats, int clear)
725 : : {
726 : : struct rte_port_ring_writer_nodrop *p =
727 : : port;
728 : :
729 [ # # ]: 0 : if (stats != NULL)
730 : 0 : memcpy(stats, &p->stats, sizeof(p->stats));
731 : :
732 [ # # ]: 0 : if (clear)
733 : 0 : memset(&p->stats, 0, sizeof(p->stats));
734 : :
735 : 0 : return 0;
736 : : }
737 : :
738 : : /*
739 : : * Summary of port operations
740 : : */
741 : : struct rte_port_in_ops rte_port_ring_reader_ops = {
742 : : .f_create = rte_port_ring_reader_create,
743 : : .f_free = rte_port_ring_reader_free,
744 : : .f_rx = rte_port_ring_reader_rx,
745 : : .f_stats = rte_port_ring_reader_stats_read,
746 : : };
747 : :
748 : : struct rte_port_out_ops rte_port_ring_writer_ops = {
749 : : .f_create = rte_port_ring_writer_create,
750 : : .f_free = rte_port_ring_writer_free,
751 : : .f_tx = rte_port_ring_writer_tx,
752 : : .f_tx_bulk = rte_port_ring_writer_tx_bulk,
753 : : .f_flush = rte_port_ring_writer_flush,
754 : : .f_stats = rte_port_ring_writer_stats_read,
755 : : };
756 : :
757 : : struct rte_port_out_ops rte_port_ring_writer_nodrop_ops = {
758 : : .f_create = rte_port_ring_writer_nodrop_create,
759 : : .f_free = rte_port_ring_writer_nodrop_free,
760 : : .f_tx = rte_port_ring_writer_nodrop_tx,
761 : : .f_tx_bulk = rte_port_ring_writer_nodrop_tx_bulk,
762 : : .f_flush = rte_port_ring_writer_nodrop_flush,
763 : : .f_stats = rte_port_ring_writer_nodrop_stats_read,
764 : : };
765 : :
766 : : struct rte_port_in_ops rte_port_ring_multi_reader_ops = {
767 : : .f_create = rte_port_ring_multi_reader_create,
768 : : .f_free = rte_port_ring_reader_free,
769 : : .f_rx = rte_port_ring_multi_reader_rx,
770 : : .f_stats = rte_port_ring_reader_stats_read,
771 : : };
772 : :
773 : : struct rte_port_out_ops rte_port_ring_multi_writer_ops = {
774 : : .f_create = rte_port_ring_multi_writer_create,
775 : : .f_free = rte_port_ring_writer_free,
776 : : .f_tx = rte_port_ring_multi_writer_tx,
777 : : .f_tx_bulk = rte_port_ring_multi_writer_tx_bulk,
778 : : .f_flush = rte_port_ring_multi_writer_flush,
779 : : .f_stats = rte_port_ring_writer_stats_read,
780 : : };
781 : :
782 : : struct rte_port_out_ops rte_port_ring_multi_writer_nodrop_ops = {
783 : : .f_create = rte_port_ring_multi_writer_nodrop_create,
784 : : .f_free = rte_port_ring_writer_nodrop_free,
785 : : .f_tx = rte_port_ring_multi_writer_nodrop_tx,
786 : : .f_tx_bulk = rte_port_ring_multi_writer_nodrop_tx_bulk,
787 : : .f_flush = rte_port_ring_multi_writer_nodrop_flush,
788 : : .f_stats = rte_port_ring_writer_nodrop_stats_read,
789 : : };
|