app/pdump: remove unused socket path options
[dpdk.git] / app / pdump / main.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2016 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdint.h>
8 #include <inttypes.h>
9 #include <stdlib.h>
10 #include <getopt.h>
11 #include <signal.h>
12 #include <stdbool.h>
13 #include <net/if.h>
14
15 #include <rte_eal.h>
16 #include <rte_common.h>
17 #include <rte_debug.h>
18 #include <rte_ethdev.h>
19 #include <rte_memory.h>
20 #include <rte_lcore.h>
21 #include <rte_branch_prediction.h>
22 #include <rte_errno.h>
23 #include <rte_dev.h>
24 #include <rte_kvargs.h>
25 #include <rte_mempool.h>
26 #include <rte_ring.h>
27 #include <rte_string_fns.h>
28 #include <rte_pdump.h>
29
30 #define CMD_LINE_OPT_PDUMP "pdump"
31 #define PDUMP_PORT_ARG "port"
32 #define PDUMP_PCI_ARG "device_id"
33 #define PDUMP_QUEUE_ARG "queue"
34 #define PDUMP_DIR_ARG "dir"
35 #define PDUMP_RX_DEV_ARG "rx-dev"
36 #define PDUMP_TX_DEV_ARG "tx-dev"
37 #define PDUMP_RING_SIZE_ARG "ring-size"
38 #define PDUMP_MSIZE_ARG "mbuf-size"
39 #define PDUMP_NUM_MBUFS_ARG "total-num-mbufs"
40
41 #define VDEV_PCAP "net_pcap_%s_%d,tx_pcap=%s"
42 #define VDEV_IFACE "net_pcap_%s_%d,tx_iface=%s"
43 #define TX_STREAM_SIZE 64
44
45 #define MP_NAME "pdump_pool_%d"
46
47 #define RX_RING "rx_ring_%d"
48 #define TX_RING "tx_ring_%d"
49
50 #define RX_STR "rx"
51 #define TX_STR "tx"
52
53 /* Maximum long option length for option parsing. */
54 #define APP_ARG_TCPDUMP_MAX_TUPLES 54
55 #define MBUF_POOL_CACHE_SIZE 250
56 #define TX_DESC_PER_QUEUE 512
57 #define RX_DESC_PER_QUEUE 128
58 #define MBUFS_PER_POOL 65535
59 #define MAX_LONG_OPT_SZ 64
60 #define RING_SIZE 16384
61 #define SIZE 256
62 #define BURST_SIZE 32
63 #define NUM_VDEVS 2
64
65 /* true if x is a power of 2 */
66 #define POWEROF2(x) ((((x)-1) & (x)) == 0)
67
68 enum pdump_en_dis {
69         DISABLE = 1,
70         ENABLE = 2
71 };
72
73 enum pcap_stream {
74         IFACE = 1,
75         PCAP = 2
76 };
77
78 enum pdump_by {
79         PORT_ID = 1,
80         DEVICE_ID = 2
81 };
82
83 const char *valid_pdump_arguments[] = {
84         PDUMP_PORT_ARG,
85         PDUMP_PCI_ARG,
86         PDUMP_QUEUE_ARG,
87         PDUMP_DIR_ARG,
88         PDUMP_RX_DEV_ARG,
89         PDUMP_TX_DEV_ARG,
90         PDUMP_RING_SIZE_ARG,
91         PDUMP_MSIZE_ARG,
92         PDUMP_NUM_MBUFS_ARG,
93         NULL
94 };
95
96 struct pdump_stats {
97         uint64_t dequeue_pkts;
98         uint64_t tx_pkts;
99         uint64_t freed_pkts;
100 };
101
102 struct pdump_tuples {
103         /* cli params */
104         uint16_t port;
105         char *device_id;
106         uint16_t queue;
107         char rx_dev[TX_STREAM_SIZE];
108         char tx_dev[TX_STREAM_SIZE];
109         uint32_t ring_size;
110         uint16_t mbuf_data_size;
111         uint32_t total_num_mbufs;
112
113         /* params for library API call */
114         uint32_t dir;
115         struct rte_mempool *mp;
116         struct rte_ring *rx_ring;
117         struct rte_ring *tx_ring;
118
119         /* params for packet dumping */
120         enum pdump_by dump_by_type;
121         int rx_vdev_id;
122         int tx_vdev_id;
123         enum pcap_stream rx_vdev_stream_type;
124         enum pcap_stream tx_vdev_stream_type;
125         bool single_pdump_dev;
126
127         /* stats */
128         struct pdump_stats stats;
129 } __rte_cache_aligned;
130 static struct pdump_tuples pdump_t[APP_ARG_TCPDUMP_MAX_TUPLES];
131
132 struct parse_val {
133         uint64_t min;
134         uint64_t max;
135         uint64_t val;
136 };
137
138 int num_tuples;
139 static struct rte_eth_conf port_conf_default;
140 volatile uint8_t quit_signal;
141
142 /**< display usage */
143 static void
144 pdump_usage(const char *prgname)
145 {
146         printf("usage: %s [EAL options] -- --pdump "
147                         "'(port=<port id> | device_id=<pci id or vdev name>),"
148                         "(queue=<queue_id>),"
149                         "(rx-dev=<iface or pcap file> |"
150                         " tx-dev=<iface or pcap file>,"
151                         "[ring-size=<ring size>default:16384],"
152                         "[mbuf-size=<mbuf data size>default:2176],"
153                         "[total-num-mbufs=<number of mbufs>default:65535]'\n",
154                         prgname);
155 }
156
157 static int
158 parse_device_id(const char *key __rte_unused, const char *value,
159                 void *extra_args)
160 {
161         struct pdump_tuples *pt = extra_args;
162
163         pt->device_id = strdup(value);
164         pt->dump_by_type = DEVICE_ID;
165
166         return 0;
167 }
168
169 static int
170 parse_queue(const char *key __rte_unused, const char *value, void *extra_args)
171 {
172         unsigned long n;
173         struct pdump_tuples *pt = extra_args;
174
175         if (!strcmp(value, "*"))
176                 pt->queue = RTE_PDUMP_ALL_QUEUES;
177         else {
178                 n = strtoul(value, NULL, 10);
179                 pt->queue = (uint16_t) n;
180         }
181         return 0;
182 }
183
184 static int
185 parse_rxtxdev(const char *key, const char *value, void *extra_args)
186 {
187
188         struct pdump_tuples *pt = extra_args;
189
190         if (!strcmp(key, PDUMP_RX_DEV_ARG)) {
191                 snprintf(pt->rx_dev, sizeof(pt->rx_dev), "%s", value);
192                 /* identify the tx stream type for pcap vdev */
193                 if (if_nametoindex(pt->rx_dev))
194                         pt->rx_vdev_stream_type = IFACE;
195         } else if (!strcmp(key, PDUMP_TX_DEV_ARG)) {
196                 snprintf(pt->tx_dev, sizeof(pt->tx_dev), "%s", value);
197                 /* identify the tx stream type for pcap vdev */
198                 if (if_nametoindex(pt->tx_dev))
199                         pt->tx_vdev_stream_type = IFACE;
200         }
201
202         return 0;
203 }
204
205 static int
206 parse_uint_value(const char *key, const char *value, void *extra_args)
207 {
208         struct parse_val *v;
209         unsigned long t;
210         char *end;
211         int ret = 0;
212
213         errno = 0;
214         v = extra_args;
215         t = strtoul(value, &end, 10);
216
217         if (errno != 0 || end[0] != 0 || t < v->min || t > v->max) {
218                 printf("invalid value:\"%s\" for key:\"%s\", "
219                         "value must be >= %"PRIu64" and <= %"PRIu64"\n",
220                         value, key, v->min, v->max);
221                 ret = -EINVAL;
222         }
223         if (!strcmp(key, PDUMP_RING_SIZE_ARG) && !POWEROF2(t)) {
224                 printf("invalid value:\"%s\" for key:\"%s\", "
225                         "value must be power of 2\n", value, key);
226                 ret = -EINVAL;
227         }
228
229         if (ret != 0)
230                 return ret;
231
232         v->val = t;
233         return 0;
234 }
235
236 static int
237 parse_pdump(const char *optarg)
238 {
239         struct rte_kvargs *kvlist;
240         int ret = 0, cnt1, cnt2;
241         struct pdump_tuples *pt;
242         struct parse_val v = {0};
243
244         pt = &pdump_t[num_tuples];
245
246         /* initial check for invalid arguments */
247         kvlist = rte_kvargs_parse(optarg, valid_pdump_arguments);
248         if (kvlist == NULL) {
249                 printf("--pdump=\"%s\": invalid argument passed\n", optarg);
250                 return -1;
251         }
252
253         /* port/device_id parsing and validation */
254         cnt1 = rte_kvargs_count(kvlist, PDUMP_PORT_ARG);
255         cnt2 = rte_kvargs_count(kvlist, PDUMP_PCI_ARG);
256         if (!((cnt1 == 1 && cnt2 == 0) || (cnt1 == 0 && cnt2 == 1))) {
257                 printf("--pdump=\"%s\": must have either port or "
258                         "device_id argument\n", optarg);
259                 ret = -1;
260                 goto free_kvlist;
261         } else if (cnt1 == 1) {
262                 v.min = 0;
263                 v.max = RTE_MAX_ETHPORTS-1;
264                 ret = rte_kvargs_process(kvlist, PDUMP_PORT_ARG,
265                                 &parse_uint_value, &v);
266                 if (ret < 0)
267                         goto free_kvlist;
268                 pt->port = (uint8_t) v.val;
269                 pt->dump_by_type = PORT_ID;
270         } else if (cnt2 == 1) {
271                 ret = rte_kvargs_process(kvlist, PDUMP_PCI_ARG,
272                                 &parse_device_id, pt);
273                 if (ret < 0)
274                         goto free_kvlist;
275         }
276
277         /* queue parsing and validation */
278         cnt1 = rte_kvargs_count(kvlist, PDUMP_QUEUE_ARG);
279         if (cnt1 != 1) {
280                 printf("--pdump=\"%s\": must have queue argument\n", optarg);
281                 ret = -1;
282                 goto free_kvlist;
283         }
284         ret = rte_kvargs_process(kvlist, PDUMP_QUEUE_ARG, &parse_queue, pt);
285         if (ret < 0)
286                 goto free_kvlist;
287
288         /* rx-dev and tx-dev parsing and validation */
289         cnt1 = rte_kvargs_count(kvlist, PDUMP_RX_DEV_ARG);
290         cnt2 = rte_kvargs_count(kvlist, PDUMP_TX_DEV_ARG);
291         if (cnt1 == 0 && cnt2 == 0) {
292                 printf("--pdump=\"%s\": must have either rx-dev or "
293                         "tx-dev argument\n", optarg);
294                 ret = -1;
295                 goto free_kvlist;
296         } else if (cnt1 == 1 && cnt2 == 1) {
297                 ret = rte_kvargs_process(kvlist, PDUMP_RX_DEV_ARG,
298                                         &parse_rxtxdev, pt);
299                 if (ret < 0)
300                         goto free_kvlist;
301                 ret = rte_kvargs_process(kvlist, PDUMP_TX_DEV_ARG,
302                                         &parse_rxtxdev, pt);
303                 if (ret < 0)
304                         goto free_kvlist;
305                 /* if captured packets has to send to the same vdev */
306                 if (!strcmp(pt->rx_dev, pt->tx_dev))
307                         pt->single_pdump_dev = true;
308                 pt->dir = RTE_PDUMP_FLAG_RXTX;
309         } else if (cnt1 == 1) {
310                 ret = rte_kvargs_process(kvlist, PDUMP_RX_DEV_ARG,
311                                         &parse_rxtxdev, pt);
312                 if (ret < 0)
313                         goto free_kvlist;
314                 pt->dir = RTE_PDUMP_FLAG_RX;
315         } else if (cnt2 == 1) {
316                 ret = rte_kvargs_process(kvlist, PDUMP_TX_DEV_ARG,
317                                         &parse_rxtxdev, pt);
318                 if (ret < 0)
319                         goto free_kvlist;
320                 pt->dir = RTE_PDUMP_FLAG_TX;
321         }
322
323         /* optional */
324         /* ring_size parsing and validation */
325         cnt1 = rte_kvargs_count(kvlist, PDUMP_RING_SIZE_ARG);
326         if (cnt1 == 1) {
327                 v.min = 2;
328                 v.max = RTE_RING_SZ_MASK-1;
329                 ret = rte_kvargs_process(kvlist, PDUMP_RING_SIZE_ARG,
330                                                 &parse_uint_value, &v);
331                 if (ret < 0)
332                         goto free_kvlist;
333                 pt->ring_size = (uint32_t) v.val;
334         } else
335                 pt->ring_size = RING_SIZE;
336
337         /* mbuf_data_size parsing and validation */
338         cnt1 = rte_kvargs_count(kvlist, PDUMP_MSIZE_ARG);
339         if (cnt1 == 1) {
340                 v.min = 1;
341                 v.max = UINT16_MAX;
342                 ret = rte_kvargs_process(kvlist, PDUMP_MSIZE_ARG,
343                                                 &parse_uint_value, &v);
344                 if (ret < 0)
345                         goto free_kvlist;
346                 pt->mbuf_data_size = (uint16_t) v.val;
347         } else
348                 pt->mbuf_data_size = RTE_MBUF_DEFAULT_BUF_SIZE;
349
350         /* total_num_mbufs parsing and validation */
351         cnt1 = rte_kvargs_count(kvlist, PDUMP_NUM_MBUFS_ARG);
352         if (cnt1 == 1) {
353                 v.min = 1025;
354                 v.max = UINT16_MAX;
355                 ret = rte_kvargs_process(kvlist, PDUMP_NUM_MBUFS_ARG,
356                                                 &parse_uint_value, &v);
357                 if (ret < 0)
358                         goto free_kvlist;
359                 pt->total_num_mbufs = (uint16_t) v.val;
360         } else
361                 pt->total_num_mbufs = MBUFS_PER_POOL;
362
363         num_tuples++;
364
365 free_kvlist:
366         rte_kvargs_free(kvlist);
367         return ret;
368 }
369
370 /* Parse the argument given in the command line of the application */
371 static int
372 launch_args_parse(int argc, char **argv, char *prgname)
373 {
374         int opt, ret;
375         int option_index;
376         static struct option long_option[] = {
377                 {"pdump", 1, 0, 0},
378                 {NULL, 0, 0, 0}
379         };
380
381         if (argc == 1)
382                 pdump_usage(prgname);
383
384         /* Parse command line */
385         while ((opt = getopt_long(argc, argv, " ",
386                         long_option, &option_index)) != EOF) {
387                 switch (opt) {
388                 case 0:
389                         if (!strncmp(long_option[option_index].name,
390                                         CMD_LINE_OPT_PDUMP,
391                                         sizeof(CMD_LINE_OPT_PDUMP))) {
392                                 ret = parse_pdump(optarg);
393                                 if (ret) {
394                                         pdump_usage(prgname);
395                                         return -1;
396                                 }
397                         }
398                         break;
399                 default:
400                         pdump_usage(prgname);
401                         return -1;
402                 }
403         }
404
405         return 0;
406 }
407
408 static void
409 print_pdump_stats(void)
410 {
411         int i;
412         struct pdump_tuples *pt;
413
414         for (i = 0; i < num_tuples; i++) {
415                 printf("##### PDUMP DEBUG STATS #####\n");
416                 pt = &pdump_t[i];
417                 printf(" -packets dequeued:                     %"PRIu64"\n",
418                                                         pt->stats.dequeue_pkts);
419                 printf(" -packets transmitted to vdev:          %"PRIu64"\n",
420                                                         pt->stats.tx_pkts);
421                 printf(" -packets freed:                        %"PRIu64"\n",
422                                                         pt->stats.freed_pkts);
423         }
424 }
425
426 static inline void
427 disable_pdump(struct pdump_tuples *pt)
428 {
429         if (pt->dump_by_type == DEVICE_ID)
430                 rte_pdump_disable_by_deviceid(pt->device_id, pt->queue,
431                                                 pt->dir);
432         else if (pt->dump_by_type == PORT_ID)
433                 rte_pdump_disable(pt->port, pt->queue, pt->dir);
434 }
435
436 static inline void
437 pdump_rxtx(struct rte_ring *ring, uint8_t vdev_id, struct pdump_stats *stats)
438 {
439         /* write input packets of port to vdev for pdump */
440         struct rte_mbuf *rxtx_bufs[BURST_SIZE];
441
442         /* first dequeue packets from ring of primary process */
443         const uint16_t nb_in_deq = rte_ring_dequeue_burst(ring,
444                         (void *)rxtx_bufs, BURST_SIZE, NULL);
445         stats->dequeue_pkts += nb_in_deq;
446
447         if (nb_in_deq) {
448                 /* then sent on vdev */
449                 uint16_t nb_in_txd = rte_eth_tx_burst(
450                                 vdev_id,
451                                 0, rxtx_bufs, nb_in_deq);
452                 stats->tx_pkts += nb_in_txd;
453
454                 if (unlikely(nb_in_txd < nb_in_deq)) {
455                         do {
456                                 rte_pktmbuf_free(rxtx_bufs[nb_in_txd]);
457                                 stats->freed_pkts++;
458                         } while (++nb_in_txd < nb_in_deq);
459                 }
460         }
461 }
462
463 static void
464 free_ring_data(struct rte_ring *ring, uint8_t vdev_id,
465                 struct pdump_stats *stats)
466 {
467         while (rte_ring_count(ring))
468                 pdump_rxtx(ring, vdev_id, stats);
469 }
470
471 static void
472 cleanup_rings(void)
473 {
474         int i;
475         struct pdump_tuples *pt;
476
477         for (i = 0; i < num_tuples; i++) {
478                 pt = &pdump_t[i];
479
480                 if (pt->device_id)
481                         free(pt->device_id);
482
483                 /* free the rings */
484                 if (pt->rx_ring)
485                         rte_ring_free(pt->rx_ring);
486                 if (pt->tx_ring)
487                         rte_ring_free(pt->tx_ring);
488         }
489 }
490
491 static void
492 cleanup_pdump_resources(void)
493 {
494         int i;
495         struct pdump_tuples *pt;
496
497         /* disable pdump and free the pdump_tuple resources */
498         for (i = 0; i < num_tuples; i++) {
499                 pt = &pdump_t[i];
500
501                 /* remove callbacks */
502                 disable_pdump(pt);
503
504                 /*
505                 * transmit rest of the enqueued packets of the rings on to
506                 * the vdev, in order to release mbufs to the mepool.
507                 **/
508                 if (pt->dir & RTE_PDUMP_FLAG_RX)
509                         free_ring_data(pt->rx_ring, pt->rx_vdev_id, &pt->stats);
510                 if (pt->dir & RTE_PDUMP_FLAG_TX)
511                         free_ring_data(pt->tx_ring, pt->tx_vdev_id, &pt->stats);
512         }
513         cleanup_rings();
514 }
515
516 static void
517 signal_handler(int sig_num)
518 {
519         if (sig_num == SIGINT) {
520                 printf("\n\nSignal %d received, preparing to exit...\n",
521                                 sig_num);
522                 quit_signal = 1;
523         }
524 }
525
526 static inline int
527 configure_vdev(uint16_t port_id)
528 {
529         struct ether_addr addr;
530         const uint16_t rxRings = 0, txRings = 1;
531         int ret;
532         uint16_t q;
533
534         if (!rte_eth_dev_is_valid_port(port_id))
535                 return -1;
536
537         ret = rte_eth_dev_configure(port_id, rxRings, txRings,
538                                         &port_conf_default);
539         if (ret != 0)
540                 rte_exit(EXIT_FAILURE, "dev config failed\n");
541
542          for (q = 0; q < txRings; q++) {
543                 ret = rte_eth_tx_queue_setup(port_id, q, TX_DESC_PER_QUEUE,
544                                 rte_eth_dev_socket_id(port_id), NULL);
545                 if (ret < 0)
546                         rte_exit(EXIT_FAILURE, "queue setup failed\n");
547         }
548
549         ret = rte_eth_dev_start(port_id);
550         if (ret < 0)
551                 rte_exit(EXIT_FAILURE, "dev start failed\n");
552
553         rte_eth_macaddr_get(port_id, &addr);
554         printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
555                         " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
556                         port_id,
557                         addr.addr_bytes[0], addr.addr_bytes[1],
558                         addr.addr_bytes[2], addr.addr_bytes[3],
559                         addr.addr_bytes[4], addr.addr_bytes[5]);
560
561         rte_eth_promiscuous_enable(port_id);
562
563         return 0;
564 }
565
566 static void
567 create_mp_ring_vdev(void)
568 {
569         int i;
570         uint16_t portid;
571         struct pdump_tuples *pt = NULL;
572         struct rte_mempool *mbuf_pool = NULL;
573         char vdev_args[SIZE];
574         char ring_name[SIZE];
575         char mempool_name[SIZE];
576
577         for (i = 0; i < num_tuples; i++) {
578                 pt = &pdump_t[i];
579                 snprintf(mempool_name, SIZE, MP_NAME, i);
580                 mbuf_pool = rte_mempool_lookup(mempool_name);
581                 if (mbuf_pool == NULL) {
582                         /* create mempool */
583                         mbuf_pool = rte_pktmbuf_pool_create(mempool_name,
584                                         pt->total_num_mbufs,
585                                         MBUF_POOL_CACHE_SIZE, 0,
586                                         pt->mbuf_data_size,
587                                         rte_socket_id());
588                         if (mbuf_pool == NULL) {
589                                 cleanup_rings();
590                                 rte_exit(EXIT_FAILURE,
591                                         "Mempool creation failed: %s\n",
592                                         rte_strerror(rte_errno));
593                         }
594                 }
595                 pt->mp = mbuf_pool;
596
597                 if (pt->dir == RTE_PDUMP_FLAG_RXTX) {
598                         /* if captured packets has to send to the same vdev */
599                         /* create rx_ring */
600                         snprintf(ring_name, SIZE, RX_RING, i);
601                         pt->rx_ring = rte_ring_create(ring_name, pt->ring_size,
602                                         rte_socket_id(), 0);
603                         if (pt->rx_ring == NULL) {
604                                 cleanup_rings();
605                                 rte_exit(EXIT_FAILURE, "%s:%s:%d\n",
606                                                 rte_strerror(rte_errno),
607                                                 __func__, __LINE__);
608                         }
609
610                         /* create tx_ring */
611                         snprintf(ring_name, SIZE, TX_RING, i);
612                         pt->tx_ring = rte_ring_create(ring_name, pt->ring_size,
613                                         rte_socket_id(), 0);
614                         if (pt->tx_ring == NULL) {
615                                 cleanup_rings();
616                                 rte_exit(EXIT_FAILURE, "%s:%s:%d\n",
617                                                 rte_strerror(rte_errno),
618                                                 __func__, __LINE__);
619                         }
620
621                         /* create vdevs */
622                         (pt->rx_vdev_stream_type == IFACE) ?
623                         snprintf(vdev_args, SIZE, VDEV_IFACE, RX_STR, i,
624                         pt->rx_dev) :
625                         snprintf(vdev_args, SIZE, VDEV_PCAP, RX_STR, i,
626                         pt->rx_dev);
627                         if (rte_eth_dev_attach(vdev_args, &portid) < 0) {
628                                 cleanup_rings();
629                                 rte_exit(EXIT_FAILURE,
630                                         "vdev creation failed:%s:%d\n",
631                                         __func__, __LINE__);
632                         }
633                         pt->rx_vdev_id = portid;
634
635                         /* configure vdev */
636                         configure_vdev(pt->rx_vdev_id);
637
638                         if (pt->single_pdump_dev)
639                                 pt->tx_vdev_id = portid;
640                         else {
641                                 (pt->tx_vdev_stream_type == IFACE) ?
642                                 snprintf(vdev_args, SIZE, VDEV_IFACE, TX_STR, i,
643                                 pt->tx_dev) :
644                                 snprintf(vdev_args, SIZE, VDEV_PCAP, TX_STR, i,
645                                 pt->tx_dev);
646                                 if (rte_eth_dev_attach(vdev_args,
647                                                         &portid) < 0) {
648                                         cleanup_rings();
649                                         rte_exit(EXIT_FAILURE,
650                                                 "vdev creation failed:"
651                                                 "%s:%d\n", __func__, __LINE__);
652                                 }
653                                 pt->tx_vdev_id = portid;
654
655                                 /* configure vdev */
656                                 configure_vdev(pt->tx_vdev_id);
657                         }
658                 } else if (pt->dir == RTE_PDUMP_FLAG_RX) {
659
660                         /* create rx_ring */
661                         snprintf(ring_name, SIZE, RX_RING, i);
662                         pt->rx_ring = rte_ring_create(ring_name, pt->ring_size,
663                                         rte_socket_id(), 0);
664                         if (pt->rx_ring == NULL) {
665                                 cleanup_rings();
666                                 rte_exit(EXIT_FAILURE, "%s\n",
667                                         rte_strerror(rte_errno));
668                         }
669
670                         (pt->rx_vdev_stream_type == IFACE) ?
671                         snprintf(vdev_args, SIZE, VDEV_IFACE, RX_STR, i,
672                                 pt->rx_dev) :
673                         snprintf(vdev_args, SIZE, VDEV_PCAP, RX_STR, i,
674                                 pt->rx_dev);
675                         if (rte_eth_dev_attach(vdev_args, &portid) < 0) {
676                                 cleanup_rings();
677                                 rte_exit(EXIT_FAILURE,
678                                         "vdev creation failed:%s:%d\n",
679                                         __func__, __LINE__);
680                         }
681                         pt->rx_vdev_id = portid;
682                         /* configure vdev */
683                         configure_vdev(pt->rx_vdev_id);
684                 } else if (pt->dir == RTE_PDUMP_FLAG_TX) {
685
686                         /* create tx_ring */
687                         snprintf(ring_name, SIZE, TX_RING, i);
688                         pt->tx_ring = rte_ring_create(ring_name, pt->ring_size,
689                                         rte_socket_id(), 0);
690                         if (pt->tx_ring == NULL) {
691                                 cleanup_rings();
692                                 rte_exit(EXIT_FAILURE, "%s\n",
693                                         rte_strerror(rte_errno));
694                         }
695
696                         (pt->tx_vdev_stream_type == IFACE) ?
697                         snprintf(vdev_args, SIZE, VDEV_IFACE, TX_STR, i,
698                                 pt->tx_dev) :
699                         snprintf(vdev_args, SIZE, VDEV_PCAP, TX_STR, i,
700                                 pt->tx_dev);
701                         if (rte_eth_dev_attach(vdev_args, &portid) < 0) {
702                                 cleanup_rings();
703                                 rte_exit(EXIT_FAILURE,
704                                         "vdev creation failed\n");
705                         }
706                         pt->tx_vdev_id = portid;
707
708                         /* configure vdev */
709                         configure_vdev(pt->tx_vdev_id);
710                 }
711         }
712 }
713
714 static void
715 enable_pdump(void)
716 {
717         int i;
718         struct pdump_tuples *pt;
719         int ret = 0, ret1 = 0;
720
721         for (i = 0; i < num_tuples; i++) {
722                 pt = &pdump_t[i];
723                 if (pt->dir == RTE_PDUMP_FLAG_RXTX) {
724                         if (pt->dump_by_type == DEVICE_ID) {
725                                 ret = rte_pdump_enable_by_deviceid(
726                                                 pt->device_id,
727                                                 pt->queue,
728                                                 RTE_PDUMP_FLAG_RX,
729                                                 pt->rx_ring,
730                                                 pt->mp, NULL);
731                                 ret1 = rte_pdump_enable_by_deviceid(
732                                                 pt->device_id,
733                                                 pt->queue,
734                                                 RTE_PDUMP_FLAG_TX,
735                                                 pt->tx_ring,
736                                                 pt->mp, NULL);
737                         } else if (pt->dump_by_type == PORT_ID) {
738                                 ret = rte_pdump_enable(pt->port, pt->queue,
739                                                 RTE_PDUMP_FLAG_RX,
740                                                 pt->rx_ring, pt->mp, NULL);
741                                 ret1 = rte_pdump_enable(pt->port, pt->queue,
742                                                 RTE_PDUMP_FLAG_TX,
743                                                 pt->tx_ring, pt->mp, NULL);
744                         }
745                 } else if (pt->dir == RTE_PDUMP_FLAG_RX) {
746                         if (pt->dump_by_type == DEVICE_ID)
747                                 ret = rte_pdump_enable_by_deviceid(
748                                                 pt->device_id,
749                                                 pt->queue,
750                                                 pt->dir, pt->rx_ring,
751                                                 pt->mp, NULL);
752                         else if (pt->dump_by_type == PORT_ID)
753                                 ret = rte_pdump_enable(pt->port, pt->queue,
754                                                 pt->dir,
755                                                 pt->rx_ring, pt->mp, NULL);
756                 } else if (pt->dir == RTE_PDUMP_FLAG_TX) {
757                         if (pt->dump_by_type == DEVICE_ID)
758                                 ret = rte_pdump_enable_by_deviceid(
759                                                 pt->device_id,
760                                                 pt->queue,
761                                                 pt->dir,
762                                                 pt->tx_ring, pt->mp, NULL);
763                         else if (pt->dump_by_type == PORT_ID)
764                                 ret = rte_pdump_enable(pt->port, pt->queue,
765                                                 pt->dir,
766                                                 pt->tx_ring, pt->mp, NULL);
767                 }
768                 if (ret < 0 || ret1 < 0) {
769                         cleanup_pdump_resources();
770                         rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));
771                 }
772         }
773 }
774
775 static inline void
776 dump_packets(void)
777 {
778         int i;
779         struct pdump_tuples *pt;
780
781         while (!quit_signal) {
782                 for (i = 0; i < num_tuples; i++) {
783                         pt = &pdump_t[i];
784                         if (pt->dir & RTE_PDUMP_FLAG_RX)
785                                 pdump_rxtx(pt->rx_ring, pt->rx_vdev_id,
786                                         &pt->stats);
787                         if (pt->dir & RTE_PDUMP_FLAG_TX)
788                                 pdump_rxtx(pt->tx_ring, pt->tx_vdev_id,
789                                         &pt->stats);
790                 }
791         }
792 }
793
794 int
795 main(int argc, char **argv)
796 {
797         int diag;
798         int ret;
799         int i;
800
801         char c_flag[] = "-c1";
802         char n_flag[] = "-n4";
803         char mp_flag[] = "--proc-type=secondary";
804         char *argp[argc + 3];
805
806         /* catch ctrl-c so we can print on exit */
807         signal(SIGINT, signal_handler);
808
809         argp[0] = argv[0];
810         argp[1] = c_flag;
811         argp[2] = n_flag;
812         argp[3] = mp_flag;
813
814         for (i = 1; i < argc; i++)
815                 argp[i + 3] = argv[i];
816
817         argc += 3;
818
819         diag = rte_eal_init(argc, argp);
820         if (diag < 0)
821                 rte_panic("Cannot init EAL\n");
822
823         if (rte_eth_dev_count_avail() == 0)
824                 rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
825
826         argc -= diag;
827         argv += (diag - 3);
828
829         /* parse app arguments */
830         if (argc > 1) {
831                 ret = launch_args_parse(argc, argv, argp[0]);
832                 if (ret < 0)
833                         rte_exit(EXIT_FAILURE, "Invalid argument\n");
834         }
835
836         /* create mempool, ring and vdevs info */
837         create_mp_ring_vdev();
838         enable_pdump();
839         dump_packets();
840
841         cleanup_pdump_resources();
842         /* dump debug stats */
843         print_pdump_stats();
844
845         ret = rte_eal_cleanup();
846         if (ret)
847                 printf("Error from rte_eal_cleanup(), %d\n", ret);
848
849         return 0;
850 }