199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson * Copyright(c) 2020 Intel Corporation
399a2dd95SBruce Richardson */
499a2dd95SBruce Richardson #include <stdint.h>
599a2dd95SBruce Richardson #include <stdlib.h>
699a2dd95SBruce Richardson #include <string.h>
799a2dd95SBruce Richardson #ifdef RTE_PORT_PCAP
899a2dd95SBruce Richardson #include <pcap.h>
999a2dd95SBruce Richardson #endif
1099a2dd95SBruce Richardson #include <sys/time.h>
1199a2dd95SBruce Richardson
1299a2dd95SBruce Richardson #include <rte_common.h>
1399a2dd95SBruce Richardson #include <rte_mbuf.h>
1499a2dd95SBruce Richardson #include <rte_hexdump.h>
1599a2dd95SBruce Richardson
1699a2dd95SBruce Richardson #include "rte_swx_port_source_sink.h"
1799a2dd95SBruce Richardson
1899a2dd95SBruce Richardson #define CHECK(condition) \
1999a2dd95SBruce Richardson do { \
2099a2dd95SBruce Richardson if (!(condition)) \
2199a2dd95SBruce Richardson return NULL; \
2299a2dd95SBruce Richardson } while (0)
2399a2dd95SBruce Richardson
2499a2dd95SBruce Richardson #ifndef TRACE_LEVEL
2599a2dd95SBruce Richardson #define TRACE_LEVEL 0
2699a2dd95SBruce Richardson #endif
2799a2dd95SBruce Richardson
2899a2dd95SBruce Richardson #if TRACE_LEVEL
2999a2dd95SBruce Richardson #define TRACE(...) printf(__VA_ARGS__)
3099a2dd95SBruce Richardson #else
3199a2dd95SBruce Richardson #define TRACE(...)
3299a2dd95SBruce Richardson #endif
3399a2dd95SBruce Richardson
3499a2dd95SBruce Richardson /*
3599a2dd95SBruce Richardson * Port SOURCE
3699a2dd95SBruce Richardson */
3799a2dd95SBruce Richardson #ifdef RTE_PORT_PCAP
3899a2dd95SBruce Richardson
3999a2dd95SBruce Richardson struct source {
4099a2dd95SBruce Richardson struct {
4199a2dd95SBruce Richardson struct rte_mempool *pool;
420317c452SYogesh Jangra uint64_t n_loops;
4399a2dd95SBruce Richardson } params;
4499a2dd95SBruce Richardson struct rte_swx_port_in_stats stats;
4599a2dd95SBruce Richardson struct rte_mbuf **pkts;
4699a2dd95SBruce Richardson uint32_t n_pkts;
4799a2dd95SBruce Richardson uint32_t pos;
4899a2dd95SBruce Richardson };
4999a2dd95SBruce Richardson
5099a2dd95SBruce Richardson static void
source_free(void * port)5199a2dd95SBruce Richardson source_free(void *port)
5299a2dd95SBruce Richardson {
5399a2dd95SBruce Richardson struct source *p = port;
5499a2dd95SBruce Richardson uint32_t i;
5599a2dd95SBruce Richardson
5699a2dd95SBruce Richardson if (!p)
5799a2dd95SBruce Richardson return;
5899a2dd95SBruce Richardson
5999a2dd95SBruce Richardson for (i = 0; i < p->n_pkts; i++)
6099a2dd95SBruce Richardson rte_pktmbuf_free(p->pkts[i]);
6199a2dd95SBruce Richardson
6299a2dd95SBruce Richardson free(p->pkts);
6399a2dd95SBruce Richardson
6499a2dd95SBruce Richardson free(p);
6599a2dd95SBruce Richardson }
6699a2dd95SBruce Richardson
6799a2dd95SBruce Richardson static void *
source_create(void * args)6899a2dd95SBruce Richardson source_create(void *args)
6999a2dd95SBruce Richardson {
7099a2dd95SBruce Richardson char pcap_errbuf[PCAP_ERRBUF_SIZE];
7199a2dd95SBruce Richardson struct rte_swx_port_source_params *params = args;
7299a2dd95SBruce Richardson struct source *p = NULL;
7399a2dd95SBruce Richardson pcap_t *f = NULL;
7499a2dd95SBruce Richardson uint32_t n_pkts_max, i;
7599a2dd95SBruce Richardson
7699a2dd95SBruce Richardson /* Check input arguments. */
7799a2dd95SBruce Richardson CHECK(params);
7899a2dd95SBruce Richardson CHECK(params->pool);
7999a2dd95SBruce Richardson CHECK(params->file_name && params->file_name[0]);
8099a2dd95SBruce Richardson n_pkts_max = params->n_pkts_max ?
8199a2dd95SBruce Richardson params->n_pkts_max :
8299a2dd95SBruce Richardson RTE_SWX_PORT_SOURCE_PKTS_MAX;
8399a2dd95SBruce Richardson
8499a2dd95SBruce Richardson /* Resource allocation. */
8599a2dd95SBruce Richardson f = pcap_open_offline(params->file_name, pcap_errbuf);
8699a2dd95SBruce Richardson if (!f)
8799a2dd95SBruce Richardson goto error;
8899a2dd95SBruce Richardson
8999a2dd95SBruce Richardson p = calloc(1, sizeof(struct source));
9099a2dd95SBruce Richardson if (!p)
9199a2dd95SBruce Richardson goto error;
9299a2dd95SBruce Richardson
9399a2dd95SBruce Richardson p->pkts = calloc(n_pkts_max, sizeof(struct rte_mbuf *));
9499a2dd95SBruce Richardson if (!p->pkts)
9599a2dd95SBruce Richardson goto error;
9699a2dd95SBruce Richardson
9799a2dd95SBruce Richardson /* Initialization. */
9899a2dd95SBruce Richardson p->params.pool = params->pool;
9999a2dd95SBruce Richardson
1000317c452SYogesh Jangra p->params.n_loops = params->n_loops ? params->n_loops : UINT64_MAX;
1010317c452SYogesh Jangra
10299a2dd95SBruce Richardson /* PCAP file. */
10399a2dd95SBruce Richardson for (i = 0; i < n_pkts_max; i++) {
10499a2dd95SBruce Richardson struct pcap_pkthdr pcap_pkthdr;
10599a2dd95SBruce Richardson const uint8_t *pcap_pktdata;
10699a2dd95SBruce Richardson struct rte_mbuf *m;
10799a2dd95SBruce Richardson uint8_t *m_data;
10899a2dd95SBruce Richardson
10999a2dd95SBruce Richardson /* Read new packet from PCAP file. */
11099a2dd95SBruce Richardson pcap_pktdata = pcap_next(f, &pcap_pkthdr);
11199a2dd95SBruce Richardson if (!pcap_pktdata)
11299a2dd95SBruce Richardson break;
11399a2dd95SBruce Richardson
11499a2dd95SBruce Richardson /* Allocate new buffer from pool. */
11599a2dd95SBruce Richardson m = rte_pktmbuf_alloc(params->pool);
11699a2dd95SBruce Richardson if (!m)
11799a2dd95SBruce Richardson goto error;
11899a2dd95SBruce Richardson m_data = rte_pktmbuf_mtod(m, uint8_t *);
11999a2dd95SBruce Richardson
12099a2dd95SBruce Richardson rte_memcpy(m_data, pcap_pktdata, pcap_pkthdr.caplen);
12199a2dd95SBruce Richardson m->data_len = pcap_pkthdr.caplen;
12299a2dd95SBruce Richardson m->pkt_len = pcap_pkthdr.caplen;
12399a2dd95SBruce Richardson
12499a2dd95SBruce Richardson p->pkts[p->n_pkts] = m;
12599a2dd95SBruce Richardson p->n_pkts++;
12699a2dd95SBruce Richardson }
12799a2dd95SBruce Richardson
12899a2dd95SBruce Richardson if (!p->n_pkts)
12999a2dd95SBruce Richardson goto error;
13099a2dd95SBruce Richardson
13199a2dd95SBruce Richardson pcap_close(f);
13299a2dd95SBruce Richardson return p;
13399a2dd95SBruce Richardson
13499a2dd95SBruce Richardson error:
13599a2dd95SBruce Richardson source_free(p);
13699a2dd95SBruce Richardson if (f)
13799a2dd95SBruce Richardson pcap_close(f);
13899a2dd95SBruce Richardson return NULL;
13999a2dd95SBruce Richardson }
14099a2dd95SBruce Richardson
14199a2dd95SBruce Richardson static int
source_pkt_rx(void * port,struct rte_swx_pkt * pkt)14299a2dd95SBruce Richardson source_pkt_rx(void *port, struct rte_swx_pkt *pkt)
14399a2dd95SBruce Richardson {
14499a2dd95SBruce Richardson struct source *p = port;
14599a2dd95SBruce Richardson struct rte_mbuf *m_dst, *m_src;
14699a2dd95SBruce Richardson uint8_t *m_dst_data, *m_src_data;
14799a2dd95SBruce Richardson
1480317c452SYogesh Jangra if (!p->params.n_loops)
1490317c452SYogesh Jangra return 0;
15099a2dd95SBruce Richardson /* m_src identification. */
15199a2dd95SBruce Richardson m_src = p->pkts[p->pos];
15299a2dd95SBruce Richardson m_src_data = rte_pktmbuf_mtod(m_src, uint8_t *);
15399a2dd95SBruce Richardson
15499a2dd95SBruce Richardson /* m_dst allocation from pool. */
15599a2dd95SBruce Richardson m_dst = rte_pktmbuf_alloc(p->params.pool);
15699a2dd95SBruce Richardson if (!m_dst)
15799a2dd95SBruce Richardson return 0;
15899a2dd95SBruce Richardson
15999a2dd95SBruce Richardson /* m_dst initialization. */
16099a2dd95SBruce Richardson m_dst->data_len = m_src->data_len;
16199a2dd95SBruce Richardson m_dst->pkt_len = m_src->pkt_len;
16299a2dd95SBruce Richardson m_dst->data_off = m_src->data_off;
16399a2dd95SBruce Richardson
16499a2dd95SBruce Richardson m_dst_data = rte_pktmbuf_mtod(m_dst, uint8_t *);
16599a2dd95SBruce Richardson rte_memcpy(m_dst_data, m_src_data, m_src->data_len);
16699a2dd95SBruce Richardson
16799a2dd95SBruce Richardson /* pkt initialization. */
16899a2dd95SBruce Richardson pkt->handle = m_dst;
16999a2dd95SBruce Richardson pkt->pkt = m_dst->buf_addr;
17099a2dd95SBruce Richardson pkt->offset = m_dst->data_off;
17199a2dd95SBruce Richardson pkt->length = m_dst->pkt_len;
17299a2dd95SBruce Richardson
17399a2dd95SBruce Richardson TRACE("[Source port] Pkt RX (%u bytes at offset %u)\n",
17499a2dd95SBruce Richardson pkt->length,
17599a2dd95SBruce Richardson pkt->offset);
17699a2dd95SBruce Richardson if (TRACE_LEVEL)
17799a2dd95SBruce Richardson rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
17899a2dd95SBruce Richardson
17999a2dd95SBruce Richardson /* port stats update. */
18099a2dd95SBruce Richardson p->stats.n_pkts++;
18199a2dd95SBruce Richardson p->stats.n_bytes += pkt->length;
18299a2dd95SBruce Richardson
18399a2dd95SBruce Richardson /* m_src next. */
18499a2dd95SBruce Richardson p->pos++;
1850317c452SYogesh Jangra if (p->pos == p->n_pkts) {
18699a2dd95SBruce Richardson p->pos = 0;
1870317c452SYogesh Jangra p->params.n_loops--;
1880317c452SYogesh Jangra }
18999a2dd95SBruce Richardson
19099a2dd95SBruce Richardson return 1;
19199a2dd95SBruce Richardson }
19299a2dd95SBruce Richardson
19399a2dd95SBruce Richardson static void
source_stats_read(void * port,struct rte_swx_port_in_stats * stats)19499a2dd95SBruce Richardson source_stats_read(void *port, struct rte_swx_port_in_stats *stats)
19599a2dd95SBruce Richardson {
19699a2dd95SBruce Richardson struct source *p = port;
19799a2dd95SBruce Richardson
19899a2dd95SBruce Richardson if (!p || !stats)
19999a2dd95SBruce Richardson return;
20099a2dd95SBruce Richardson
20199a2dd95SBruce Richardson memcpy(stats, &p->stats, sizeof(p->stats));
20299a2dd95SBruce Richardson }
20399a2dd95SBruce Richardson
20499a2dd95SBruce Richardson struct rte_swx_port_in_ops rte_swx_port_source_ops = {
20599a2dd95SBruce Richardson .create = source_create,
20699a2dd95SBruce Richardson .free = source_free,
20799a2dd95SBruce Richardson .pkt_rx = source_pkt_rx,
20899a2dd95SBruce Richardson .stats_read = source_stats_read,
20999a2dd95SBruce Richardson };
21099a2dd95SBruce Richardson
21199a2dd95SBruce Richardson #else
21299a2dd95SBruce Richardson
21399a2dd95SBruce Richardson struct rte_swx_port_in_ops rte_swx_port_source_ops = {
21499a2dd95SBruce Richardson .create = NULL,
21599a2dd95SBruce Richardson .free = NULL,
21699a2dd95SBruce Richardson .pkt_rx = NULL,
21799a2dd95SBruce Richardson .stats_read = NULL,
21899a2dd95SBruce Richardson };
21999a2dd95SBruce Richardson
22099a2dd95SBruce Richardson #endif
22199a2dd95SBruce Richardson
22299a2dd95SBruce Richardson /*
22399a2dd95SBruce Richardson * Port SINK
22499a2dd95SBruce Richardson */
22599a2dd95SBruce Richardson struct sink {
22699a2dd95SBruce Richardson struct rte_swx_port_out_stats stats;
22799a2dd95SBruce Richardson
22899a2dd95SBruce Richardson #ifdef RTE_PORT_PCAP
22999a2dd95SBruce Richardson pcap_t *f_pcap;
23099a2dd95SBruce Richardson pcap_dumper_t *f_dump;
23199a2dd95SBruce Richardson #endif
23299a2dd95SBruce Richardson };
23399a2dd95SBruce Richardson
23499a2dd95SBruce Richardson static void
sink_free(void * port)23599a2dd95SBruce Richardson sink_free(void *port)
23699a2dd95SBruce Richardson {
23799a2dd95SBruce Richardson struct sink *p = port;
23899a2dd95SBruce Richardson
23999a2dd95SBruce Richardson if (!p)
24099a2dd95SBruce Richardson return;
24199a2dd95SBruce Richardson
24299a2dd95SBruce Richardson #ifdef RTE_PORT_PCAP
24399a2dd95SBruce Richardson if (p->f_dump)
24499a2dd95SBruce Richardson pcap_dump_close(p->f_dump);
24599a2dd95SBruce Richardson if (p->f_pcap)
24699a2dd95SBruce Richardson pcap_close(p->f_pcap);
24799a2dd95SBruce Richardson #endif
24899a2dd95SBruce Richardson
24999a2dd95SBruce Richardson free(p);
25099a2dd95SBruce Richardson }
25199a2dd95SBruce Richardson
25299a2dd95SBruce Richardson static void *
sink_create(void * args __rte_unused)25399a2dd95SBruce Richardson sink_create(void *args __rte_unused)
25499a2dd95SBruce Richardson {
25599a2dd95SBruce Richardson struct sink *p;
25699a2dd95SBruce Richardson
25799a2dd95SBruce Richardson /* Memory allocation. */
25899a2dd95SBruce Richardson p = calloc(1, sizeof(struct sink));
25999a2dd95SBruce Richardson if (!p)
26099a2dd95SBruce Richardson goto error;
26199a2dd95SBruce Richardson
26299a2dd95SBruce Richardson #ifdef RTE_PORT_PCAP
26399a2dd95SBruce Richardson if (args) {
26499a2dd95SBruce Richardson struct rte_swx_port_sink_params *params = args;
26599a2dd95SBruce Richardson
26699a2dd95SBruce Richardson if (params->file_name && params->file_name[0]) {
26799a2dd95SBruce Richardson p->f_pcap = pcap_open_dead(DLT_EN10MB, 65535);
26899a2dd95SBruce Richardson if (!p->f_pcap)
26999a2dd95SBruce Richardson goto error;
27099a2dd95SBruce Richardson
27199a2dd95SBruce Richardson p->f_dump = pcap_dump_open(p->f_pcap,
27299a2dd95SBruce Richardson params->file_name);
27399a2dd95SBruce Richardson if (!p->f_dump)
27499a2dd95SBruce Richardson goto error;
27599a2dd95SBruce Richardson }
27699a2dd95SBruce Richardson }
27799a2dd95SBruce Richardson #endif
27899a2dd95SBruce Richardson
27999a2dd95SBruce Richardson return p;
28099a2dd95SBruce Richardson
28199a2dd95SBruce Richardson error:
28299a2dd95SBruce Richardson sink_free(p);
28399a2dd95SBruce Richardson return NULL;
28499a2dd95SBruce Richardson }
28599a2dd95SBruce Richardson
28699a2dd95SBruce Richardson static void
sink_pkt_tx(void * port,struct rte_swx_pkt * pkt)28799a2dd95SBruce Richardson sink_pkt_tx(void *port, struct rte_swx_pkt *pkt)
28899a2dd95SBruce Richardson {
28999a2dd95SBruce Richardson struct sink *p = port;
29099a2dd95SBruce Richardson struct rte_mbuf *m = pkt->handle;
29199a2dd95SBruce Richardson
29299a2dd95SBruce Richardson TRACE("[Sink port] Pkt TX (%u bytes at offset %u)\n",
29399a2dd95SBruce Richardson pkt->length,
29499a2dd95SBruce Richardson pkt->offset);
29599a2dd95SBruce Richardson if (TRACE_LEVEL)
29699a2dd95SBruce Richardson rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
29799a2dd95SBruce Richardson
298b94eb6cdSCristian Dumitrescu m->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len);
29999a2dd95SBruce Richardson m->pkt_len = pkt->length;
30099a2dd95SBruce Richardson m->data_off = (uint16_t)pkt->offset;
30199a2dd95SBruce Richardson
302*7c10ca26SCristian Dumitrescu p->stats.n_pkts_drop++;
303*7c10ca26SCristian Dumitrescu p->stats.n_bytes_drop += pkt->length;
30499a2dd95SBruce Richardson
30599a2dd95SBruce Richardson #ifdef RTE_PORT_PCAP
30699a2dd95SBruce Richardson if (p->f_dump) {
30799a2dd95SBruce Richardson struct pcap_pkthdr pcap_pkthdr;
30899a2dd95SBruce Richardson uint8_t *m_data = rte_pktmbuf_mtod(m, uint8_t *);
30999a2dd95SBruce Richardson
31099a2dd95SBruce Richardson pcap_pkthdr.len = m->pkt_len;
31199a2dd95SBruce Richardson pcap_pkthdr.caplen = m->data_len;
31299a2dd95SBruce Richardson gettimeofday(&pcap_pkthdr.ts, NULL);
31399a2dd95SBruce Richardson
31499a2dd95SBruce Richardson pcap_dump((uint8_t *)p->f_dump, &pcap_pkthdr, m_data);
31599a2dd95SBruce Richardson pcap_dump_flush(p->f_dump);
31699a2dd95SBruce Richardson }
31799a2dd95SBruce Richardson #endif
31899a2dd95SBruce Richardson
31999a2dd95SBruce Richardson rte_pktmbuf_free(m);
32099a2dd95SBruce Richardson }
32199a2dd95SBruce Richardson
32299a2dd95SBruce Richardson static void
__sink_pkt_clone_tx(void * port,struct rte_swx_pkt * pkt,uint32_t truncation_length __rte_unused)323b94eb6cdSCristian Dumitrescu __sink_pkt_clone_tx(void *port, struct rte_swx_pkt *pkt, uint32_t truncation_length __rte_unused)
324b94eb6cdSCristian Dumitrescu {
325b94eb6cdSCristian Dumitrescu struct sink *p = port;
326b94eb6cdSCristian Dumitrescu struct rte_mbuf *m = pkt->handle;
327b94eb6cdSCristian Dumitrescu
328b94eb6cdSCristian Dumitrescu TRACE("[Sink port] Pkt TX (%u bytes at offset %u) (clone)\n",
329b94eb6cdSCristian Dumitrescu pkt->length,
330b94eb6cdSCristian Dumitrescu pkt->offset);
331b94eb6cdSCristian Dumitrescu if (TRACE_LEVEL)
332b94eb6cdSCristian Dumitrescu rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
333b94eb6cdSCristian Dumitrescu
334b94eb6cdSCristian Dumitrescu m->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len);
335b94eb6cdSCristian Dumitrescu m->pkt_len = pkt->length;
336b94eb6cdSCristian Dumitrescu m->data_off = (uint16_t)pkt->offset;
337b94eb6cdSCristian Dumitrescu
338*7c10ca26SCristian Dumitrescu p->stats.n_pkts_drop++;
339*7c10ca26SCristian Dumitrescu p->stats.n_bytes_drop += pkt->length;
340b94eb6cdSCristian Dumitrescu p->stats.n_pkts_clone++;
341b94eb6cdSCristian Dumitrescu
342b94eb6cdSCristian Dumitrescu #ifdef RTE_PORT_PCAP
343b94eb6cdSCristian Dumitrescu if (p->f_dump) {
344b94eb6cdSCristian Dumitrescu struct pcap_pkthdr pcap_pkthdr;
345b94eb6cdSCristian Dumitrescu uint8_t *m_data = rte_pktmbuf_mtod(m, uint8_t *);
346b94eb6cdSCristian Dumitrescu
347b94eb6cdSCristian Dumitrescu pcap_pkthdr.len = m->pkt_len;
348b94eb6cdSCristian Dumitrescu pcap_pkthdr.caplen = RTE_MIN(m->data_len, truncation_length);
349b94eb6cdSCristian Dumitrescu gettimeofday(&pcap_pkthdr.ts, NULL);
350b94eb6cdSCristian Dumitrescu
351b94eb6cdSCristian Dumitrescu pcap_dump((uint8_t *)p->f_dump, &pcap_pkthdr, m_data);
352b94eb6cdSCristian Dumitrescu pcap_dump_flush(p->f_dump);
353b94eb6cdSCristian Dumitrescu }
354b94eb6cdSCristian Dumitrescu #endif
355b94eb6cdSCristian Dumitrescu }
356b94eb6cdSCristian Dumitrescu
357b94eb6cdSCristian Dumitrescu static void
sink_pkt_fast_clone_tx(void * port,struct rte_swx_pkt * pkt)358b94eb6cdSCristian Dumitrescu sink_pkt_fast_clone_tx(void *port, struct rte_swx_pkt *pkt)
359b94eb6cdSCristian Dumitrescu {
360b94eb6cdSCristian Dumitrescu __sink_pkt_clone_tx(port, pkt, UINT32_MAX);
361b94eb6cdSCristian Dumitrescu }
362b94eb6cdSCristian Dumitrescu
363b94eb6cdSCristian Dumitrescu static void
sink_pkt_clone_tx(void * port,struct rte_swx_pkt * pkt,uint32_t truncation_length)364b94eb6cdSCristian Dumitrescu sink_pkt_clone_tx(void *port, struct rte_swx_pkt *pkt, uint32_t truncation_length)
365b94eb6cdSCristian Dumitrescu {
366b94eb6cdSCristian Dumitrescu __sink_pkt_clone_tx(port, pkt, truncation_length);
367b94eb6cdSCristian Dumitrescu }
368b94eb6cdSCristian Dumitrescu
369b94eb6cdSCristian Dumitrescu static void
sink_stats_read(void * port,struct rte_swx_port_out_stats * stats)37099a2dd95SBruce Richardson sink_stats_read(void *port, struct rte_swx_port_out_stats *stats)
37199a2dd95SBruce Richardson {
37299a2dd95SBruce Richardson struct sink *p = port;
37399a2dd95SBruce Richardson
37499a2dd95SBruce Richardson if (!p || !stats)
37599a2dd95SBruce Richardson return;
37699a2dd95SBruce Richardson
37799a2dd95SBruce Richardson memcpy(stats, &p->stats, sizeof(p->stats));
37899a2dd95SBruce Richardson }
37999a2dd95SBruce Richardson
38099a2dd95SBruce Richardson /*
38199a2dd95SBruce Richardson * Summary of port operations
38299a2dd95SBruce Richardson */
38399a2dd95SBruce Richardson struct rte_swx_port_out_ops rte_swx_port_sink_ops = {
38499a2dd95SBruce Richardson .create = sink_create,
38599a2dd95SBruce Richardson .free = sink_free,
38699a2dd95SBruce Richardson .pkt_tx = sink_pkt_tx,
387b94eb6cdSCristian Dumitrescu .pkt_fast_clone_tx = sink_pkt_fast_clone_tx,
388b94eb6cdSCristian Dumitrescu .pkt_clone_tx = sink_pkt_clone_tx,
38999a2dd95SBruce Richardson .flush = NULL,
39099a2dd95SBruce Richardson .stats_read = sink_stats_read,
39199a2dd95SBruce Richardson };
392