doc: add Meson coding style to contributors guide
[dpdk.git] / lib / librte_port / rte_swx_port_ring.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2021 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_hexdump.h>
10
11 #include "rte_swx_port_ring.h"
12
13 #ifndef TRACE_LEVEL
14 #define TRACE_LEVEL 0
15 #endif
16
17 #if TRACE_LEVEL
18 #define TRACE(...) printf(__VA_ARGS__)
19 #else
20 #define TRACE(...)
21 #endif
22
23 /*
24  * Reader
25  */
26 struct reader {
27         struct {
28                 struct rte_ring *ring;
29                 char *name;
30                 uint32_t burst_size;
31         } params;
32         struct rte_swx_port_in_stats stats;
33         struct rte_mbuf **pkts;
34         int n_pkts;
35         int pos;
36 };
37
38 static void *
39 reader_create(void *args)
40 {
41         struct rte_swx_port_ring_reader_params *params = args;
42         struct rte_ring *ring;
43         struct reader *p = NULL;
44
45         /* Check input parameters. */
46         if (!params || !params->name || !params->burst_size)
47                 goto error;
48
49         ring = rte_ring_lookup(params->name);
50         if (!ring)
51                 goto error;
52
53         /* Memory allocation. */
54         p = calloc(1, sizeof(struct reader));
55         if (!p)
56                 goto error;
57
58         p->params.name = strdup(params->name);
59         if (!p->params.name)
60                 goto error;
61
62         p->pkts = calloc(params->burst_size, sizeof(struct rte_mbuf *));
63         if (!p->pkts)
64                 goto error;
65
66         /* Initialization. */
67         p->params.ring = ring;
68         p->params.burst_size = params->burst_size;
69
70         return p;
71
72 error:
73         if (!p)
74                 return NULL;
75
76         free(p->pkts);
77         free(p->params.name);
78         free(p);
79         return NULL;
80 }
81
82 static int
83 reader_pkt_rx(void *port, struct rte_swx_pkt *pkt)
84 {
85         struct reader *p = port;
86         struct rte_mbuf *m;
87
88         if (p->pos == p->n_pkts) {
89                 int n_pkts;
90
91                 n_pkts = rte_ring_sc_dequeue_burst(p->params.ring,
92                         (void **) p->pkts,
93                         p->params.burst_size,
94                         NULL);
95                 if (!n_pkts) {
96                         p->stats.n_empty++;
97                         return 0;
98                 }
99
100                 TRACE("[Ring %s] %d packets in\n",
101                       p->params.name,
102                       n_pkts);
103
104                 p->n_pkts = n_pkts;
105                 p->pos = 0;
106         }
107
108         m = p->pkts[p->pos++];
109         pkt->handle = m;
110         pkt->pkt = m->buf_addr;
111         pkt->offset = m->data_off;
112         pkt->length = m->pkt_len;
113
114         TRACE("[Ring %s] Pkt %d (%u bytes at offset %u)\n",
115               (uint32_t)p->params.name,
116               p->pos - 1,
117               pkt->length,
118               pkt->offset);
119         if (TRACE_LEVEL)
120                 rte_hexdump(stdout,
121                             NULL,
122                             &((uint8_t *)m->buf_addr)[m->data_off],
123                             m->data_len);
124
125         p->stats.n_pkts++;
126         p->stats.n_bytes += pkt->length;
127
128         return 1;
129 }
130
131 static void
132 reader_free(void *port)
133 {
134         struct reader *p = port;
135         int i;
136
137         if (!p)
138                 return;
139
140         for (i = 0; i < p->n_pkts; i++) {
141                 struct rte_mbuf *pkt = p->pkts[i];
142
143                 rte_pktmbuf_free(pkt);
144         }
145
146         free(p->pkts);
147         free(p->params.name);
148         free(p);
149 }
150
151 static void
152 reader_stats_read(void *port, struct rte_swx_port_in_stats *stats)
153 {
154         struct reader *p = port;
155
156         if (!stats)
157                 return;
158
159         memcpy(stats, &p->stats, sizeof(p->stats));
160 }
161
162 /*
163  * Writer
164  */
165 struct writer {
166         struct {
167                 struct rte_ring *ring;
168                 char *name;
169                 uint32_t burst_size;
170         } params;
171         struct rte_swx_port_out_stats stats;
172
173         struct rte_mbuf **pkts;
174         int n_pkts;
175 };
176
177 static void *
178 writer_create(void *args)
179 {
180         struct rte_swx_port_ring_writer_params *params = args;
181         struct rte_ring *ring;
182         struct writer *p = NULL;
183
184         /* Check input parameters. */
185         if (!params || !params->name || !params->burst_size)
186                 goto error;
187
188         ring = rte_ring_lookup(params->name);
189         if (!ring)
190                 goto error;
191
192         /* Memory allocation. */
193         p = calloc(1, sizeof(struct writer));
194         if (!p)
195                 goto error;
196
197         p->params.name = strdup(params->name);
198         if (!p->params.name)
199                 goto error;
200
201         p->pkts = calloc(params->burst_size, sizeof(struct rte_mbuf *));
202         if (!p->pkts)
203                 goto error;
204
205         /* Initialization. */
206         p->params.ring = ring;
207         p->params.burst_size = params->burst_size;
208
209         return p;
210
211 error:
212         if (!p)
213                 return NULL;
214
215         free(p->params.name);
216         free(p->pkts);
217         free(p);
218         return NULL;
219 }
220
221 static void
222 __writer_flush(struct writer *p)
223 {
224         int n_pkts;
225
226         for (n_pkts = 0; ; ) {
227                 n_pkts += rte_ring_sp_enqueue_burst(p->params.ring,
228                                                     (void **)p->pkts + n_pkts,
229                                                     p->n_pkts - n_pkts,
230                                                     NULL);
231
232                 TRACE("[Ring %s] %d packets out\n", p->params.name, n_pkts);
233
234                 if (n_pkts == p->n_pkts)
235                         break;
236         }
237
238         p->n_pkts = 0;
239 }
240
241 static void
242 writer_pkt_tx(void *port, struct rte_swx_pkt *pkt)
243 {
244         struct writer *p = port;
245         struct rte_mbuf *m = pkt->handle;
246
247         TRACE("[Ring %s] Pkt %d (%u bytes at offset %u)\n",
248               p->params.name,
249               p->n_pkts - 1,
250               pkt->length,
251               pkt->offset);
252         if (TRACE_LEVEL)
253                 rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
254
255         m->pkt_len = pkt->length;
256         m->data_len = (uint16_t)pkt->length;
257         m->data_off = (uint16_t)pkt->offset;
258
259         p->stats.n_pkts++;
260         p->stats.n_bytes += pkt->length;
261
262         p->pkts[p->n_pkts++] = m;
263         if (p->n_pkts ==  (int)p->params.burst_size)
264                 __writer_flush(p);
265 }
266
267 static void
268 writer_flush(void *port)
269 {
270         struct writer *p = port;
271
272         if (p->n_pkts)
273                 __writer_flush(p);
274 }
275
276 static void
277 writer_free(void *port)
278 {
279         struct writer *p = port;
280
281         if (!p)
282                 return;
283
284         writer_flush(p);
285         free(p->pkts);
286         free(p->params.name);
287         free(port);
288 }
289
290 static void
291 writer_stats_read(void *port, struct rte_swx_port_out_stats *stats)
292 {
293         struct writer *p = port;
294
295         if (!stats)
296                 return;
297
298         memcpy(stats, &p->stats, sizeof(p->stats));
299 }
300
301 /*
302  * Summary of port operations
303  */
304 struct rte_swx_port_in_ops rte_swx_port_ring_reader_ops = {
305         .create = reader_create,
306         .free = reader_free,
307         .pkt_rx = reader_pkt_rx,
308         .stats_read = reader_stats_read,
309 };
310
311 struct rte_swx_port_out_ops rte_swx_port_ring_writer_ops = {
312         .create = writer_create,
313         .free = writer_free,
314         .pkt_tx = writer_pkt_tx,
315         .flush = writer_flush,
316         .stats_read = writer_stats_read,
317 };