xref: /dpdk/lib/port/rte_swx_port_ethdev.c (revision 45b3fcbfd15348468c428b9db2691f71208a9507)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2020 Intel Corporation
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson #include <string.h>
599a2dd95SBruce Richardson #include <stdlib.h>
699a2dd95SBruce Richardson #include <stdio.h>
799a2dd95SBruce Richardson #include <stdint.h>
899a2dd95SBruce Richardson 
999a2dd95SBruce Richardson #include <rte_mbuf.h>
1099a2dd95SBruce Richardson #include <rte_ethdev.h>
1199a2dd95SBruce Richardson #include <rte_hexdump.h>
1299a2dd95SBruce Richardson 
1399a2dd95SBruce Richardson #include "rte_swx_port_ethdev.h"
1499a2dd95SBruce Richardson 
1599a2dd95SBruce Richardson #define CHECK(condition)                                                       \
1699a2dd95SBruce Richardson do {                                                                           \
1799a2dd95SBruce Richardson 	if (!(condition))                                                      \
1899a2dd95SBruce Richardson 		return NULL;                                                   \
1999a2dd95SBruce Richardson } while (0)
2099a2dd95SBruce Richardson 
2199a2dd95SBruce Richardson #ifndef TRACE_LEVEL
2299a2dd95SBruce Richardson #define TRACE_LEVEL 0
2399a2dd95SBruce Richardson #endif
2499a2dd95SBruce Richardson 
2599a2dd95SBruce Richardson #if TRACE_LEVEL
2699a2dd95SBruce Richardson #define TRACE(...) printf(__VA_ARGS__)
2799a2dd95SBruce Richardson #else
2899a2dd95SBruce Richardson #define TRACE(...)
2999a2dd95SBruce Richardson #endif
3099a2dd95SBruce Richardson 
3199a2dd95SBruce Richardson /*
3299a2dd95SBruce Richardson  * Port ETHDEV Reader
3399a2dd95SBruce Richardson  */
3499a2dd95SBruce Richardson struct reader {
3599a2dd95SBruce Richardson 	struct {
3699a2dd95SBruce Richardson 		uint16_t port_id;
3799a2dd95SBruce Richardson 		uint16_t queue_id;
3899a2dd95SBruce Richardson 		uint32_t burst_size;
3999a2dd95SBruce Richardson 	} params;
4099a2dd95SBruce Richardson 	struct rte_swx_port_in_stats stats;
4199a2dd95SBruce Richardson 	struct rte_mbuf **pkts;
4299a2dd95SBruce Richardson 	int n_pkts;
4399a2dd95SBruce Richardson 	int pos;
4499a2dd95SBruce Richardson };
4599a2dd95SBruce Richardson 
4699a2dd95SBruce Richardson static void *
reader_create(void * args)4799a2dd95SBruce Richardson reader_create(void *args)
4899a2dd95SBruce Richardson {
4999a2dd95SBruce Richardson 	struct rte_eth_dev_info info;
5099a2dd95SBruce Richardson 	struct rte_swx_port_ethdev_reader_params *params = args;
5199a2dd95SBruce Richardson 	struct reader *p;
5299a2dd95SBruce Richardson 	int status;
5399a2dd95SBruce Richardson 	uint16_t port_id;
5499a2dd95SBruce Richardson 
5599a2dd95SBruce Richardson 	/* Check input parameters. */
5699a2dd95SBruce Richardson 	CHECK(params);
5799a2dd95SBruce Richardson 
5899a2dd95SBruce Richardson 	CHECK(params->dev_name);
5999a2dd95SBruce Richardson 	status = rte_eth_dev_get_port_by_name(params->dev_name, &port_id);
6099a2dd95SBruce Richardson 	CHECK(!status);
6199a2dd95SBruce Richardson 
6299a2dd95SBruce Richardson 	status = rte_eth_dev_info_get(port_id, &info);
6399a2dd95SBruce Richardson 	CHECK((status == -ENOTSUP) || (params->queue_id < info.nb_rx_queues));
6499a2dd95SBruce Richardson 
6599a2dd95SBruce Richardson 	CHECK(params->burst_size);
6699a2dd95SBruce Richardson 
6799a2dd95SBruce Richardson 	/* Memory allocation. */
6899a2dd95SBruce Richardson 	p = calloc(1, sizeof(struct reader));
6999a2dd95SBruce Richardson 	CHECK(p);
7099a2dd95SBruce Richardson 
7199a2dd95SBruce Richardson 	p->pkts = calloc(params->burst_size, sizeof(struct rte_mbuf *));
7299a2dd95SBruce Richardson 	if (!p->pkts) {
7399a2dd95SBruce Richardson 		free(p);
7499a2dd95SBruce Richardson 		CHECK(0);
7599a2dd95SBruce Richardson 	}
7699a2dd95SBruce Richardson 
7799a2dd95SBruce Richardson 	/* Initialization. */
7899a2dd95SBruce Richardson 	p->params.port_id = port_id;
7999a2dd95SBruce Richardson 	p->params.queue_id = params->queue_id;
8099a2dd95SBruce Richardson 	p->params.burst_size = params->burst_size;
8199a2dd95SBruce Richardson 
8299a2dd95SBruce Richardson 	return p;
8399a2dd95SBruce Richardson }
8499a2dd95SBruce Richardson 
8599a2dd95SBruce Richardson static int
reader_pkt_rx(void * port,struct rte_swx_pkt * pkt)8699a2dd95SBruce Richardson reader_pkt_rx(void *port, struct rte_swx_pkt *pkt)
8799a2dd95SBruce Richardson {
8899a2dd95SBruce Richardson 	struct reader *p = port;
8999a2dd95SBruce Richardson 	struct rte_mbuf *m;
9099a2dd95SBruce Richardson 
9199a2dd95SBruce Richardson 	if (p->pos == p->n_pkts) {
9299a2dd95SBruce Richardson 		int n_pkts;
9399a2dd95SBruce Richardson 
9499a2dd95SBruce Richardson 		n_pkts = rte_eth_rx_burst(p->params.port_id,
9599a2dd95SBruce Richardson 					  p->params.queue_id,
9699a2dd95SBruce Richardson 					  p->pkts,
9799a2dd95SBruce Richardson 					  p->params.burst_size);
9899a2dd95SBruce Richardson 		if (!n_pkts) {
9999a2dd95SBruce Richardson 			p->stats.n_empty++;
10099a2dd95SBruce Richardson 			return 0;
10199a2dd95SBruce Richardson 		}
10299a2dd95SBruce Richardson 
10399a2dd95SBruce Richardson 		TRACE("[Ethdev RX port %u queue %u] %d packets in\n",
10499a2dd95SBruce Richardson 		      (uint32_t)p->params.port_id,
10599a2dd95SBruce Richardson 		      (uint32_t)p->params.queue_id,
10699a2dd95SBruce Richardson 		      n_pkts);
10799a2dd95SBruce Richardson 
10899a2dd95SBruce Richardson 		p->n_pkts = n_pkts;
10999a2dd95SBruce Richardson 		p->pos = 0;
11099a2dd95SBruce Richardson 	}
11199a2dd95SBruce Richardson 
11299a2dd95SBruce Richardson 	m = p->pkts[p->pos++];
11399a2dd95SBruce Richardson 	pkt->handle = m;
11499a2dd95SBruce Richardson 	pkt->pkt = m->buf_addr;
11599a2dd95SBruce Richardson 	pkt->offset = m->data_off;
11699a2dd95SBruce Richardson 	pkt->length = m->pkt_len;
11799a2dd95SBruce Richardson 
11899a2dd95SBruce Richardson 	TRACE("[Ethdev RX port %u queue %u] Pkt %d (%u bytes at offset %u)\n",
11999a2dd95SBruce Richardson 	      (uint32_t)p->params.port_id,
12099a2dd95SBruce Richardson 	      (uint32_t)p->params.queue_id,
12199a2dd95SBruce Richardson 	      p->pos - 1,
12299a2dd95SBruce Richardson 	      pkt->length,
12399a2dd95SBruce Richardson 	      pkt->offset);
12499a2dd95SBruce Richardson 	if (TRACE_LEVEL)
12599a2dd95SBruce Richardson 		rte_hexdump(stdout,
12699a2dd95SBruce Richardson 			    NULL,
12799a2dd95SBruce Richardson 			    &((uint8_t *)m->buf_addr)[m->data_off],
12899a2dd95SBruce Richardson 			    m->data_len);
12999a2dd95SBruce Richardson 
13099a2dd95SBruce Richardson 	p->stats.n_pkts++;
13199a2dd95SBruce Richardson 	p->stats.n_bytes += pkt->length;
13299a2dd95SBruce Richardson 
13399a2dd95SBruce Richardson 	return 1;
13499a2dd95SBruce Richardson }
13599a2dd95SBruce Richardson 
13699a2dd95SBruce Richardson static void
reader_free(void * port)13799a2dd95SBruce Richardson reader_free(void *port)
13899a2dd95SBruce Richardson {
13999a2dd95SBruce Richardson 	struct reader *p = port;
14099a2dd95SBruce Richardson 	int i;
14199a2dd95SBruce Richardson 
14299a2dd95SBruce Richardson 	if (!p)
14399a2dd95SBruce Richardson 		return;
14499a2dd95SBruce Richardson 
14599a2dd95SBruce Richardson 	for (i = 0; i < p->n_pkts; i++) {
14699a2dd95SBruce Richardson 		struct rte_mbuf *pkt = p->pkts[i];
14799a2dd95SBruce Richardson 
14899a2dd95SBruce Richardson 		rte_pktmbuf_free(pkt);
14999a2dd95SBruce Richardson 	}
15099a2dd95SBruce Richardson 
15199a2dd95SBruce Richardson 	free(p->pkts);
15299a2dd95SBruce Richardson 	free(p);
15399a2dd95SBruce Richardson }
15499a2dd95SBruce Richardson 
15599a2dd95SBruce Richardson static void
reader_stats_read(void * port,struct rte_swx_port_in_stats * stats)15699a2dd95SBruce Richardson reader_stats_read(void *port, struct rte_swx_port_in_stats *stats)
15799a2dd95SBruce Richardson {
15899a2dd95SBruce Richardson 	struct reader *p = port;
15999a2dd95SBruce Richardson 
16099a2dd95SBruce Richardson 	memcpy(stats, &p->stats, sizeof(p->stats));
16199a2dd95SBruce Richardson }
16299a2dd95SBruce Richardson 
16399a2dd95SBruce Richardson /*
16499a2dd95SBruce Richardson  * Port ETHDEV Writer
16599a2dd95SBruce Richardson  */
16699a2dd95SBruce Richardson struct writer {
16799a2dd95SBruce Richardson 	struct {
16899a2dd95SBruce Richardson 		uint16_t port_id;
16999a2dd95SBruce Richardson 		uint16_t queue_id;
17099a2dd95SBruce Richardson 		uint32_t burst_size;
17199a2dd95SBruce Richardson 	} params;
17299a2dd95SBruce Richardson 	struct rte_swx_port_out_stats stats;
17399a2dd95SBruce Richardson 
17499a2dd95SBruce Richardson 	struct rte_mbuf **pkts;
17599a2dd95SBruce Richardson 	int n_pkts;
176f317fff0SCristian Dumitrescu 	uint32_t n_bytes;
177*45b3fcbfSCristian Dumitrescu 	int flush_flag;
17899a2dd95SBruce Richardson };
17999a2dd95SBruce Richardson 
18099a2dd95SBruce Richardson static void *
writer_create(void * args)18199a2dd95SBruce Richardson writer_create(void *args)
18299a2dd95SBruce Richardson {
18399a2dd95SBruce Richardson 	struct rte_eth_dev_info info;
18499a2dd95SBruce Richardson 	struct rte_swx_port_ethdev_writer_params *params = args;
18599a2dd95SBruce Richardson 	struct writer *p;
18699a2dd95SBruce Richardson 	int status;
18799a2dd95SBruce Richardson 	uint16_t port_id;
18899a2dd95SBruce Richardson 
18999a2dd95SBruce Richardson 	/* Check input parameters. */
19099a2dd95SBruce Richardson 	CHECK(params);
19199a2dd95SBruce Richardson 
19299a2dd95SBruce Richardson 	CHECK(params->dev_name);
19399a2dd95SBruce Richardson 	status = rte_eth_dev_get_port_by_name(params->dev_name, &port_id);
19499a2dd95SBruce Richardson 	CHECK(!status);
19599a2dd95SBruce Richardson 
19699a2dd95SBruce Richardson 	status = rte_eth_dev_info_get(port_id, &info);
19799a2dd95SBruce Richardson 	CHECK((status == -ENOTSUP) || (params->queue_id < info.nb_tx_queues));
19899a2dd95SBruce Richardson 
19999a2dd95SBruce Richardson 	CHECK(params->burst_size);
20099a2dd95SBruce Richardson 
20199a2dd95SBruce Richardson 	/* Memory allocation. */
20299a2dd95SBruce Richardson 	p = calloc(1, sizeof(struct writer));
20399a2dd95SBruce Richardson 	CHECK(p);
20499a2dd95SBruce Richardson 
20599a2dd95SBruce Richardson 	p->pkts = calloc(params->burst_size, sizeof(struct rte_mbuf *));
20699a2dd95SBruce Richardson 	if (!p->pkts) {
20799a2dd95SBruce Richardson 		free(p);
20899a2dd95SBruce Richardson 		CHECK(0);
20999a2dd95SBruce Richardson 	}
21099a2dd95SBruce Richardson 
21199a2dd95SBruce Richardson 	/* Initialization. */
21299a2dd95SBruce Richardson 	p->params.port_id = port_id;
21399a2dd95SBruce Richardson 	p->params.queue_id = params->queue_id;
21499a2dd95SBruce Richardson 	p->params.burst_size = params->burst_size;
21599a2dd95SBruce Richardson 
21699a2dd95SBruce Richardson 	return p;
21799a2dd95SBruce Richardson }
21899a2dd95SBruce Richardson 
219f317fff0SCristian Dumitrescu static inline void
__writer_flush(struct writer * p)22099a2dd95SBruce Richardson __writer_flush(struct writer *p)
22199a2dd95SBruce Richardson {
222f317fff0SCristian Dumitrescu 	struct rte_mbuf **pkts = p->pkts;
223f317fff0SCristian Dumitrescu 	uint64_t n_pkts_total = p->stats.n_pkts;
224f317fff0SCristian Dumitrescu 	uint64_t n_bytes_total = p->stats.n_bytes;
225f317fff0SCristian Dumitrescu 	uint64_t n_pkts_drop_total = p->stats.n_pkts_drop;
226f317fff0SCristian Dumitrescu 	uint64_t n_bytes_drop_total = p->stats.n_bytes_drop;
227f317fff0SCristian Dumitrescu 	int n_pkts = p->n_pkts, n_pkts_drop, n_pkts_tx;
228f317fff0SCristian Dumitrescu 	uint32_t n_bytes = p->n_bytes, n_bytes_drop = 0;
22999a2dd95SBruce Richardson 
230f317fff0SCristian Dumitrescu 	/* Packet TX. */
231f317fff0SCristian Dumitrescu 	n_pkts_tx = rte_eth_tx_burst(p->params.port_id,
23299a2dd95SBruce Richardson 				     p->params.queue_id,
233f317fff0SCristian Dumitrescu 				     pkts,
23499a2dd95SBruce Richardson 				     n_pkts);
23599a2dd95SBruce Richardson 
236f317fff0SCristian Dumitrescu 	/* Packet drop. */
237f317fff0SCristian Dumitrescu 	n_pkts_drop = n_pkts - n_pkts_tx;
238f317fff0SCristian Dumitrescu 
239f317fff0SCristian Dumitrescu 	for ( ; n_pkts_tx < n_pkts; n_pkts_tx++) {
240f317fff0SCristian Dumitrescu 		struct rte_mbuf *m = pkts[n_pkts_tx];
241f317fff0SCristian Dumitrescu 
242f317fff0SCristian Dumitrescu 		n_bytes_drop += m->pkt_len;
243f317fff0SCristian Dumitrescu 		rte_pktmbuf_free(m);
24499a2dd95SBruce Richardson 	}
24599a2dd95SBruce Richardson 
246f317fff0SCristian Dumitrescu 	/* Port update. */
247f317fff0SCristian Dumitrescu 	p->stats.n_pkts = n_pkts_total + n_pkts - n_pkts_drop;
248f317fff0SCristian Dumitrescu 	p->stats.n_bytes = n_bytes_total + n_bytes - n_bytes_drop;
249f317fff0SCristian Dumitrescu 	p->stats.n_pkts_drop = n_pkts_drop_total + n_pkts_drop;
250f317fff0SCristian Dumitrescu 	p->stats.n_bytes_drop = n_bytes_drop_total + n_bytes_drop;
25199a2dd95SBruce Richardson 	p->n_pkts = 0;
252f317fff0SCristian Dumitrescu 	p->n_bytes = 0;
253*45b3fcbfSCristian Dumitrescu 	p->flush_flag = 0;
254f317fff0SCristian Dumitrescu 
255f317fff0SCristian Dumitrescu 	TRACE("[Ethdev TX port %u queue %u] Buffered packets flushed: %d out, %d dropped\n",
256f317fff0SCristian Dumitrescu 	      (uint32_t)p->params.port_id,
257f317fff0SCristian Dumitrescu 	      (uint32_t)p->params.queue_id,
258f317fff0SCristian Dumitrescu 	      n_pkts - n_pkts_drop,
259f317fff0SCristian Dumitrescu 	      n_pkts_drop);
26099a2dd95SBruce Richardson }
26199a2dd95SBruce Richardson 
26299a2dd95SBruce Richardson static void
writer_pkt_tx(void * port,struct rte_swx_pkt * pkt)26399a2dd95SBruce Richardson writer_pkt_tx(void *port, struct rte_swx_pkt *pkt)
26499a2dd95SBruce Richardson {
26599a2dd95SBruce Richardson 	struct writer *p = port;
266f317fff0SCristian Dumitrescu 	int n_pkts = p->n_pkts;
267f317fff0SCristian Dumitrescu 	uint32_t n_bytes = p->n_bytes;
26899a2dd95SBruce Richardson 	struct rte_mbuf *m = pkt->handle;
269f317fff0SCristian Dumitrescu 	uint32_t pkt_length = pkt->length;
27099a2dd95SBruce Richardson 
27199a2dd95SBruce Richardson 	TRACE("[Ethdev TX port %u queue %u] Pkt %d (%u bytes at offset %u)\n",
27299a2dd95SBruce Richardson 	      (uint32_t)p->params.port_id,
27399a2dd95SBruce Richardson 	      (uint32_t)p->params.queue_id,
27499a2dd95SBruce Richardson 	      p->n_pkts - 1,
27599a2dd95SBruce Richardson 	      pkt->length,
27699a2dd95SBruce Richardson 	      pkt->offset);
27799a2dd95SBruce Richardson 	if (TRACE_LEVEL)
27899a2dd95SBruce Richardson 		rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
27999a2dd95SBruce Richardson 
280f317fff0SCristian Dumitrescu 	m->data_len = (uint16_t)(pkt_length + m->data_len - m->pkt_len);
281f317fff0SCristian Dumitrescu 	m->pkt_len = pkt_length;
28299a2dd95SBruce Richardson 	m->data_off = (uint16_t)pkt->offset;
28399a2dd95SBruce Richardson 
284f317fff0SCristian Dumitrescu 	p->pkts[n_pkts++] = m;
285f317fff0SCristian Dumitrescu 	p->n_pkts = n_pkts;
286f317fff0SCristian Dumitrescu 	p->n_bytes = n_bytes + pkt_length;
28799a2dd95SBruce Richardson 
288f317fff0SCristian Dumitrescu 	if (n_pkts == (int)p->params.burst_size)
28999a2dd95SBruce Richardson 		__writer_flush(p);
29099a2dd95SBruce Richardson }
29199a2dd95SBruce Richardson 
29299a2dd95SBruce Richardson static void
writer_pkt_fast_clone_tx(void * port,struct rte_swx_pkt * pkt)293b94eb6cdSCristian Dumitrescu writer_pkt_fast_clone_tx(void *port, struct rte_swx_pkt *pkt)
294b94eb6cdSCristian Dumitrescu {
295b94eb6cdSCristian Dumitrescu 	struct writer *p = port;
296f317fff0SCristian Dumitrescu 	int n_pkts = p->n_pkts;
297f317fff0SCristian Dumitrescu 	uint32_t n_bytes = p->n_bytes;
298f317fff0SCristian Dumitrescu 	uint64_t n_pkts_clone = p->stats.n_pkts_clone;
299b94eb6cdSCristian Dumitrescu 	struct rte_mbuf *m = pkt->handle;
300f317fff0SCristian Dumitrescu 	uint32_t pkt_length = pkt->length;
301b94eb6cdSCristian Dumitrescu 
302b94eb6cdSCristian Dumitrescu 	TRACE("[Ethdev TX port %u queue %u] Pkt %d (%u bytes at offset %u) (fast clone)\n",
303b94eb6cdSCristian Dumitrescu 	      (uint32_t)p->params.port_id,
304b94eb6cdSCristian Dumitrescu 	      (uint32_t)p->params.queue_id,
305b94eb6cdSCristian Dumitrescu 	      p->n_pkts - 1,
306b94eb6cdSCristian Dumitrescu 	      pkt->length,
307b94eb6cdSCristian Dumitrescu 	      pkt->offset);
308b94eb6cdSCristian Dumitrescu 	if (TRACE_LEVEL)
309b94eb6cdSCristian Dumitrescu 		rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
310b94eb6cdSCristian Dumitrescu 
311f317fff0SCristian Dumitrescu 	m->data_len = (uint16_t)(pkt_length + m->data_len - m->pkt_len);
312f317fff0SCristian Dumitrescu 	m->pkt_len = pkt_length;
313b94eb6cdSCristian Dumitrescu 	m->data_off = (uint16_t)pkt->offset;
314b94eb6cdSCristian Dumitrescu 	rte_pktmbuf_refcnt_update(m, 1);
315b94eb6cdSCristian Dumitrescu 
316f317fff0SCristian Dumitrescu 	p->pkts[n_pkts++] = m;
317f317fff0SCristian Dumitrescu 	p->n_pkts = n_pkts;
318f317fff0SCristian Dumitrescu 	p->n_bytes = n_bytes + pkt_length;
319f317fff0SCristian Dumitrescu 	p->stats.n_pkts_clone = n_pkts_clone + 1;
320b94eb6cdSCristian Dumitrescu 
321f317fff0SCristian Dumitrescu 	if (n_pkts == (int)p->params.burst_size)
322b94eb6cdSCristian Dumitrescu 		__writer_flush(p);
323b94eb6cdSCristian Dumitrescu }
324b94eb6cdSCristian Dumitrescu 
325b94eb6cdSCristian Dumitrescu static void
writer_pkt_clone_tx(void * port,struct rte_swx_pkt * pkt,uint32_t truncation_length)326b94eb6cdSCristian Dumitrescu writer_pkt_clone_tx(void *port, struct rte_swx_pkt *pkt, uint32_t truncation_length)
327b94eb6cdSCristian Dumitrescu {
328b94eb6cdSCristian Dumitrescu 	struct writer *p = port;
329f317fff0SCristian Dumitrescu 	int n_pkts = p->n_pkts;
330f317fff0SCristian Dumitrescu 	uint32_t n_bytes = p->n_bytes;
331f317fff0SCristian Dumitrescu 	uint64_t n_pkts_clone = p->stats.n_pkts_clone;
332b94eb6cdSCristian Dumitrescu 	struct rte_mbuf *m = pkt->handle, *m_clone;
333f317fff0SCristian Dumitrescu 	uint32_t pkt_length = pkt->length;
334b94eb6cdSCristian Dumitrescu 
335b94eb6cdSCristian Dumitrescu 	TRACE("[Ethdev TX port %u queue %u] Pkt %d (%u bytes at offset %u) (clone)\n",
336b94eb6cdSCristian Dumitrescu 	      (uint32_t)p->params.port_id,
337b94eb6cdSCristian Dumitrescu 	      (uint32_t)p->params.queue_id,
338b94eb6cdSCristian Dumitrescu 	      p->n_pkts - 1,
339b94eb6cdSCristian Dumitrescu 	      pkt->length,
340b94eb6cdSCristian Dumitrescu 	      pkt->offset);
341b94eb6cdSCristian Dumitrescu 	if (TRACE_LEVEL)
342b94eb6cdSCristian Dumitrescu 		rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
343b94eb6cdSCristian Dumitrescu 
344f317fff0SCristian Dumitrescu 	m->data_len = (uint16_t)(pkt_length + m->data_len - m->pkt_len);
345f317fff0SCristian Dumitrescu 	m->pkt_len = pkt_length;
346b94eb6cdSCristian Dumitrescu 	m->data_off = (uint16_t)pkt->offset;
347b94eb6cdSCristian Dumitrescu 
348b94eb6cdSCristian Dumitrescu 	m_clone = rte_pktmbuf_copy(m, m->pool, 0, truncation_length);
349b94eb6cdSCristian Dumitrescu 	if (!m_clone) {
350b94eb6cdSCristian Dumitrescu 		p->stats.n_pkts_clone_err++;
351b94eb6cdSCristian Dumitrescu 		return;
352b94eb6cdSCristian Dumitrescu 	}
353b94eb6cdSCristian Dumitrescu 
354f317fff0SCristian Dumitrescu 	p->pkts[n_pkts++] = m_clone;
355f317fff0SCristian Dumitrescu 	p->n_pkts = n_pkts;
356f317fff0SCristian Dumitrescu 	p->n_bytes = n_bytes + pkt_length;
357f317fff0SCristian Dumitrescu 	p->stats.n_pkts_clone = n_pkts_clone + 1;
358b94eb6cdSCristian Dumitrescu 
359f317fff0SCristian Dumitrescu 	if (n_pkts == (int)p->params.burst_size)
360b94eb6cdSCristian Dumitrescu 		__writer_flush(p);
361b94eb6cdSCristian Dumitrescu }
362b94eb6cdSCristian Dumitrescu 
363b94eb6cdSCristian Dumitrescu static void
writer_flush(void * port)36499a2dd95SBruce Richardson writer_flush(void *port)
36599a2dd95SBruce Richardson {
36699a2dd95SBruce Richardson 	struct writer *p = port;
36799a2dd95SBruce Richardson 
368*45b3fcbfSCristian Dumitrescu 	if (p->n_pkts && p->flush_flag)
36999a2dd95SBruce Richardson 		__writer_flush(p);
370*45b3fcbfSCristian Dumitrescu 
371*45b3fcbfSCristian Dumitrescu 	p->flush_flag = 1;
37299a2dd95SBruce Richardson }
37399a2dd95SBruce Richardson 
37499a2dd95SBruce Richardson static void
writer_free(void * port)37599a2dd95SBruce Richardson writer_free(void *port)
37699a2dd95SBruce Richardson {
37799a2dd95SBruce Richardson 	struct writer *p = port;
3787150064dSCristian Dumitrescu 	int i;
37999a2dd95SBruce Richardson 
38099a2dd95SBruce Richardson 	if (!p)
38199a2dd95SBruce Richardson 		return;
38299a2dd95SBruce Richardson 
3837150064dSCristian Dumitrescu 	for (i = 0; i < p->n_pkts; i++) {
3847150064dSCristian Dumitrescu 		struct rte_mbuf *m = p->pkts[i];
3857150064dSCristian Dumitrescu 
3867150064dSCristian Dumitrescu 		rte_pktmbuf_free(m);
3877150064dSCristian Dumitrescu 	}
3887150064dSCristian Dumitrescu 
38999a2dd95SBruce Richardson 	free(p->pkts);
39099a2dd95SBruce Richardson 	free(port);
39199a2dd95SBruce Richardson }
39299a2dd95SBruce Richardson 
39399a2dd95SBruce Richardson static void
writer_stats_read(void * port,struct rte_swx_port_out_stats * stats)39499a2dd95SBruce Richardson writer_stats_read(void *port, struct rte_swx_port_out_stats *stats)
39599a2dd95SBruce Richardson {
39699a2dd95SBruce Richardson 	struct writer *p = port;
39799a2dd95SBruce Richardson 
39899a2dd95SBruce Richardson 	memcpy(stats, &p->stats, sizeof(p->stats));
39999a2dd95SBruce Richardson }
40099a2dd95SBruce Richardson 
40199a2dd95SBruce Richardson /*
40299a2dd95SBruce Richardson  * Summary of port operations
40399a2dd95SBruce Richardson  */
40499a2dd95SBruce Richardson struct rte_swx_port_in_ops rte_swx_port_ethdev_reader_ops = {
40599a2dd95SBruce Richardson 	.create = reader_create,
40699a2dd95SBruce Richardson 	.free = reader_free,
40799a2dd95SBruce Richardson 	.pkt_rx = reader_pkt_rx,
40899a2dd95SBruce Richardson 	.stats_read = reader_stats_read,
40999a2dd95SBruce Richardson };
41099a2dd95SBruce Richardson 
41199a2dd95SBruce Richardson struct rte_swx_port_out_ops rte_swx_port_ethdev_writer_ops = {
41299a2dd95SBruce Richardson 	.create = writer_create,
41399a2dd95SBruce Richardson 	.free = writer_free,
41499a2dd95SBruce Richardson 	.pkt_tx = writer_pkt_tx,
415b94eb6cdSCristian Dumitrescu 	.pkt_fast_clone_tx = writer_pkt_fast_clone_tx,
416b94eb6cdSCristian Dumitrescu 	.pkt_clone_tx = writer_pkt_clone_tx,
41799a2dd95SBruce Richardson 	.flush = writer_flush,
41899a2dd95SBruce Richardson 	.stats_read = writer_stats_read,
41999a2dd95SBruce Richardson };
420