1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
12 #include <rte_common.h>
14 #include <rte_hexdump.h>
16 #include "rte_swx_port_source_sink.h"
18 #define CHECK(condition) \
29 #define TRACE(...) printf(__VA_ARGS__)
41 struct rte_mempool *pool;
44 struct rte_swx_port_in_stats stats;
45 struct rte_mbuf **pkts;
51 source_free(void *port)
53 struct source *p = port;
59 for (i = 0; i < p->n_pkts; i++)
60 rte_pktmbuf_free(p->pkts[i]);
68 source_create(void *args)
70 char pcap_errbuf[PCAP_ERRBUF_SIZE];
71 struct rte_swx_port_source_params *params = args;
72 struct source *p = NULL;
74 uint32_t n_pkts_max, i;
76 /* Check input arguments. */
79 CHECK(params->file_name && params->file_name[0]);
80 n_pkts_max = params->n_pkts_max ?
82 RTE_SWX_PORT_SOURCE_PKTS_MAX;
84 /* Resource allocation. */
85 f = pcap_open_offline(params->file_name, pcap_errbuf);
89 p = calloc(1, sizeof(struct source));
93 p->pkts = calloc(n_pkts_max, sizeof(struct rte_mbuf *));
98 p->params.pool = params->pool;
100 p->params.n_loops = params->n_loops ? params->n_loops : UINT64_MAX;
103 for (i = 0; i < n_pkts_max; i++) {
104 struct pcap_pkthdr pcap_pkthdr;
105 const uint8_t *pcap_pktdata;
109 /* Read new packet from PCAP file. */
110 pcap_pktdata = pcap_next(f, &pcap_pkthdr);
114 /* Allocate new buffer from pool. */
115 m = rte_pktmbuf_alloc(params->pool);
118 m_data = rte_pktmbuf_mtod(m, uint8_t *);
120 rte_memcpy(m_data, pcap_pktdata, pcap_pkthdr.caplen);
121 m->data_len = pcap_pkthdr.caplen;
122 m->pkt_len = pcap_pkthdr.caplen;
124 p->pkts[p->n_pkts] = m;
142 source_pkt_rx(void *port, struct rte_swx_pkt *pkt)
144 struct source *p = port;
145 struct rte_mbuf *m_dst, *m_src;
146 uint8_t *m_dst_data, *m_src_data;
148 if (!p->params.n_loops)
150 /* m_src identification. */
151 m_src = p->pkts[p->pos];
152 m_src_data = rte_pktmbuf_mtod(m_src, uint8_t *);
154 /* m_dst allocation from pool. */
155 m_dst = rte_pktmbuf_alloc(p->params.pool);
159 /* m_dst initialization. */
160 m_dst->data_len = m_src->data_len;
161 m_dst->pkt_len = m_src->pkt_len;
162 m_dst->data_off = m_src->data_off;
164 m_dst_data = rte_pktmbuf_mtod(m_dst, uint8_t *);
165 rte_memcpy(m_dst_data, m_src_data, m_src->data_len);
167 /* pkt initialization. */
169 pkt->pkt = m_dst->buf_addr;
170 pkt->offset = m_dst->data_off;
171 pkt->length = m_dst->pkt_len;
173 TRACE("[Source port] Pkt RX (%u bytes at offset %u)\n",
177 rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
179 /* port stats update. */
181 p->stats.n_bytes += pkt->length;
185 if (p->pos == p->n_pkts) {
194 source_stats_read(void *port, struct rte_swx_port_in_stats *stats)
196 struct source *p = port;
201 memcpy(stats, &p->stats, sizeof(p->stats));
204 struct rte_swx_port_in_ops rte_swx_port_source_ops = {
205 .create = source_create,
207 .pkt_rx = source_pkt_rx,
208 .stats_read = source_stats_read,
213 struct rte_swx_port_in_ops rte_swx_port_source_ops = {
226 struct rte_swx_port_out_stats stats;
230 pcap_dumper_t *f_dump;
235 sink_free(void *port)
237 struct sink *p = port;
244 pcap_dump_close(p->f_dump);
246 pcap_close(p->f_pcap);
253 sink_create(void *args __rte_unused)
257 /* Memory allocation. */
258 p = calloc(1, sizeof(struct sink));
264 struct rte_swx_port_sink_params *params = args;
266 if (params->file_name && params->file_name[0]) {
267 p->f_pcap = pcap_open_dead(DLT_EN10MB, 65535);
271 p->f_dump = pcap_dump_open(p->f_pcap,
287 sink_pkt_tx(void *port, struct rte_swx_pkt *pkt)
289 struct sink *p = port;
290 struct rte_mbuf *m = pkt->handle;
292 TRACE("[Sink port] Pkt TX (%u bytes at offset %u)\n",
296 rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
298 m->pkt_len = pkt->length;
299 m->data_len = (uint16_t)pkt->length;
300 m->data_off = (uint16_t)pkt->offset;
303 p->stats.n_bytes += pkt->length;
307 struct pcap_pkthdr pcap_pkthdr;
308 uint8_t *m_data = rte_pktmbuf_mtod(m, uint8_t *);
310 pcap_pkthdr.len = m->pkt_len;
311 pcap_pkthdr.caplen = m->data_len;
312 gettimeofday(&pcap_pkthdr.ts, NULL);
314 pcap_dump((uint8_t *)p->f_dump, &pcap_pkthdr, m_data);
315 pcap_dump_flush(p->f_dump);
323 sink_stats_read(void *port, struct rte_swx_port_out_stats *stats)
325 struct sink *p = port;
330 memcpy(stats, &p->stats, sizeof(p->stats));
334 * Summary of port operations
336 struct rte_swx_port_out_ops rte_swx_port_sink_ops = {
337 .create = sink_create,
339 .pkt_tx = sink_pkt_tx,
341 .stats_read = sink_stats_read,