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 : : #include <unistd.h>
8 : :
9 : : #include <rte_mbuf.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 : 0 : 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 [ # # # # : 0 : if (!conf || conf->fd < 0 || conf->mtu == 0 || !conf->mempool)
# # # # ]
49 : : return NULL;
50 : :
51 : : /* Memory allocation. */
52 : 0 : p = calloc(1, sizeof(struct reader));
53 [ # # ]: 0 : if (!p)
54 : : return NULL;
55 : :
56 : 0 : p->pkts = calloc(conf->burst_size, sizeof(struct rte_mbuf *));
57 [ # # ]: 0 : if (!p->pkts) {
58 : 0 : free(p);
59 : 0 : return NULL;
60 : : }
61 : :
62 : : /* Initialization. */
63 : 0 : p->params.fd = conf->fd;
64 : 0 : p->params.mtu = conf->mtu;
65 : 0 : p->params.burst_size = conf->burst_size;
66 : 0 : p->params.mempool = conf->mempool;
67 : :
68 : 0 : return p;
69 : : }
70 : :
71 : : static void
72 : 0 : reader_free(void *port)
73 : : {
74 : : struct reader *p = port;
75 : : uint32_t i;
76 : :
77 [ # # ]: 0 : if (!p)
78 : : return;
79 : :
80 [ # # ]: 0 : for (i = 0; i < p->n_pkts; i++)
81 : 0 : rte_pktmbuf_free(p->pkts[i]);
82 : :
83 : 0 : free(p->pkts);
84 : 0 : free(p);
85 : : }
86 : :
87 : : static int
88 : 0 : 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 [ # # ]: 0 : if (p->n_pkts == p->pos) {
97 [ # # ]: 0 : if (rte_pktmbuf_alloc_bulk(p->params.mempool, p->pkts, p->params.burst_size) != 0)
98 : : return 0;
99 : :
100 [ # # ]: 0 : for (i = 0; i < p->params.burst_size; i++) {
101 : 0 : m = p->pkts[i];
102 : 0 : pkt_data = rte_pktmbuf_mtod(m, void *);
103 [ # # ]: 0 : n_bytes = read(p->params.fd, pkt_data, (size_t) p->params.mtu);
104 : :
105 [ # # ]: 0 : if (n_bytes <= 0)
106 : : break;
107 : :
108 : 0 : m->data_len = n_bytes;
109 : 0 : m->pkt_len = n_bytes;
110 : :
111 : 0 : p->stats.n_pkts++;
112 : 0 : p->stats.n_bytes += n_bytes;
113 : : }
114 : :
115 [ # # ]: 0 : for (j = i; j < p->params.burst_size; j++)
116 : 0 : rte_pktmbuf_free(p->pkts[j]);
117 : :
118 : 0 : p->n_pkts = i;
119 : 0 : p->pos = 0;
120 : :
121 [ # # ]: 0 : if (!p->n_pkts)
122 : : return 0;
123 : : }
124 : :
125 : 0 : m = p->pkts[p->pos++];
126 : 0 : pkt->handle = m;
127 : 0 : pkt->pkt = m->buf_addr;
128 : 0 : pkt->offset = m->data_off;
129 : 0 : 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 : 0 : return 1;
142 : : }
143 : :
144 : : static void
145 : 0 : reader_stats_read(void *port, struct rte_swx_port_in_stats *stats)
146 : : {
147 : : struct reader *p = port;
148 : :
149 : 0 : memcpy(stats, &p->stats, sizeof(p->stats));
150 : 0 : }
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 : 0 : 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 [ # # ]: 0 : if (!conf)
176 : : return NULL;
177 : :
178 : : /* Memory allocation. */
179 : 0 : p = calloc(1, sizeof(struct writer));
180 [ # # ]: 0 : if (!p)
181 : : return NULL;
182 : :
183 : :
184 : 0 : p->pkts = calloc(conf->burst_size, sizeof(struct rte_mbuf *));
185 [ # # ]: 0 : if (!p->pkts) {
186 : 0 : free(p);
187 : 0 : return NULL;
188 : : }
189 : :
190 : : /* Initialization. */
191 : 0 : p->params.fd = conf->fd;
192 : 0 : p->params.burst_size = conf->burst_size;
193 : :
194 : 0 : return p;
195 : : }
196 : :
197 : : static void
198 : 0 : __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 [ # # ]: 0 : for (i = 0; i < p->n_pkts; i++) {
207 : 0 : pkt = p->pkts[i];
208 : 0 : pkt_data = rte_pktmbuf_mtod(pkt, void*);
209 : 0 : n_bytes = rte_pktmbuf_data_len(pkt);
210 : :
211 : 0 : ret = write(p->params.fd, pkt_data, n_bytes);
212 [ # # ]: 0 : 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 [ # # ]: 0 : for (i = 0; i < p->n_pkts; i++)
221 : 0 : rte_pktmbuf_free(p->pkts[i]);
222 : :
223 : 0 : p->n_pkts = 0;
224 : 0 : }
225 : :
226 : : static void
227 : 0 : writer_pkt_tx(void *port, struct rte_swx_pkt *pkt)
228 : : {
229 : : struct writer *p = port;
230 : 0 : 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 : 0 : m->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len);
242 : 0 : m->pkt_len = pkt->length;
243 : 0 : m->data_off = (uint16_t)pkt->offset;
244 : :
245 : 0 : p->stats.n_pkts++;
246 : 0 : p->stats.n_bytes += pkt->length;
247 : :
248 : 0 : p->pkts[p->n_pkts++] = m;
249 [ # # ]: 0 : if (p->n_pkts == p->params.burst_size)
250 : 0 : __writer_flush(p);
251 : 0 : }
252 : :
253 : : static void
254 : 0 : writer_pkt_fast_clone_tx(void *port, struct rte_swx_pkt *pkt)
255 : : {
256 : : struct writer *p = port;
257 : 0 : struct rte_mbuf *m = pkt->handle;
258 : :
259 : : TRACE("[FD %u] Pkt %u (%u bytes at offset %u) (fast clone)\n",
260 : : (uint32_t)p->params.fd,
261 : : p->n_pkts - 1,
262 : : pkt->length,
263 : : pkt->offset);
264 : : if (TRACE_LEVEL)
265 : : rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
266 : :
267 : 0 : m->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len);
268 : 0 : m->pkt_len = pkt->length;
269 : 0 : m->data_off = (uint16_t)pkt->offset;
270 : : rte_pktmbuf_refcnt_update(m, 1);
271 : :
272 : 0 : p->stats.n_pkts++;
273 : 0 : p->stats.n_bytes += pkt->length;
274 : 0 : p->stats.n_pkts_clone++;
275 : :
276 : 0 : p->pkts[p->n_pkts++] = m;
277 [ # # ]: 0 : if (p->n_pkts == p->params.burst_size)
278 : 0 : __writer_flush(p);
279 : 0 : }
280 : :
281 : : static void
282 : 0 : writer_pkt_clone_tx(void *port, struct rte_swx_pkt *pkt, uint32_t truncation_length)
283 : : {
284 : : struct writer *p = port;
285 : 0 : struct rte_mbuf *m = pkt->handle, *m_clone;
286 : :
287 : : TRACE("[FD %u] Pkt %u (%u bytes at offset %u) (clone)\n",
288 : : (uint32_t)p->params.fd,
289 : : p->n_pkts - 1,
290 : : pkt->length,
291 : : pkt->offset);
292 : : if (TRACE_LEVEL)
293 : : rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
294 : :
295 : 0 : m->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len);
296 : 0 : m->pkt_len = pkt->length;
297 : 0 : m->data_off = (uint16_t)pkt->offset;
298 : :
299 : 0 : m_clone = rte_pktmbuf_copy(m, m->pool, 0, truncation_length);
300 [ # # ]: 0 : if (!m_clone) {
301 : 0 : p->stats.n_pkts_clone_err++;
302 : 0 : return;
303 : : }
304 : :
305 : 0 : p->stats.n_pkts++;
306 : 0 : p->stats.n_bytes += pkt->length;
307 : 0 : p->stats.n_pkts_clone++;
308 : :
309 : 0 : p->pkts[p->n_pkts++] = m_clone;
310 [ # # ]: 0 : if (p->n_pkts == p->params.burst_size)
311 : 0 : __writer_flush(p);
312 : : }
313 : :
314 : : static void
315 : 0 : writer_flush(void *port)
316 : : {
317 : : struct writer *p = port;
318 : :
319 [ # # # # ]: 0 : if (p->n_pkts)
320 : 0 : __writer_flush(p);
321 : 0 : }
322 : :
323 : : static void
324 : 0 : writer_free(void *port)
325 : : {
326 : : struct writer *p = port;
327 : :
328 [ # # ]: 0 : if (!p)
329 : : return;
330 : :
331 : : writer_flush(p);
332 : 0 : free(p->pkts);
333 : 0 : free(p);
334 : : }
335 : :
336 : : static void
337 : 0 : writer_stats_read(void *port, struct rte_swx_port_out_stats *stats)
338 : : {
339 : : struct writer *p = port;
340 : :
341 : 0 : memcpy(stats, &p->stats, sizeof(p->stats));
342 : 0 : }
343 : :
344 : : /*
345 : : * Summary of port operations
346 : : */
347 : : struct rte_swx_port_in_ops rte_swx_port_fd_reader_ops = {
348 : : .create = reader_create,
349 : : .free = reader_free,
350 : : .pkt_rx = reader_pkt_rx,
351 : : .stats_read = reader_stats_read,
352 : : };
353 : :
354 : : struct rte_swx_port_out_ops rte_swx_port_fd_writer_ops = {
355 : : .create = writer_create,
356 : : .free = writer_free,
357 : : .pkt_tx = writer_pkt_tx,
358 : : .pkt_fast_clone_tx = writer_pkt_fast_clone_tx,
359 : : .pkt_clone_tx = writer_pkt_clone_tx,
360 : : .flush = writer_flush,
361 : : .stats_read = writer_stats_read,
362 : : };
|