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