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