xref: /dpdk/lib/port/rte_swx_port_fd.c (revision 72b452c5f2599f970f47fd17d3e8e5d60bfebe7a)
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 *
reader_create(void * args)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
reader_free(void * port)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
reader_pkt_rx(void * port,struct rte_swx_pkt * pkt)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
reader_stats_read(void * port,struct rte_swx_port_in_stats * stats)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 *
writer_create(void * args)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
__writer_flush(struct writer * p)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
writer_pkt_tx(void * port,struct rte_swx_pkt * pkt)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->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len);
242 	m->pkt_len = 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
writer_pkt_fast_clone_tx(void * port,struct rte_swx_pkt * pkt)254 writer_pkt_fast_clone_tx(void *port, struct rte_swx_pkt *pkt)
255 {
256 	struct writer *p = port;
257 	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 	m->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len);
268 	m->pkt_len = pkt->length;
269 	m->data_off = (uint16_t)pkt->offset;
270 	rte_pktmbuf_refcnt_update(m, 1);
271 
272 	p->stats.n_pkts++;
273 	p->stats.n_bytes += pkt->length;
274 	p->stats.n_pkts_clone++;
275 
276 	p->pkts[p->n_pkts++] = m;
277 	if (p->n_pkts == p->params.burst_size)
278 		__writer_flush(p);
279 }
280 
281 static void
writer_pkt_clone_tx(void * port,struct rte_swx_pkt * pkt,uint32_t truncation_length)282 writer_pkt_clone_tx(void *port, struct rte_swx_pkt *pkt, uint32_t truncation_length)
283 {
284 	struct writer *p = port;
285 	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 	m->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len);
296 	m->pkt_len = pkt->length;
297 	m->data_off = (uint16_t)pkt->offset;
298 
299 	m_clone = rte_pktmbuf_copy(m, m->pool, 0, truncation_length);
300 	if (!m_clone) {
301 		p->stats.n_pkts_clone_err++;
302 		return;
303 	}
304 
305 	p->stats.n_pkts++;
306 	p->stats.n_bytes += pkt->length;
307 	p->stats.n_pkts_clone++;
308 
309 	p->pkts[p->n_pkts++] = m_clone;
310 	if (p->n_pkts == p->params.burst_size)
311 		__writer_flush(p);
312 }
313 
314 static void
writer_flush(void * port)315 writer_flush(void *port)
316 {
317 	struct writer *p = port;
318 
319 	if (p->n_pkts)
320 		__writer_flush(p);
321 }
322 
323 static void
writer_free(void * port)324 writer_free(void *port)
325 {
326 	struct writer *p = port;
327 
328 	if (!p)
329 		return;
330 
331 	writer_flush(p);
332 	free(p->pkts);
333 	free(p);
334 }
335 
336 static void
writer_stats_read(void * port,struct rte_swx_port_out_stats * stats)337 writer_stats_read(void *port, struct rte_swx_port_out_stats *stats)
338 {
339 	struct writer *p = port;
340 
341 	memcpy(stats, &p->stats, sizeof(p->stats));
342 }
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 };
363