test/cksum: new test for L3/L4 checksum API
[dpdk.git] / lib / port / rte_swx_port_source_sink.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020 Intel Corporation
3  */
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #ifdef RTE_PORT_PCAP
8 #include <pcap.h>
9 #endif
10 #include <sys/time.h>
11
12 #include <rte_common.h>
13 #include <rte_mbuf.h>
14 #include <rte_hexdump.h>
15
16 #include "rte_swx_port_source_sink.h"
17
18 #define CHECK(condition)                                                       \
19 do {                                                                           \
20         if (!(condition))                                                      \
21                 return NULL;                                                   \
22 } while (0)
23
24 #ifndef TRACE_LEVEL
25 #define TRACE_LEVEL 0
26 #endif
27
28 #if TRACE_LEVEL
29 #define TRACE(...) printf(__VA_ARGS__)
30 #else
31 #define TRACE(...)
32 #endif
33
34 /*
35  * Port SOURCE
36  */
37 #ifdef RTE_PORT_PCAP
38
39 struct source {
40         struct {
41                 struct rte_mempool *pool;
42         } params;
43         struct rte_swx_port_in_stats stats;
44         struct rte_mbuf **pkts;
45         uint32_t n_pkts;
46         uint32_t pos;
47 };
48
49 static void
50 source_free(void *port)
51 {
52         struct source *p = port;
53         uint32_t i;
54
55         if (!p)
56                 return;
57
58         for (i = 0; i < p->n_pkts; i++)
59                 rte_pktmbuf_free(p->pkts[i]);
60
61         free(p->pkts);
62
63         free(p);
64 }
65
66 static void *
67 source_create(void *args)
68 {
69         char pcap_errbuf[PCAP_ERRBUF_SIZE];
70         struct rte_swx_port_source_params *params = args;
71         struct source *p = NULL;
72         pcap_t *f = NULL;
73         uint32_t n_pkts_max, i;
74
75         /* Check input arguments. */
76         CHECK(params);
77         CHECK(params->pool);
78         CHECK(params->file_name && params->file_name[0]);
79         n_pkts_max = params->n_pkts_max ?
80                 params->n_pkts_max :
81                 RTE_SWX_PORT_SOURCE_PKTS_MAX;
82
83         /* Resource allocation. */
84         f = pcap_open_offline(params->file_name, pcap_errbuf);
85         if (!f)
86                 goto error;
87
88         p = calloc(1, sizeof(struct source));
89         if (!p)
90                 goto error;
91
92         p->pkts = calloc(n_pkts_max, sizeof(struct rte_mbuf *));
93         if (!p->pkts)
94                 goto error;
95
96         /* Initialization. */
97         p->params.pool = params->pool;
98
99         /* PCAP file. */
100         for (i = 0; i < n_pkts_max; i++) {
101                 struct pcap_pkthdr pcap_pkthdr;
102                 const uint8_t *pcap_pktdata;
103                 struct rte_mbuf *m;
104                 uint8_t *m_data;
105
106                 /* Read new packet from PCAP file. */
107                 pcap_pktdata = pcap_next(f, &pcap_pkthdr);
108                 if (!pcap_pktdata)
109                         break;
110
111                 /* Allocate new buffer from pool. */
112                 m = rte_pktmbuf_alloc(params->pool);
113                 if (!m)
114                         goto error;
115                 m_data = rte_pktmbuf_mtod(m, uint8_t *);
116
117                 rte_memcpy(m_data, pcap_pktdata, pcap_pkthdr.caplen);
118                 m->data_len = pcap_pkthdr.caplen;
119                 m->pkt_len = pcap_pkthdr.caplen;
120
121                 p->pkts[p->n_pkts] = m;
122                 p->n_pkts++;
123         }
124
125         if (!p->n_pkts)
126                 goto error;
127
128         pcap_close(f);
129         return p;
130
131 error:
132         source_free(p);
133         if (f)
134                 pcap_close(f);
135         return NULL;
136 }
137
138 static int
139 source_pkt_rx(void *port, struct rte_swx_pkt *pkt)
140 {
141         struct source *p = port;
142         struct rte_mbuf *m_dst, *m_src;
143         uint8_t *m_dst_data, *m_src_data;
144
145         /* m_src identification. */
146         m_src = p->pkts[p->pos];
147         m_src_data = rte_pktmbuf_mtod(m_src, uint8_t *);
148
149         /* m_dst allocation from pool. */
150         m_dst = rte_pktmbuf_alloc(p->params.pool);
151         if (!m_dst)
152                 return 0;
153
154         /* m_dst initialization. */
155         m_dst->data_len = m_src->data_len;
156         m_dst->pkt_len = m_src->pkt_len;
157         m_dst->data_off = m_src->data_off;
158
159         m_dst_data = rte_pktmbuf_mtod(m_dst, uint8_t *);
160         rte_memcpy(m_dst_data, m_src_data, m_src->data_len);
161
162         /* pkt initialization. */
163         pkt->handle = m_dst;
164         pkt->pkt = m_dst->buf_addr;
165         pkt->offset = m_dst->data_off;
166         pkt->length = m_dst->pkt_len;
167
168         TRACE("[Source port] Pkt RX (%u bytes at offset %u)\n",
169               pkt->length,
170               pkt->offset);
171         if (TRACE_LEVEL)
172                 rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
173
174         /* port stats update. */
175         p->stats.n_pkts++;
176         p->stats.n_bytes += pkt->length;
177
178         /* m_src next. */
179         p->pos++;
180         if (p->pos == p->n_pkts)
181                 p->pos = 0;
182
183         return 1;
184 }
185
186 static void
187 source_stats_read(void *port, struct rte_swx_port_in_stats *stats)
188 {
189         struct source *p = port;
190
191         if (!p || !stats)
192                 return;
193
194         memcpy(stats, &p->stats, sizeof(p->stats));
195 }
196
197 struct rte_swx_port_in_ops rte_swx_port_source_ops = {
198         .create = source_create,
199         .free = source_free,
200         .pkt_rx = source_pkt_rx,
201         .stats_read = source_stats_read,
202 };
203
204 #else
205
206 struct rte_swx_port_in_ops rte_swx_port_source_ops = {
207         .create = NULL,
208         .free = NULL,
209         .pkt_rx = NULL,
210         .stats_read = NULL,
211 };
212
213 #endif
214
215 /*
216  * Port SINK
217  */
218 struct sink {
219         struct rte_swx_port_out_stats stats;
220
221 #ifdef RTE_PORT_PCAP
222         pcap_t *f_pcap;
223         pcap_dumper_t *f_dump;
224 #endif
225 };
226
227 static void
228 sink_free(void *port)
229 {
230         struct sink *p = port;
231
232         if (!p)
233                 return;
234
235 #ifdef RTE_PORT_PCAP
236         if (p->f_dump)
237                 pcap_dump_close(p->f_dump);
238         if (p->f_pcap)
239                 pcap_close(p->f_pcap);
240 #endif
241
242         free(p);
243 }
244
245 static void *
246 sink_create(void *args __rte_unused)
247 {
248         struct sink *p;
249
250         /* Memory allocation. */
251         p = calloc(1, sizeof(struct sink));
252         if (!p)
253                 goto error;
254
255 #ifdef RTE_PORT_PCAP
256         if (args) {
257                 struct rte_swx_port_sink_params *params = args;
258
259                 if (params->file_name && params->file_name[0]) {
260                         p->f_pcap = pcap_open_dead(DLT_EN10MB, 65535);
261                         if (!p->f_pcap)
262                                 goto error;
263
264                         p->f_dump = pcap_dump_open(p->f_pcap,
265                                                    params->file_name);
266                         if (!p->f_dump)
267                                 goto error;
268                 }
269         }
270 #endif
271
272         return p;
273
274 error:
275         sink_free(p);
276         return NULL;
277 }
278
279 static void
280 sink_pkt_tx(void *port, struct rte_swx_pkt *pkt)
281 {
282         struct sink *p = port;
283         struct rte_mbuf *m = pkt->handle;
284
285         TRACE("[Sink port] Pkt TX (%u bytes at offset %u)\n",
286               pkt->length,
287               pkt->offset);
288         if (TRACE_LEVEL)
289                 rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
290
291         m->pkt_len = pkt->length;
292         m->data_len = (uint16_t)pkt->length;
293         m->data_off = (uint16_t)pkt->offset;
294
295         p->stats.n_pkts++;
296         p->stats.n_bytes += pkt->length;
297
298 #ifdef RTE_PORT_PCAP
299         if (p->f_dump) {
300                 struct pcap_pkthdr pcap_pkthdr;
301                 uint8_t *m_data = rte_pktmbuf_mtod(m, uint8_t *);
302
303                 pcap_pkthdr.len = m->pkt_len;
304                 pcap_pkthdr.caplen = m->data_len;
305                 gettimeofday(&pcap_pkthdr.ts, NULL);
306
307                 pcap_dump((uint8_t *)p->f_dump, &pcap_pkthdr, m_data);
308                 pcap_dump_flush(p->f_dump);
309         }
310 #endif
311
312         rte_pktmbuf_free(m);
313 }
314
315 static void
316 sink_stats_read(void *port, struct rte_swx_port_out_stats *stats)
317 {
318         struct sink *p = port;
319
320         if (!p || !stats)
321                 return;
322
323         memcpy(stats, &p->stats, sizeof(p->stats));
324 }
325
326 /*
327  * Summary of port operations
328  */
329 struct rte_swx_port_out_ops rte_swx_port_sink_ops = {
330         .create = sink_create,
331         .free = sink_free,
332         .pkt_tx = sink_pkt_tx,
333         .flush = NULL,
334         .stats_read = sink_stats_read,
335 };