Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2021 Intel Corporation
3 : : */
4 : : #include <string.h>
5 : : #include <stdint.h>
6 : : #include <stdlib.h>
7 : :
8 : : #include <rte_mbuf.h>
9 : : #include <rte_ring.h>
10 : : #include <rte_hexdump.h>
11 : :
12 : : #include "rte_swx_port_ring.h"
13 : :
14 : : #ifndef TRACE_LEVEL
15 : : #define TRACE_LEVEL 0
16 : : #endif
17 : :
18 : : #if TRACE_LEVEL
19 : : #define TRACE(...) printf(__VA_ARGS__)
20 : : #else
21 : : #define TRACE(...)
22 : : #endif
23 : :
24 : : /*
25 : : * Reader
26 : : */
27 : : struct reader {
28 : : struct {
29 : : struct rte_ring *ring;
30 : : char *name;
31 : : uint32_t burst_size;
32 : : } params;
33 : : struct rte_swx_port_in_stats stats;
34 : : struct rte_mbuf **pkts;
35 : : int n_pkts;
36 : : int pos;
37 : : };
38 : :
39 : : static void *
40 : 0 : reader_create(void *args)
41 : : {
42 : : struct rte_swx_port_ring_reader_params *params = args;
43 : : struct rte_ring *ring;
44 : : struct reader *p = NULL;
45 : :
46 : : /* Check input parameters. */
47 [ # # # # : 0 : if (!params || !params->name || !params->burst_size)
# # ]
48 : 0 : goto error;
49 : :
50 : 0 : ring = rte_ring_lookup(params->name);
51 [ # # ]: 0 : if (!ring)
52 : 0 : goto error;
53 : :
54 : : /* Memory allocation. */
55 : 0 : p = calloc(1, sizeof(struct reader));
56 [ # # ]: 0 : if (!p)
57 : 0 : goto error;
58 : :
59 : 0 : p->params.name = strdup(params->name);
60 [ # # ]: 0 : if (!p->params.name)
61 : 0 : goto error;
62 : :
63 : 0 : p->pkts = calloc(params->burst_size, sizeof(struct rte_mbuf *));
64 [ # # ]: 0 : if (!p->pkts)
65 : 0 : goto error;
66 : :
67 : : /* Initialization. */
68 : 0 : p->params.ring = ring;
69 : 0 : p->params.burst_size = params->burst_size;
70 : :
71 : 0 : return p;
72 : :
73 : 0 : error:
74 [ # # ]: 0 : if (!p)
75 : 0 : return NULL;
76 : :
77 : 0 : free(p->pkts);
78 : 0 : free(p->params.name);
79 : 0 : free(p);
80 : 0 : return NULL;
81 : : }
82 : :
83 : : static int
84 : 0 : reader_pkt_rx(void *port, struct rte_swx_pkt *pkt)
85 : : {
86 : : struct reader *p = port;
87 : : struct rte_mbuf *m;
88 : :
89 [ # # ]: 0 : if (p->pos == p->n_pkts) {
90 : : int n_pkts;
91 : :
92 : 0 : n_pkts = rte_ring_sc_dequeue_burst(p->params.ring,
93 : 0 : (void **) p->pkts,
94 : : p->params.burst_size,
95 : : NULL);
96 [ # # ]: 0 : if (!n_pkts) {
97 : 0 : p->stats.n_empty++;
98 : 0 : return 0;
99 : : }
100 : :
101 : : TRACE("[Ring %s] %d packets in\n",
102 : : p->params.name,
103 : : n_pkts);
104 : :
105 : 0 : p->n_pkts = n_pkts;
106 : 0 : p->pos = 0;
107 : : }
108 : :
109 : 0 : m = p->pkts[p->pos++];
110 : 0 : pkt->handle = m;
111 : 0 : pkt->pkt = m->buf_addr;
112 : 0 : pkt->offset = m->data_off;
113 : 0 : pkt->length = m->pkt_len;
114 : :
115 : : TRACE("[Ring %s] Pkt %d (%u bytes at offset %u)\n",
116 : : (uint32_t)p->params.name,
117 : : p->pos - 1,
118 : : pkt->length,
119 : : pkt->offset);
120 : : if (TRACE_LEVEL)
121 : : rte_hexdump(stdout,
122 : : NULL,
123 : : &((uint8_t *)m->buf_addr)[m->data_off],
124 : : m->data_len);
125 : :
126 : 0 : p->stats.n_pkts++;
127 : 0 : p->stats.n_bytes += pkt->length;
128 : :
129 : 0 : return 1;
130 : : }
131 : :
132 : : static void
133 : 0 : reader_free(void *port)
134 : : {
135 : : struct reader *p = port;
136 : : int i;
137 : :
138 [ # # ]: 0 : if (!p)
139 : : return;
140 : :
141 [ # # ]: 0 : for (i = 0; i < p->n_pkts; i++) {
142 : 0 : struct rte_mbuf *pkt = p->pkts[i];
143 : :
144 : 0 : rte_pktmbuf_free(pkt);
145 : : }
146 : :
147 : 0 : free(p->pkts);
148 : 0 : free(p->params.name);
149 : 0 : free(p);
150 : : }
151 : :
152 : : static void
153 : 0 : reader_stats_read(void *port, struct rte_swx_port_in_stats *stats)
154 : : {
155 : : struct reader *p = port;
156 : :
157 [ # # ]: 0 : if (!stats)
158 : : return;
159 : :
160 : 0 : memcpy(stats, &p->stats, sizeof(p->stats));
161 : : }
162 : :
163 : : /*
164 : : * Writer
165 : : */
166 : : struct writer {
167 : : struct {
168 : : struct rte_ring *ring;
169 : : char *name;
170 : : uint32_t burst_size;
171 : : } params;
172 : : struct rte_swx_port_out_stats stats;
173 : :
174 : : struct rte_mbuf **pkts;
175 : : int n_pkts;
176 : : uint32_t n_bytes;
177 : : int flush_flag;
178 : : };
179 : :
180 : : static void *
181 : 0 : writer_create(void *args)
182 : : {
183 : : struct rte_swx_port_ring_writer_params *params = args;
184 : : struct rte_ring *ring;
185 : : struct writer *p = NULL;
186 : :
187 : : /* Check input parameters. */
188 [ # # # # : 0 : if (!params || !params->name || !params->burst_size)
# # ]
189 : 0 : goto error;
190 : :
191 : 0 : ring = rte_ring_lookup(params->name);
192 [ # # ]: 0 : if (!ring)
193 : 0 : goto error;
194 : :
195 : : /* Memory allocation. */
196 : 0 : p = calloc(1, sizeof(struct writer));
197 [ # # ]: 0 : if (!p)
198 : 0 : goto error;
199 : :
200 : 0 : p->params.name = strdup(params->name);
201 [ # # ]: 0 : if (!p->params.name)
202 : 0 : goto error;
203 : :
204 : 0 : p->pkts = calloc(params->burst_size, sizeof(struct rte_mbuf *));
205 [ # # ]: 0 : if (!p->pkts)
206 : 0 : goto error;
207 : :
208 : : /* Initialization. */
209 : 0 : p->params.ring = ring;
210 : 0 : p->params.burst_size = params->burst_size;
211 : :
212 : 0 : return p;
213 : :
214 : 0 : error:
215 [ # # ]: 0 : if (!p)
216 : 0 : return NULL;
217 : :
218 : 0 : free(p->params.name);
219 : 0 : free(p->pkts);
220 : 0 : free(p);
221 : 0 : return NULL;
222 : : }
223 : :
224 : : static inline void
225 : 0 : __writer_flush(struct writer *p)
226 : : {
227 : 0 : struct rte_mbuf **pkts = p->pkts;
228 : 0 : uint64_t n_pkts_total = p->stats.n_pkts;
229 : 0 : uint64_t n_bytes_total = p->stats.n_bytes;
230 : 0 : uint64_t n_pkts_drop_total = p->stats.n_pkts_drop;
231 : 0 : uint64_t n_bytes_drop_total = p->stats.n_bytes_drop;
232 : 0 : int n_pkts = p->n_pkts, n_pkts_drop, n_pkts_tx;
233 : 0 : uint32_t n_bytes = p->n_bytes, n_bytes_drop = 0;
234 : :
235 : : /* Packet TX. */
236 : 0 : n_pkts_tx = rte_ring_sp_enqueue_burst(p->params.ring,
237 : : (void **)pkts,
238 : : n_pkts,
239 : : NULL);
240 : :
241 : : /* Packet drop. */
242 : 0 : n_pkts_drop = n_pkts - n_pkts_tx;
243 : :
244 [ # # ]: 0 : for ( ; n_pkts_tx < n_pkts; n_pkts_tx++) {
245 : 0 : struct rte_mbuf *m = pkts[n_pkts_tx];
246 : :
247 : 0 : n_bytes_drop += m->pkt_len;
248 : 0 : rte_pktmbuf_free(m);
249 : : }
250 : :
251 : : /* Port update. */
252 : 0 : p->stats.n_pkts = n_pkts_total + n_pkts - n_pkts_drop;
253 : 0 : p->stats.n_bytes = n_bytes_total + n_bytes - n_bytes_drop;
254 : 0 : p->stats.n_pkts_drop = n_pkts_drop_total + n_pkts_drop;
255 : 0 : p->stats.n_bytes_drop = n_bytes_drop_total + n_bytes_drop;
256 : 0 : p->n_pkts = 0;
257 : 0 : p->n_bytes = 0;
258 : 0 : p->flush_flag = 0;
259 : :
260 : : TRACE("[Ring %s] Buffered packets flushed: %d out, %d dropped\n",
261 : : p->params.name,
262 : : n_pkts - n_pkts_drop,
263 : : n_pkts_drop);
264 : 0 : }
265 : :
266 : : static void
267 : 0 : writer_pkt_tx(void *port, struct rte_swx_pkt *pkt)
268 : : {
269 : : struct writer *p = port;
270 : 0 : int n_pkts = p->n_pkts;
271 : 0 : uint32_t n_bytes = p->n_bytes;
272 : 0 : struct rte_mbuf *m = pkt->handle;
273 : 0 : uint32_t pkt_length = pkt->length;
274 : :
275 : : TRACE("[Ring %s] Pkt %d (%u bytes at offset %u)\n",
276 : : p->params.name,
277 : : p->n_pkts - 1,
278 : : pkt->length,
279 : : pkt->offset);
280 : : if (TRACE_LEVEL)
281 : : rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
282 : :
283 : 0 : m->data_len = (uint16_t)(pkt_length + m->data_len - m->pkt_len);
284 : 0 : m->pkt_len = pkt_length;
285 : 0 : m->data_off = (uint16_t)pkt->offset;
286 : :
287 : 0 : p->pkts[n_pkts++] = m;
288 : 0 : p->n_pkts = n_pkts;
289 : 0 : p->n_bytes = n_bytes + pkt_length;
290 : :
291 [ # # ]: 0 : if (n_pkts == (int)p->params.burst_size)
292 : 0 : __writer_flush(p);
293 : 0 : }
294 : :
295 : : static void
296 : 0 : writer_pkt_fast_clone_tx(void *port, struct rte_swx_pkt *pkt)
297 : : {
298 : : struct writer *p = port;
299 : 0 : int n_pkts = p->n_pkts;
300 : 0 : uint32_t n_bytes = p->n_bytes;
301 : 0 : uint64_t n_pkts_clone = p->stats.n_pkts_clone;
302 : 0 : struct rte_mbuf *m = pkt->handle;
303 : 0 : uint32_t pkt_length = pkt->length;
304 : :
305 : : TRACE("[Ring %s] Pkt %d (%u bytes at offset %u) (fast clone)\n",
306 : : p->params.name,
307 : : p->n_pkts - 1,
308 : : pkt->length,
309 : : pkt->offset);
310 : : if (TRACE_LEVEL)
311 : : rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
312 : :
313 : 0 : m->data_len = (uint16_t)(pkt_length + m->data_len - m->pkt_len);
314 : 0 : m->pkt_len = pkt_length;
315 : 0 : m->data_off = (uint16_t)pkt->offset;
316 : : rte_pktmbuf_refcnt_update(m, 1);
317 : :
318 : 0 : p->pkts[n_pkts++] = m;
319 : 0 : p->n_pkts = n_pkts;
320 : 0 : p->n_bytes = n_bytes + pkt_length;
321 : 0 : p->stats.n_pkts_clone = n_pkts_clone + 1;
322 : :
323 [ # # ]: 0 : if (n_pkts == (int)p->params.burst_size)
324 : 0 : __writer_flush(p);
325 : 0 : }
326 : :
327 : : static void
328 : 0 : writer_pkt_clone_tx(void *port, struct rte_swx_pkt *pkt, uint32_t truncation_length)
329 : : {
330 : : struct writer *p = port;
331 : 0 : int n_pkts = p->n_pkts;
332 : 0 : uint32_t n_bytes = p->n_bytes;
333 : 0 : uint64_t n_pkts_clone = p->stats.n_pkts_clone;
334 : 0 : struct rte_mbuf *m = pkt->handle, *m_clone;
335 : 0 : uint32_t pkt_length = pkt->length;
336 : :
337 : : TRACE("[Ring %s] Pkt %d (%u bytes at offset %u) (clone)\n",
338 : : p->params.name,
339 : : p->n_pkts - 1,
340 : : pkt->length,
341 : : pkt->offset);
342 : : if (TRACE_LEVEL)
343 : : rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
344 : :
345 : 0 : m->data_len = (uint16_t)(pkt_length + m->data_len - m->pkt_len);
346 : 0 : m->pkt_len = pkt_length;
347 : 0 : m->data_off = (uint16_t)pkt->offset;
348 : :
349 : 0 : m_clone = rte_pktmbuf_copy(m, m->pool, 0, truncation_length);
350 [ # # ]: 0 : if (!m_clone) {
351 : 0 : p->stats.n_pkts_clone_err++;
352 : 0 : return;
353 : : }
354 : :
355 : 0 : p->pkts[n_pkts++] = m_clone;
356 : 0 : p->n_pkts = n_pkts;
357 : 0 : p->n_bytes = n_bytes + pkt_length;
358 : 0 : p->stats.n_pkts_clone = n_pkts_clone + 1;
359 : :
360 [ # # ]: 0 : if (n_pkts == (int)p->params.burst_size)
361 : 0 : __writer_flush(p);
362 : : }
363 : :
364 : : static void
365 : 0 : writer_flush(void *port)
366 : : {
367 : : struct writer *p = port;
368 : :
369 [ # # # # ]: 0 : if (p->n_pkts && p->flush_flag)
370 : 0 : __writer_flush(p);
371 : :
372 : 0 : p->flush_flag = 1;
373 : 0 : }
374 : :
375 : : static void
376 : 0 : writer_free(void *port)
377 : : {
378 : : struct writer *p = port;
379 : : int i;
380 : :
381 [ # # ]: 0 : if (!p)
382 : : return;
383 : :
384 [ # # ]: 0 : for (i = 0; i < p->n_pkts; i++) {
385 : 0 : struct rte_mbuf *m = p->pkts[i];
386 : :
387 : 0 : rte_pktmbuf_free(m);
388 : : }
389 : :
390 : 0 : free(p->pkts);
391 : 0 : free(p->params.name);
392 : 0 : free(port);
393 : : }
394 : :
395 : : static void
396 : 0 : writer_stats_read(void *port, struct rte_swx_port_out_stats *stats)
397 : : {
398 : : struct writer *p = port;
399 : :
400 [ # # ]: 0 : if (!stats)
401 : : return;
402 : :
403 : 0 : memcpy(stats, &p->stats, sizeof(p->stats));
404 : : }
405 : :
406 : : /*
407 : : * Summary of port operations
408 : : */
409 : : struct rte_swx_port_in_ops rte_swx_port_ring_reader_ops = {
410 : : .create = reader_create,
411 : : .free = reader_free,
412 : : .pkt_rx = reader_pkt_rx,
413 : : .stats_read = reader_stats_read,
414 : : };
415 : :
416 : : struct rte_swx_port_out_ops rte_swx_port_ring_writer_ops = {
417 : : .create = writer_create,
418 : : .free = writer_free,
419 : : .pkt_tx = writer_pkt_tx,
420 : : .pkt_fast_clone_tx = writer_pkt_fast_clone_tx,
421 : : .pkt_clone_tx = writer_pkt_clone_tx,
422 : : .flush = writer_flush,
423 : : .stats_read = writer_stats_read,
424 : : };
|