LCOV - code coverage report
Current view: top level - app/pdump - main.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 398 0.0 %
Date: 2024-02-14 00:53:57 Functions: 0 23 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       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_alarm.h>
      17                 :            : #include <rte_common.h>
      18                 :            : #include <rte_debug.h>
      19                 :            : #include <rte_ethdev.h>
      20                 :            : #include <rte_memory.h>
      21                 :            : #include <rte_lcore.h>
      22                 :            : #include <rte_branch_prediction.h>
      23                 :            : #include <rte_errno.h>
      24                 :            : #include <rte_dev.h>
      25                 :            : #include <rte_kvargs.h>
      26                 :            : #include <rte_mempool.h>
      27                 :            : #include <rte_ring.h>
      28                 :            : #include <rte_string_fns.h>
      29                 :            : #include <rte_pdump.h>
      30                 :            : 
      31                 :            : #define CMD_LINE_OPT_PDUMP "pdump"
      32                 :            : #define CMD_LINE_OPT_PDUMP_NUM 256
      33                 :            : #define CMD_LINE_OPT_MULTI "multi"
      34                 :            : #define CMD_LINE_OPT_MULTI_NUM 257
      35                 :            : #define PDUMP_PORT_ARG "port"
      36                 :            : #define PDUMP_PCI_ARG "device_id"
      37                 :            : #define PDUMP_QUEUE_ARG "queue"
      38                 :            : #define PDUMP_DIR_ARG "dir"
      39                 :            : #define PDUMP_RX_DEV_ARG "rx-dev"
      40                 :            : #define PDUMP_TX_DEV_ARG "tx-dev"
      41                 :            : #define PDUMP_RING_SIZE_ARG "ring-size"
      42                 :            : #define PDUMP_MSIZE_ARG "mbuf-size"
      43                 :            : #define PDUMP_NUM_MBUFS_ARG "total-num-mbufs"
      44                 :            : 
      45                 :            : #define VDEV_NAME_FMT "net_pcap_%s_%d"
      46                 :            : #define VDEV_PCAP_ARGS_FMT "tx_pcap=%s"
      47                 :            : #define VDEV_IFACE_ARGS_FMT "tx_iface=%s"
      48                 :            : #define TX_STREAM_SIZE 64
      49                 :            : 
      50                 :            : #define MP_NAME "pdump_pool_%d"
      51                 :            : 
      52                 :            : #define RX_RING "rx_ring_%d"
      53                 :            : #define TX_RING "tx_ring_%d"
      54                 :            : 
      55                 :            : #define RX_STR "rx"
      56                 :            : #define TX_STR "tx"
      57                 :            : 
      58                 :            : /* Maximum long option length for option parsing. */
      59                 :            : #define APP_ARG_TCPDUMP_MAX_TUPLES 54
      60                 :            : #define MBUF_POOL_CACHE_SIZE 250
      61                 :            : #define TX_DESC_PER_QUEUE 512
      62                 :            : #define RX_DESC_PER_QUEUE 128
      63                 :            : #define MBUFS_PER_POOL 65535
      64                 :            : #define MAX_LONG_OPT_SZ 64
      65                 :            : #define RING_SIZE 16384
      66                 :            : #define SIZE 256
      67                 :            : #define BURST_SIZE 32
      68                 :            : #define NUM_VDEVS 2
      69                 :            : /* Maximum delay for exiting after primary process. */
      70                 :            : #define MONITOR_INTERVAL (500 * 1000)
      71                 :            : 
      72                 :            : /* true if x is a power of 2 */
      73                 :            : #define POWEROF2(x) ((((x)-1) & (x)) == 0)
      74                 :            : 
      75                 :            : enum pdump_en_dis {
      76                 :            :         DISABLE = 1,
      77                 :            :         ENABLE = 2
      78                 :            : };
      79                 :            : 
      80                 :            : enum pcap_stream {
      81                 :            :         IFACE = 1,
      82                 :            :         PCAP = 2
      83                 :            : };
      84                 :            : 
      85                 :            : enum pdump_by {
      86                 :            :         PORT_ID = 1,
      87                 :            :         DEVICE_ID = 2
      88                 :            : };
      89                 :            : 
      90                 :            : static const char * const valid_pdump_arguments[] = {
      91                 :            :         PDUMP_PORT_ARG,
      92                 :            :         PDUMP_PCI_ARG,
      93                 :            :         PDUMP_QUEUE_ARG,
      94                 :            :         PDUMP_DIR_ARG,
      95                 :            :         PDUMP_RX_DEV_ARG,
      96                 :            :         PDUMP_TX_DEV_ARG,
      97                 :            :         PDUMP_RING_SIZE_ARG,
      98                 :            :         PDUMP_MSIZE_ARG,
      99                 :            :         PDUMP_NUM_MBUFS_ARG,
     100                 :            :         NULL
     101                 :            : };
     102                 :            : 
     103                 :            : struct pdump_stats {
     104                 :            :         uint64_t dequeue_pkts;
     105                 :            :         uint64_t tx_pkts;
     106                 :            :         uint64_t freed_pkts;
     107                 :            : };
     108                 :            : 
     109                 :            : struct pdump_tuples {
     110                 :            :         /* cli params */
     111                 :            :         uint16_t port;
     112                 :            :         char *device_id;
     113                 :            :         uint16_t queue;
     114                 :            :         char rx_dev[TX_STREAM_SIZE];
     115                 :            :         char tx_dev[TX_STREAM_SIZE];
     116                 :            :         uint32_t ring_size;
     117                 :            :         uint16_t mbuf_data_size;
     118                 :            :         uint32_t total_num_mbufs;
     119                 :            : 
     120                 :            :         /* params for library API call */
     121                 :            :         uint32_t dir;
     122                 :            :         struct rte_mempool *mp;
     123                 :            :         struct rte_ring *rx_ring;
     124                 :            :         struct rte_ring *tx_ring;
     125                 :            : 
     126                 :            :         /* params for packet dumping */
     127                 :            :         enum pdump_by dump_by_type;
     128                 :            :         uint16_t rx_vdev_id;
     129                 :            :         uint16_t tx_vdev_id;
     130                 :            :         enum pcap_stream rx_vdev_stream_type;
     131                 :            :         enum pcap_stream tx_vdev_stream_type;
     132                 :            :         bool single_pdump_dev;
     133                 :            : 
     134                 :            :         /* stats */
     135                 :            :         struct pdump_stats stats;
     136                 :            : } __rte_cache_aligned;
     137                 :            : static struct pdump_tuples pdump_t[APP_ARG_TCPDUMP_MAX_TUPLES];
     138                 :            : 
     139                 :            : struct parse_val {
     140                 :            :         uint64_t min;
     141                 :            :         uint64_t max;
     142                 :            :         uint64_t val;
     143                 :            : };
     144                 :            : 
     145                 :            : static int num_tuples;
     146                 :            : static struct rte_eth_conf port_conf_default;
     147                 :            : static volatile uint8_t quit_signal;
     148                 :            : static uint8_t multiple_core_capture;
     149                 :            : 
     150                 :            : /**< display usage */
     151                 :            : static void
     152                 :            : pdump_usage(const char *prgname)
     153                 :            : {
     154                 :            :         printf("usage: %s [EAL options] --"
     155                 :            :                         " --["CMD_LINE_OPT_MULTI"]\n"
     156                 :            :                         " --"CMD_LINE_OPT_PDUMP" "
     157                 :            :                         "'(port=<port id> | device_id=<pci id or vdev name>),"
     158                 :            :                         "(queue=<queue_id>),"
     159                 :            :                         "(rx-dev=<iface or pcap file> |"
     160                 :            :                         " tx-dev=<iface or pcap file>,"
     161                 :            :                         "[ring-size=<ring size>default:16384],"
     162                 :            :                         "[mbuf-size=<mbuf data size>default:2176],"
     163                 :            :                         "[total-num-mbufs=<number of mbufs>default:65535]'\n",
     164                 :            :                         prgname);
     165                 :          0 : }
     166                 :            : 
     167                 :            : static int
     168                 :          0 : parse_device_id(const char *key __rte_unused, const char *value,
     169                 :            :                 void *extra_args)
     170                 :            : {
     171                 :            :         struct pdump_tuples *pt = extra_args;
     172                 :            : 
     173                 :          0 :         pt->device_id = strdup(value);
     174                 :          0 :         pt->dump_by_type = DEVICE_ID;
     175                 :            : 
     176                 :          0 :         return 0;
     177                 :            : }
     178                 :            : 
     179                 :            : static int
     180                 :          0 : parse_queue(const char *key __rte_unused, const char *value, void *extra_args)
     181                 :            : {
     182                 :            :         unsigned long n;
     183                 :            :         struct pdump_tuples *pt = extra_args;
     184                 :            : 
     185                 :          0 :         if (!strcmp(value, "*"))
     186                 :          0 :                 pt->queue = RTE_PDUMP_ALL_QUEUES;
     187                 :            :         else {
     188                 :          0 :                 n = strtoul(value, NULL, 10);
     189                 :          0 :                 pt->queue = (uint16_t) n;
     190                 :            :         }
     191                 :          0 :         return 0;
     192                 :            : }
     193                 :            : 
     194                 :            : static int
     195                 :          0 : parse_rxtxdev(const char *key, const char *value, void *extra_args)
     196                 :            : {
     197                 :            : 
     198                 :            :         struct pdump_tuples *pt = extra_args;
     199                 :            : 
     200                 :          0 :         if (!strcmp(key, PDUMP_RX_DEV_ARG)) {
     201                 :          0 :                 strlcpy(pt->rx_dev, value, sizeof(pt->rx_dev));
     202                 :            :                 /* identify the tx stream type for pcap vdev */
     203                 :          0 :                 if (if_nametoindex(pt->rx_dev))
     204                 :          0 :                         pt->rx_vdev_stream_type = IFACE;
     205                 :          0 :         } else if (!strcmp(key, PDUMP_TX_DEV_ARG)) {
     206                 :          0 :                 strlcpy(pt->tx_dev, value, sizeof(pt->tx_dev));
     207                 :            :                 /* identify the tx stream type for pcap vdev */
     208                 :          0 :                 if (if_nametoindex(pt->tx_dev))
     209                 :          0 :                         pt->tx_vdev_stream_type = IFACE;
     210                 :            :         }
     211                 :            : 
     212                 :          0 :         return 0;
     213                 :            : }
     214                 :            : 
     215                 :            : static int
     216                 :          0 : parse_uint_value(const char *key, const char *value, void *extra_args)
     217                 :            : {
     218                 :            :         struct parse_val *v;
     219                 :            :         unsigned long t;
     220                 :            :         char *end;
     221                 :            :         int ret = 0;
     222                 :            : 
     223                 :          0 :         errno = 0;
     224                 :            :         v = extra_args;
     225                 :          0 :         t = strtoul(value, &end, 10);
     226                 :            : 
     227                 :          0 :         if (errno != 0 || end[0] != 0 || t < v->min || t > v->max) {
     228                 :          0 :                 printf("invalid value:\"%s\" for key:\"%s\", "
     229                 :            :                         "value must be >= %"PRIu64" and <= %"PRIu64"\n",
     230                 :            :                         value, key, v->min, v->max);
     231                 :            :                 ret = -EINVAL;
     232                 :            :         }
     233                 :          0 :         if (!strcmp(key, PDUMP_RING_SIZE_ARG) && !POWEROF2(t)) {
     234                 :            :                 printf("invalid value:\"%s\" for key:\"%s\", "
     235                 :            :                         "value must be power of 2\n", value, key);
     236                 :            :                 ret = -EINVAL;
     237                 :            :         }
     238                 :            : 
     239                 :          0 :         if (ret != 0)
     240                 :          0 :                 return ret;
     241                 :            : 
     242                 :          0 :         v->val = t;
     243                 :          0 :         return 0;
     244                 :            : }
     245                 :            : 
     246                 :            : static int
     247                 :          0 : parse_pdump(const char *optarg)
     248                 :            : {
     249                 :            :         struct rte_kvargs *kvlist;
     250                 :            :         int ret = 0, cnt1, cnt2;
     251                 :            :         struct pdump_tuples *pt;
     252                 :          0 :         struct parse_val v = {0};
     253                 :            : 
     254                 :          0 :         pt = &pdump_t[num_tuples];
     255                 :            : 
     256                 :            :         /* initial check for invalid arguments */
     257                 :          0 :         kvlist = rte_kvargs_parse(optarg, valid_pdump_arguments);
     258                 :          0 :         if (kvlist == NULL) {
     259                 :            :                 printf("--pdump=\"%s\": invalid argument passed\n", optarg);
     260                 :          0 :                 return -1;
     261                 :            :         }
     262                 :            : 
     263                 :            :         /* port/device_id parsing and validation */
     264                 :          0 :         cnt1 = rte_kvargs_count(kvlist, PDUMP_PORT_ARG);
     265                 :          0 :         cnt2 = rte_kvargs_count(kvlist, PDUMP_PCI_ARG);
     266                 :          0 :         if (!((cnt1 == 1 && cnt2 == 0) || (cnt1 == 0 && cnt2 == 1))) {
     267                 :            :                 printf("--pdump=\"%s\": must have either port or "
     268                 :            :                         "device_id argument\n", optarg);
     269                 :            :                 ret = -1;
     270                 :          0 :                 goto free_kvlist;
     271                 :          0 :         } else if (cnt1 == 1) {
     272                 :          0 :                 v.min = 0;
     273                 :          0 :                 v.max = RTE_MAX_ETHPORTS-1;
     274                 :          0 :                 ret = rte_kvargs_process(kvlist, PDUMP_PORT_ARG,
     275                 :            :                                 &parse_uint_value, &v);
     276                 :          0 :                 if (ret < 0)
     277                 :          0 :                         goto free_kvlist;
     278                 :          0 :                 pt->port = (uint16_t) v.val;
     279                 :          0 :                 pt->dump_by_type = PORT_ID;
     280                 :          0 :         } else if (cnt2 == 1) {
     281                 :          0 :                 ret = rte_kvargs_process(kvlist, PDUMP_PCI_ARG,
     282                 :            :                                 &parse_device_id, pt);
     283                 :          0 :                 if (ret < 0)
     284                 :          0 :                         goto free_kvlist;
     285                 :            :         }
     286                 :            : 
     287                 :            :         /* queue parsing and validation */
     288                 :          0 :         cnt1 = rte_kvargs_count(kvlist, PDUMP_QUEUE_ARG);
     289                 :          0 :         if (cnt1 != 1) {
     290                 :            :                 printf("--pdump=\"%s\": must have queue argument\n", optarg);
     291                 :            :                 ret = -1;
     292                 :          0 :                 goto free_kvlist;
     293                 :            :         }
     294                 :          0 :         ret = rte_kvargs_process(kvlist, PDUMP_QUEUE_ARG, &parse_queue, pt);
     295                 :          0 :         if (ret < 0)
     296                 :          0 :                 goto free_kvlist;
     297                 :            : 
     298                 :            :         /* rx-dev and tx-dev parsing and validation */
     299                 :          0 :         cnt1 = rte_kvargs_count(kvlist, PDUMP_RX_DEV_ARG);
     300                 :          0 :         cnt2 = rte_kvargs_count(kvlist, PDUMP_TX_DEV_ARG);
     301                 :          0 :         if (cnt1 == 0 && cnt2 == 0) {
     302                 :            :                 printf("--pdump=\"%s\": must have either rx-dev or "
     303                 :            :                         "tx-dev argument\n", optarg);
     304                 :            :                 ret = -1;
     305                 :          0 :                 goto free_kvlist;
     306                 :          0 :         } else if (cnt1 == 1 && cnt2 == 1) {
     307                 :          0 :                 ret = rte_kvargs_process(kvlist, PDUMP_RX_DEV_ARG,
     308                 :            :                                         &parse_rxtxdev, pt);
     309                 :          0 :                 if (ret < 0)
     310                 :          0 :                         goto free_kvlist;
     311                 :          0 :                 ret = rte_kvargs_process(kvlist, PDUMP_TX_DEV_ARG,
     312                 :            :                                         &parse_rxtxdev, pt);
     313                 :          0 :                 if (ret < 0)
     314                 :          0 :                         goto free_kvlist;
     315                 :            :                 /* if captured packets has to send to the same vdev */
     316                 :          0 :                 if (!strcmp(pt->rx_dev, pt->tx_dev))
     317                 :          0 :                         pt->single_pdump_dev = true;
     318                 :          0 :                 pt->dir = RTE_PDUMP_FLAG_RXTX;
     319                 :          0 :         } else if (cnt1 == 1) {
     320                 :          0 :                 ret = rte_kvargs_process(kvlist, PDUMP_RX_DEV_ARG,
     321                 :            :                                         &parse_rxtxdev, pt);
     322                 :          0 :                 if (ret < 0)
     323                 :          0 :                         goto free_kvlist;
     324                 :          0 :                 pt->dir = RTE_PDUMP_FLAG_RX;
     325                 :          0 :         } else if (cnt2 == 1) {
     326                 :          0 :                 ret = rte_kvargs_process(kvlist, PDUMP_TX_DEV_ARG,
     327                 :            :                                         &parse_rxtxdev, pt);
     328                 :          0 :                 if (ret < 0)
     329                 :          0 :                         goto free_kvlist;
     330                 :          0 :                 pt->dir = RTE_PDUMP_FLAG_TX;
     331                 :            :         }
     332                 :            : 
     333                 :            :         /* optional */
     334                 :            :         /* ring_size parsing and validation */
     335                 :          0 :         cnt1 = rte_kvargs_count(kvlist, PDUMP_RING_SIZE_ARG);
     336                 :          0 :         if (cnt1 == 1) {
     337                 :          0 :                 v.min = 2;
     338                 :          0 :                 v.max = RTE_RING_SZ_MASK-1;
     339                 :          0 :                 ret = rte_kvargs_process(kvlist, PDUMP_RING_SIZE_ARG,
     340                 :            :                                                 &parse_uint_value, &v);
     341                 :          0 :                 if (ret < 0)
     342                 :          0 :                         goto free_kvlist;
     343                 :          0 :                 pt->ring_size = (uint32_t) v.val;
     344                 :            :         } else
     345                 :          0 :                 pt->ring_size = RING_SIZE;
     346                 :            : 
     347                 :            :         /* mbuf_data_size parsing and validation */
     348                 :          0 :         cnt1 = rte_kvargs_count(kvlist, PDUMP_MSIZE_ARG);
     349                 :          0 :         if (cnt1 == 1) {
     350                 :          0 :                 v.min = 1;
     351                 :          0 :                 v.max = UINT16_MAX;
     352                 :          0 :                 ret = rte_kvargs_process(kvlist, PDUMP_MSIZE_ARG,
     353                 :            :                                                 &parse_uint_value, &v);
     354                 :          0 :                 if (ret < 0)
     355                 :          0 :                         goto free_kvlist;
     356                 :          0 :                 pt->mbuf_data_size = (uint16_t) v.val;
     357                 :            :         } else
     358                 :          0 :                 pt->mbuf_data_size = RTE_MBUF_DEFAULT_BUF_SIZE;
     359                 :            : 
     360                 :            :         /* total_num_mbufs parsing and validation */
     361                 :          0 :         cnt1 = rte_kvargs_count(kvlist, PDUMP_NUM_MBUFS_ARG);
     362                 :          0 :         if (cnt1 == 1) {
     363                 :          0 :                 v.min = 1025;
     364                 :          0 :                 v.max = UINT16_MAX;
     365                 :          0 :                 ret = rte_kvargs_process(kvlist, PDUMP_NUM_MBUFS_ARG,
     366                 :            :                                                 &parse_uint_value, &v);
     367                 :          0 :                 if (ret < 0)
     368                 :          0 :                         goto free_kvlist;
     369                 :          0 :                 pt->total_num_mbufs = (uint16_t) v.val;
     370                 :            :         } else
     371                 :          0 :                 pt->total_num_mbufs = MBUFS_PER_POOL;
     372                 :            : 
     373                 :          0 :         num_tuples++;
     374                 :            : 
     375                 :          0 : free_kvlist:
     376                 :          0 :         rte_kvargs_free(kvlist);
     377                 :          0 :         return ret;
     378                 :            : }
     379                 :            : 
     380                 :            : /* Parse the argument given in the command line of the application */
     381                 :            : static int
     382                 :          0 : launch_args_parse(int argc, char **argv, char *prgname)
     383                 :            : {
     384                 :            :         int opt, ret;
     385                 :            :         int option_index;
     386                 :            :         static struct option long_option[] = {
     387                 :            :                 {CMD_LINE_OPT_PDUMP, 1, 0, CMD_LINE_OPT_PDUMP_NUM},
     388                 :            :                 {CMD_LINE_OPT_MULTI, 0, 0, CMD_LINE_OPT_MULTI_NUM},
     389                 :            :                 {NULL, 0, 0, 0}
     390                 :            :         };
     391                 :            : 
     392                 :          0 :         if (argc == 1)
     393                 :            :                 pdump_usage(prgname);
     394                 :            : 
     395                 :            :         /* Parse command line */
     396                 :          0 :         while ((opt = getopt_long(argc, argv, " ",
     397                 :          0 :                         long_option, &option_index)) != EOF) {
     398                 :          0 :                 switch (opt) {
     399                 :          0 :                 case CMD_LINE_OPT_PDUMP_NUM:
     400                 :          0 :                         ret = parse_pdump(optarg);
     401                 :          0 :                         if (ret) {
     402                 :            :                                 pdump_usage(prgname);
     403                 :          0 :                                 return -1;
     404                 :            :                         }
     405                 :            :                         break;
     406                 :          0 :                 case CMD_LINE_OPT_MULTI_NUM:
     407                 :          0 :                         multiple_core_capture = 1;
     408                 :          0 :                         break;
     409                 :            :                 default:
     410                 :            :                         pdump_usage(prgname);
     411                 :          0 :                         return -1;
     412                 :            :                 }
     413                 :            :         }
     414                 :            : 
     415                 :            :         return 0;
     416                 :            : }
     417                 :            : 
     418                 :            : static void
     419                 :          0 : monitor_primary(void *arg __rte_unused)
     420                 :            : {
     421                 :          0 :         if (quit_signal)
     422                 :            :                 return;
     423                 :            : 
     424                 :          0 :         if (rte_eal_primary_proc_alive(NULL)) {
     425                 :          0 :                 rte_eal_alarm_set(MONITOR_INTERVAL, monitor_primary, NULL);
     426                 :          0 :                 return;
     427                 :            :         }
     428                 :            : 
     429                 :            :         printf("Primary process is no longer active, exiting...\n");
     430                 :          0 :         quit_signal = 1;
     431                 :            : }
     432                 :            : 
     433                 :            : static void
     434                 :          0 : print_pdump_stats(void)
     435                 :            : {
     436                 :            :         int i;
     437                 :            :         struct pdump_tuples *pt;
     438                 :            : 
     439                 :          0 :         for (i = 0; i < num_tuples; i++) {
     440                 :            :                 printf("##### PDUMP DEBUG STATS #####\n");
     441                 :            :                 pt = &pdump_t[i];
     442                 :          0 :                 printf(" -packets dequeued:                        %"PRIu64"\n",
     443                 :            :                                                         pt->stats.dequeue_pkts);
     444                 :          0 :                 printf(" -packets transmitted to vdev:             %"PRIu64"\n",
     445                 :            :                                                         pt->stats.tx_pkts);
     446                 :          0 :                 printf(" -packets freed:                   %"PRIu64"\n",
     447                 :            :                                                         pt->stats.freed_pkts);
     448                 :            :         }
     449                 :          0 : }
     450                 :            : 
     451                 :            : static inline void
     452                 :          0 : disable_pdump(struct pdump_tuples *pt)
     453                 :            : {
     454                 :          0 :         if (pt->dump_by_type == DEVICE_ID)
     455                 :          0 :                 rte_pdump_disable_by_deviceid(pt->device_id, pt->queue,
     456                 :            :                                                 pt->dir);
     457                 :          0 :         else if (pt->dump_by_type == PORT_ID)
     458                 :          0 :                 rte_pdump_disable(pt->port, pt->queue, pt->dir);
     459                 :          0 : }
     460                 :            : 
     461                 :            : static inline void
     462                 :          0 : pdump_rxtx(struct rte_ring *ring, uint16_t vdev_id, struct pdump_stats *stats)
     463                 :            : {
     464                 :            :         /* write input packets of port to vdev for pdump */
     465                 :            :         struct rte_mbuf *rxtx_bufs[BURST_SIZE];
     466                 :            : 
     467                 :            :         /* first dequeue packets from ring of primary process */
     468                 :          0 :         const uint16_t nb_in_deq = rte_ring_dequeue_burst(ring,
     469                 :            :                         (void *)rxtx_bufs, BURST_SIZE, NULL);
     470                 :          0 :         stats->dequeue_pkts += nb_in_deq;
     471                 :            : 
     472                 :          0 :         if (nb_in_deq) {
     473                 :            :                 /* then sent on vdev */
     474                 :          0 :                 uint16_t nb_in_txd = rte_eth_tx_burst(
     475                 :            :                                 vdev_id,
     476                 :            :                                 0, rxtx_bufs, nb_in_deq);
     477                 :          0 :                 stats->tx_pkts += nb_in_txd;
     478                 :            : 
     479                 :          0 :                 if (unlikely(nb_in_txd < nb_in_deq)) {
     480                 :          0 :                         unsigned int drops = nb_in_deq - nb_in_txd;
     481                 :            : 
     482                 :          0 :                         rte_pktmbuf_free_bulk(&rxtx_bufs[nb_in_txd], drops);
     483                 :          0 :                         stats->freed_pkts += drops;
     484                 :            :                 }
     485                 :            :         }
     486                 :          0 : }
     487                 :            : 
     488                 :            : static void
     489                 :            : free_ring_data(struct rte_ring *ring, uint16_t vdev_id,
     490                 :            :                 struct pdump_stats *stats)
     491                 :            : {
     492                 :          0 :         while (rte_ring_count(ring))
     493                 :          0 :                 pdump_rxtx(ring, vdev_id, stats);
     494                 :            : }
     495                 :            : 
     496                 :            : static void
     497                 :          0 : cleanup_rings(void)
     498                 :            : {
     499                 :            :         int i;
     500                 :            :         struct pdump_tuples *pt;
     501                 :            : 
     502                 :          0 :         for (i = 0; i < num_tuples; i++) {
     503                 :            :                 pt = &pdump_t[i];
     504                 :            : 
     505                 :          0 :                 free(pt->device_id);
     506                 :            : 
     507                 :            :                 /* free the rings */
     508                 :          0 :                 rte_ring_free(pt->rx_ring);
     509                 :          0 :                 rte_ring_free(pt->tx_ring);
     510                 :          0 :                 rte_mempool_free(pt->mp);
     511                 :            :         }
     512                 :          0 : }
     513                 :            : 
     514                 :            : static void
     515                 :          0 : cleanup_pdump_resources(void)
     516                 :            : {
     517                 :            :         int i;
     518                 :            :         struct pdump_tuples *pt;
     519                 :            :         char name[RTE_ETH_NAME_MAX_LEN];
     520                 :            : 
     521                 :            :         /* disable pdump and free the pdump_tuple resources */
     522                 :          0 :         for (i = 0; i < num_tuples; i++) {
     523                 :          0 :                 pt = &pdump_t[i];
     524                 :            : 
     525                 :            :                 /* remove callbacks */
     526                 :          0 :                 disable_pdump(pt);
     527                 :            : 
     528                 :            :                 /*
     529                 :            :                 * transmit rest of the enqueued packets of the rings on to
     530                 :            :                 * the vdev, in order to release mbufs to the mepool.
     531                 :            :                 **/
     532                 :          0 :                 if (pt->dir & RTE_PDUMP_FLAG_RX)
     533                 :          0 :                         free_ring_data(pt->rx_ring, pt->rx_vdev_id, &pt->stats);
     534                 :          0 :                 if (pt->dir & RTE_PDUMP_FLAG_TX)
     535                 :          0 :                         free_ring_data(pt->tx_ring, pt->tx_vdev_id, &pt->stats);
     536                 :            : 
     537                 :            :                 /* Remove the vdev(s) created */
     538                 :          0 :                 if (pt->dir & RTE_PDUMP_FLAG_RX) {
     539                 :          0 :                         rte_eth_dev_get_name_by_port(pt->rx_vdev_id, name);
     540                 :          0 :                         rte_eal_hotplug_remove("vdev", name);
     541                 :            :                 }
     542                 :            : 
     543                 :          0 :                 if (pt->single_pdump_dev)
     544                 :          0 :                         continue;
     545                 :            : 
     546                 :          0 :                 if (pt->dir & RTE_PDUMP_FLAG_TX) {
     547                 :          0 :                         rte_eth_dev_get_name_by_port(pt->tx_vdev_id, name);
     548                 :          0 :                         rte_eal_hotplug_remove("vdev", name);
     549                 :            :                 }
     550                 :            : 
     551                 :            :         }
     552                 :          0 :         cleanup_rings();
     553                 :          0 : }
     554                 :            : 
     555                 :            : static void
     556                 :          0 : disable_primary_monitor(void)
     557                 :            : {
     558                 :            :         int ret;
     559                 :            : 
     560                 :            :         /*
     561                 :            :          * Cancel monitoring of primary process.
     562                 :            :          * There will be no error if no alarm is set
     563                 :            :          * (in case primary process kill was detected earlier).
     564                 :            :          */
     565                 :          0 :         ret = rte_eal_alarm_cancel(monitor_primary, NULL);
     566                 :          0 :         if (ret < 0)
     567                 :            :                 printf("Fail to disable monitor:%d\n", ret);
     568                 :          0 : }
     569                 :            : 
     570                 :            : static void
     571                 :          0 : signal_handler(int sig_num)
     572                 :            : {
     573                 :          0 :         if (sig_num == SIGINT) {
     574                 :          0 :                 quit_signal = 1;
     575                 :            :         }
     576                 :          0 : }
     577                 :            : 
     578                 :            : static inline int
     579                 :          0 : configure_vdev(uint16_t port_id)
     580                 :            : {
     581                 :            :         struct rte_ether_addr addr;
     582                 :            :         const uint16_t rxRings = 0, txRings = 1;
     583                 :            :         int ret;
     584                 :            :         uint16_t q;
     585                 :            : 
     586                 :          0 :         if (!rte_eth_dev_is_valid_port(port_id))
     587                 :            :                 return -1;
     588                 :            : 
     589                 :          0 :         ret = rte_eth_dev_configure(port_id, rxRings, txRings,
     590                 :            :                                         &port_conf_default);
     591                 :          0 :         if (ret != 0)
     592                 :          0 :                 rte_exit(EXIT_FAILURE, "dev config failed\n");
     593                 :            : 
     594                 :          0 :         for (q = 0; q < txRings; q++) {
     595                 :          0 :                 ret = rte_eth_tx_queue_setup(port_id, q, TX_DESC_PER_QUEUE,
     596                 :          0 :                                 rte_eth_dev_socket_id(port_id), NULL);
     597                 :          0 :                 if (ret < 0)
     598                 :          0 :                         rte_exit(EXIT_FAILURE, "queue setup failed\n");
     599                 :            :         }
     600                 :            : 
     601                 :          0 :         ret = rte_eth_dev_start(port_id);
     602                 :          0 :         if (ret < 0)
     603                 :          0 :                 rte_exit(EXIT_FAILURE, "dev start failed\n");
     604                 :            : 
     605                 :          0 :         ret = rte_eth_macaddr_get(port_id, &addr);
     606                 :          0 :         if (ret != 0)
     607                 :          0 :                 rte_exit(EXIT_FAILURE, "macaddr get failed\n");
     608                 :            : 
     609                 :          0 :         printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
     610                 :            :                         " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
     611                 :          0 :                         port_id, RTE_ETHER_ADDR_BYTES(&addr));
     612                 :            : 
     613                 :          0 :         ret = rte_eth_promiscuous_enable(port_id);
     614                 :          0 :         if (ret != 0) {
     615                 :          0 :                 rte_exit(EXIT_FAILURE,
     616                 :            :                          "promiscuous mode enable failed: %s\n",
     617                 :            :                          rte_strerror(-ret));
     618                 :            :                 return ret;
     619                 :            :         }
     620                 :            : 
     621                 :            :         return 0;
     622                 :            : }
     623                 :            : 
     624                 :            : static void
     625                 :          0 : create_mp_ring_vdev(void)
     626                 :            : {
     627                 :            :         int i;
     628                 :            :         uint16_t portid;
     629                 :            :         struct pdump_tuples *pt = NULL;
     630                 :            :         struct rte_mempool *mbuf_pool = NULL;
     631                 :            :         char vdev_name[SIZE];
     632                 :            :         char vdev_args[SIZE];
     633                 :            :         char ring_name[SIZE];
     634                 :            :         char mempool_name[SIZE];
     635                 :            : 
     636                 :          0 :         for (i = 0; i < num_tuples; i++) {
     637                 :            :                 pt = &pdump_t[i];
     638                 :            :                 snprintf(mempool_name, SIZE, MP_NAME, i);
     639                 :          0 :                 mbuf_pool = rte_mempool_lookup(mempool_name);
     640                 :          0 :                 if (mbuf_pool == NULL) {
     641                 :            :                         /* create mempool */
     642                 :          0 :                         mbuf_pool = rte_pktmbuf_pool_create_by_ops(mempool_name,
     643                 :            :                                         pt->total_num_mbufs,
     644                 :            :                                         MBUF_POOL_CACHE_SIZE, 0,
     645                 :          0 :                                         pt->mbuf_data_size,
     646                 :          0 :                                         rte_socket_id(), "ring_mp_mc");
     647                 :          0 :                         if (mbuf_pool == NULL) {
     648                 :          0 :                                 cleanup_rings();
     649                 :          0 :                                 rte_exit(EXIT_FAILURE,
     650                 :            :                                         "Mempool creation failed: %s\n",
     651                 :            :                                         rte_strerror(rte_errno));
     652                 :            :                         }
     653                 :            :                 }
     654                 :          0 :                 pt->mp = mbuf_pool;
     655                 :            : 
     656                 :          0 :                 if (pt->dir == RTE_PDUMP_FLAG_RXTX) {
     657                 :            :                         /* if captured packets has to send to the same vdev */
     658                 :            :                         /* create rx_ring */
     659                 :            :                         snprintf(ring_name, SIZE, RX_RING, i);
     660                 :          0 :                         pt->rx_ring = rte_ring_create(ring_name, pt->ring_size,
     661                 :          0 :                                         rte_socket_id(), 0);
     662                 :          0 :                         if (pt->rx_ring == NULL) {
     663                 :          0 :                                 cleanup_rings();
     664                 :          0 :                                 rte_exit(EXIT_FAILURE, "%s:%s:%d\n",
     665                 :            :                                                 rte_strerror(rte_errno),
     666                 :            :                                                 __func__, __LINE__);
     667                 :            :                         }
     668                 :            : 
     669                 :            :                         /* create tx_ring */
     670                 :            :                         snprintf(ring_name, SIZE, TX_RING, i);
     671                 :          0 :                         pt->tx_ring = rte_ring_create(ring_name, pt->ring_size,
     672                 :          0 :                                         rte_socket_id(), 0);
     673                 :          0 :                         if (pt->tx_ring == NULL) {
     674                 :          0 :                                 cleanup_rings();
     675                 :          0 :                                 rte_exit(EXIT_FAILURE, "%s:%s:%d\n",
     676                 :            :                                                 rte_strerror(rte_errno),
     677                 :            :                                                 __func__, __LINE__);
     678                 :            :                         }
     679                 :            : 
     680                 :            :                         /* create vdevs */
     681                 :            :                         snprintf(vdev_name, sizeof(vdev_name),
     682                 :            :                                  VDEV_NAME_FMT, RX_STR, i);
     683                 :          0 :                         (pt->rx_vdev_stream_type == IFACE) ?
     684                 :            :                         snprintf(vdev_args, sizeof(vdev_args),
     685                 :          0 :                                  VDEV_IFACE_ARGS_FMT, pt->rx_dev) :
     686                 :            :                         snprintf(vdev_args, sizeof(vdev_args),
     687                 :          0 :                                  VDEV_PCAP_ARGS_FMT, pt->rx_dev);
     688                 :          0 :                         if (rte_eal_hotplug_add("vdev", vdev_name,
     689                 :            :                                                 vdev_args) < 0) {
     690                 :          0 :                                 cleanup_rings();
     691                 :          0 :                                 rte_exit(EXIT_FAILURE,
     692                 :            :                                         "vdev creation failed:%s:%d\n",
     693                 :            :                                         __func__, __LINE__);
     694                 :            :                         }
     695                 :          0 :                         if (rte_eth_dev_get_port_by_name(vdev_name,
     696                 :            :                                                          &portid) != 0) {
     697                 :          0 :                                 rte_eal_hotplug_remove("vdev", vdev_name);
     698                 :          0 :                                 cleanup_rings();
     699                 :          0 :                                 rte_exit(EXIT_FAILURE,
     700                 :            :                                         "cannot find added vdev %s:%s:%d\n",
     701                 :            :                                         vdev_name, __func__, __LINE__);
     702                 :            :                         }
     703                 :          0 :                         pt->rx_vdev_id = portid;
     704                 :            : 
     705                 :            :                         /* configure vdev */
     706                 :          0 :                         configure_vdev(pt->rx_vdev_id);
     707                 :            : 
     708                 :          0 :                         if (pt->single_pdump_dev)
     709                 :          0 :                                 pt->tx_vdev_id = portid;
     710                 :            :                         else {
     711                 :            :                                 snprintf(vdev_name, sizeof(vdev_name),
     712                 :            :                                          VDEV_NAME_FMT, TX_STR, i);
     713                 :          0 :                                 (pt->rx_vdev_stream_type == IFACE) ?
     714                 :            :                                 snprintf(vdev_args, sizeof(vdev_args),
     715                 :          0 :                                          VDEV_IFACE_ARGS_FMT, pt->tx_dev) :
     716                 :            :                                 snprintf(vdev_args, sizeof(vdev_args),
     717                 :          0 :                                          VDEV_PCAP_ARGS_FMT, pt->tx_dev);
     718                 :          0 :                                 if (rte_eal_hotplug_add("vdev", vdev_name,
     719                 :            :                                                         vdev_args) < 0) {
     720                 :          0 :                                         cleanup_rings();
     721                 :          0 :                                         rte_exit(EXIT_FAILURE,
     722                 :            :                                                 "vdev creation failed:"
     723                 :            :                                                 "%s:%d\n", __func__, __LINE__);
     724                 :            :                                 }
     725                 :          0 :                                 if (rte_eth_dev_get_port_by_name(vdev_name,
     726                 :            :                                                 &portid) != 0) {
     727                 :          0 :                                         rte_eal_hotplug_remove("vdev",
     728                 :            :                                                                vdev_name);
     729                 :          0 :                                         cleanup_rings();
     730                 :          0 :                                         rte_exit(EXIT_FAILURE,
     731                 :            :                                                 "cannot find added vdev %s:%s:%d\n",
     732                 :            :                                                 vdev_name, __func__, __LINE__);
     733                 :            :                                 }
     734                 :          0 :                                 pt->tx_vdev_id = portid;
     735                 :            : 
     736                 :            :                                 /* configure vdev */
     737                 :          0 :                                 configure_vdev(pt->tx_vdev_id);
     738                 :            :                         }
     739                 :          0 :                 } else if (pt->dir == RTE_PDUMP_FLAG_RX) {
     740                 :            : 
     741                 :            :                         /* create rx_ring */
     742                 :            :                         snprintf(ring_name, SIZE, RX_RING, i);
     743                 :          0 :                         pt->rx_ring = rte_ring_create(ring_name, pt->ring_size,
     744                 :          0 :                                         rte_socket_id(), 0);
     745                 :          0 :                         if (pt->rx_ring == NULL) {
     746                 :          0 :                                 cleanup_rings();
     747                 :          0 :                                 rte_exit(EXIT_FAILURE, "%s\n",
     748                 :            :                                         rte_strerror(rte_errno));
     749                 :            :                         }
     750                 :            : 
     751                 :            :                         snprintf(vdev_name, sizeof(vdev_name),
     752                 :            :                                  VDEV_NAME_FMT, RX_STR, i);
     753                 :          0 :                         (pt->rx_vdev_stream_type == IFACE) ?
     754                 :            :                         snprintf(vdev_args, sizeof(vdev_args),
     755                 :          0 :                                  VDEV_IFACE_ARGS_FMT, pt->rx_dev) :
     756                 :            :                         snprintf(vdev_args, sizeof(vdev_args),
     757                 :          0 :                                  VDEV_PCAP_ARGS_FMT, pt->rx_dev);
     758                 :          0 :                         if (rte_eal_hotplug_add("vdev", vdev_name,
     759                 :            :                                                 vdev_args) < 0) {
     760                 :          0 :                                 cleanup_rings();
     761                 :          0 :                                 rte_exit(EXIT_FAILURE,
     762                 :            :                                         "vdev creation failed:%s:%d\n",
     763                 :            :                                         __func__, __LINE__);
     764                 :            :                         }
     765                 :          0 :                         if (rte_eth_dev_get_port_by_name(vdev_name,
     766                 :            :                                                          &portid) != 0) {
     767                 :          0 :                                 rte_eal_hotplug_remove("vdev", vdev_name);
     768                 :          0 :                                 cleanup_rings();
     769                 :          0 :                                 rte_exit(EXIT_FAILURE,
     770                 :            :                                         "cannot find added vdev %s:%s:%d\n",
     771                 :            :                                         vdev_name, __func__, __LINE__);
     772                 :            :                         }
     773                 :          0 :                         pt->rx_vdev_id = portid;
     774                 :            :                         /* configure vdev */
     775                 :          0 :                         configure_vdev(pt->rx_vdev_id);
     776                 :          0 :                 } else if (pt->dir == RTE_PDUMP_FLAG_TX) {
     777                 :            : 
     778                 :            :                         /* create tx_ring */
     779                 :            :                         snprintf(ring_name, SIZE, TX_RING, i);
     780                 :          0 :                         pt->tx_ring = rte_ring_create(ring_name, pt->ring_size,
     781                 :          0 :                                         rte_socket_id(), 0);
     782                 :          0 :                         if (pt->tx_ring == NULL) {
     783                 :          0 :                                 cleanup_rings();
     784                 :          0 :                                 rte_exit(EXIT_FAILURE, "%s\n",
     785                 :            :                                         rte_strerror(rte_errno));
     786                 :            :                         }
     787                 :            : 
     788                 :            :                         snprintf(vdev_name, sizeof(vdev_name),
     789                 :            :                                  VDEV_NAME_FMT, TX_STR, i);
     790                 :          0 :                         (pt->tx_vdev_stream_type == IFACE) ?
     791                 :            :                         snprintf(vdev_args, sizeof(vdev_args),
     792                 :          0 :                                  VDEV_IFACE_ARGS_FMT, pt->tx_dev) :
     793                 :            :                         snprintf(vdev_args, sizeof(vdev_args),
     794                 :          0 :                                  VDEV_PCAP_ARGS_FMT, pt->tx_dev);
     795                 :          0 :                         if (rte_eal_hotplug_add("vdev", vdev_name,
     796                 :            :                                                 vdev_args) < 0) {
     797                 :          0 :                                 cleanup_rings();
     798                 :          0 :                                 rte_exit(EXIT_FAILURE,
     799                 :            :                                         "vdev creation failed\n");
     800                 :            :                         }
     801                 :          0 :                         if (rte_eth_dev_get_port_by_name(vdev_name,
     802                 :            :                                                          &portid) != 0) {
     803                 :          0 :                                 rte_eal_hotplug_remove("vdev", vdev_name);
     804                 :          0 :                                 cleanup_rings();
     805                 :          0 :                                 rte_exit(EXIT_FAILURE,
     806                 :            :                                         "cannot find added vdev %s:%s:%d\n",
     807                 :            :                                         vdev_name, __func__, __LINE__);
     808                 :            :                         }
     809                 :          0 :                         pt->tx_vdev_id = portid;
     810                 :            : 
     811                 :            :                         /* configure vdev */
     812                 :          0 :                         configure_vdev(pt->tx_vdev_id);
     813                 :            :                 }
     814                 :            :         }
     815                 :          0 : }
     816                 :            : 
     817                 :            : static void
     818                 :          0 : enable_pdump(void)
     819                 :            : {
     820                 :            :         int i;
     821                 :            :         struct pdump_tuples *pt;
     822                 :            :         int ret = 0, ret1 = 0;
     823                 :            : 
     824                 :          0 :         for (i = 0; i < num_tuples; i++) {
     825                 :            :                 pt = &pdump_t[i];
     826                 :          0 :                 if (pt->dir == RTE_PDUMP_FLAG_RXTX) {
     827                 :          0 :                         if (pt->dump_by_type == DEVICE_ID) {
     828                 :          0 :                                 ret = rte_pdump_enable_by_deviceid(
     829                 :            :                                                 pt->device_id,
     830                 :          0 :                                                 pt->queue,
     831                 :            :                                                 RTE_PDUMP_FLAG_RX,
     832                 :            :                                                 pt->rx_ring,
     833                 :            :                                                 pt->mp, NULL);
     834                 :          0 :                                 ret1 = rte_pdump_enable_by_deviceid(
     835                 :            :                                                 pt->device_id,
     836                 :          0 :                                                 pt->queue,
     837                 :            :                                                 RTE_PDUMP_FLAG_TX,
     838                 :            :                                                 pt->tx_ring,
     839                 :            :                                                 pt->mp, NULL);
     840                 :          0 :                         } else if (pt->dump_by_type == PORT_ID) {
     841                 :          0 :                                 ret = rte_pdump_enable(pt->port, pt->queue,
     842                 :            :                                                 RTE_PDUMP_FLAG_RX,
     843                 :            :                                                 pt->rx_ring, pt->mp, NULL);
     844                 :          0 :                                 ret1 = rte_pdump_enable(pt->port, pt->queue,
     845                 :            :                                                 RTE_PDUMP_FLAG_TX,
     846                 :            :                                                 pt->tx_ring, pt->mp, NULL);
     847                 :            :                         }
     848                 :          0 :                 } else if (pt->dir == RTE_PDUMP_FLAG_RX) {
     849                 :          0 :                         if (pt->dump_by_type == DEVICE_ID)
     850                 :          0 :                                 ret = rte_pdump_enable_by_deviceid(
     851                 :            :                                                 pt->device_id,
     852                 :          0 :                                                 pt->queue,
     853                 :            :                                                 pt->dir, pt->rx_ring,
     854                 :            :                                                 pt->mp, NULL);
     855                 :          0 :                         else if (pt->dump_by_type == PORT_ID)
     856                 :          0 :                                 ret = rte_pdump_enable(pt->port, pt->queue,
     857                 :            :                                                 pt->dir,
     858                 :            :                                                 pt->rx_ring, pt->mp, NULL);
     859                 :          0 :                 } else if (pt->dir == RTE_PDUMP_FLAG_TX) {
     860                 :          0 :                         if (pt->dump_by_type == DEVICE_ID)
     861                 :          0 :                                 ret = rte_pdump_enable_by_deviceid(
     862                 :            :                                                 pt->device_id,
     863                 :          0 :                                                 pt->queue,
     864                 :            :                                                 pt->dir,
     865                 :            :                                                 pt->tx_ring, pt->mp, NULL);
     866                 :          0 :                         else if (pt->dump_by_type == PORT_ID)
     867                 :          0 :                                 ret = rte_pdump_enable(pt->port, pt->queue,
     868                 :            :                                                 pt->dir,
     869                 :            :                                                 pt->tx_ring, pt->mp, NULL);
     870                 :            :                 }
     871                 :          0 :                 if (ret < 0 || ret1 < 0) {
     872                 :          0 :                         cleanup_pdump_resources();
     873                 :          0 :                         rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));
     874                 :            :                 }
     875                 :            :         }
     876                 :          0 : }
     877                 :            : 
     878                 :            : static inline void
     879                 :          0 : pdump_packets(struct pdump_tuples *pt)
     880                 :            : {
     881                 :          0 :         if (pt->dir & RTE_PDUMP_FLAG_RX)
     882                 :          0 :                 pdump_rxtx(pt->rx_ring, pt->rx_vdev_id, &pt->stats);
     883                 :          0 :         if (pt->dir & RTE_PDUMP_FLAG_TX)
     884                 :          0 :                 pdump_rxtx(pt->tx_ring, pt->tx_vdev_id, &pt->stats);
     885                 :          0 : }
     886                 :            : 
     887                 :            : static int
     888                 :          0 : dump_packets_core(void *arg)
     889                 :            : {
     890                 :            :         struct pdump_tuples *pt = (struct pdump_tuples *) arg;
     891                 :            : 
     892                 :          0 :         printf(" core (%u); port %u device (%s) queue %u\n",
     893                 :          0 :                         rte_lcore_id(), pt->port, pt->device_id, pt->queue);
     894                 :          0 :         fflush(stdout);
     895                 :            : 
     896                 :          0 :         while (!quit_signal)
     897                 :          0 :                 pdump_packets(pt);
     898                 :            : 
     899                 :          0 :         return 0;
     900                 :            : }
     901                 :            : 
     902                 :            : static unsigned int
     903                 :          0 : get_next_core(unsigned int lcore)
     904                 :            : {
     905                 :          0 :         lcore = rte_get_next_lcore(lcore, 1, 0);
     906                 :          0 :         if (lcore == RTE_MAX_LCORE)
     907                 :          0 :                 rte_exit(EXIT_FAILURE,
     908                 :            :                                 "Max core limit %u reached for packet capture", lcore);
     909                 :          0 :         return lcore;
     910                 :            : }
     911                 :            : 
     912                 :            : static inline void
     913                 :          0 : dump_packets(void)
     914                 :            : {
     915                 :            :         int i;
     916                 :            :         unsigned int lcore_id = 0;
     917                 :            : 
     918                 :          0 :         if (num_tuples == 0)
     919                 :          0 :                 rte_exit(EXIT_FAILURE, "No device specified for capture\n");
     920                 :            : 
     921                 :          0 :         if (!multiple_core_capture) {
     922                 :            :                 printf(" core (%u), capture for (%d) tuples\n",
     923                 :            :                                 rte_lcore_id(), num_tuples);
     924                 :            : 
     925                 :          0 :                 for (i = 0; i < num_tuples; i++)
     926                 :          0 :                         printf(" - port %u device (%s) queue %u\n",
     927                 :          0 :                                 pdump_t[i].port,
     928                 :            :                                 pdump_t[i].device_id,
     929                 :          0 :                                 pdump_t[i].queue);
     930                 :            : 
     931                 :          0 :                 while (!quit_signal) {
     932                 :          0 :                         for (i = 0; i < num_tuples; i++)
     933                 :          0 :                                 pdump_packets(&pdump_t[i]);
     934                 :            :                 }
     935                 :            : 
     936                 :            :                 return;
     937                 :            :         }
     938                 :            : 
     939                 :            :         /* check if there enough core */
     940                 :          0 :         if ((uint32_t)num_tuples >= rte_lcore_count()) {
     941                 :            :                 printf("Insufficient cores to run parallel!\n");
     942                 :          0 :                 return;
     943                 :            :         }
     944                 :            : 
     945                 :          0 :         lcore_id = get_next_core(lcore_id);
     946                 :            : 
     947                 :          0 :         for (i = 0; i < num_tuples; i++) {
     948                 :          0 :                 rte_eal_remote_launch(dump_packets_core,
     949                 :          0 :                                 &pdump_t[i], lcore_id);
     950                 :          0 :                 lcore_id = get_next_core(lcore_id);
     951                 :            : 
     952                 :          0 :                 if (rte_eal_wait_lcore(lcore_id) < 0)
     953                 :          0 :                         rte_exit(EXIT_FAILURE, "failed to wait\n");
     954                 :            :         }
     955                 :            : 
     956                 :            :         /* main core */
     957                 :          0 :         while (!quit_signal)
     958                 :            :                 ;
     959                 :            : }
     960                 :            : 
     961                 :            : static void
     962                 :          0 : enable_primary_monitor(void)
     963                 :            : {
     964                 :            :         int ret;
     965                 :            : 
     966                 :            :         /* Once primary exits, so will pdump. */
     967                 :          0 :         ret = rte_eal_alarm_set(MONITOR_INTERVAL, monitor_primary, NULL);
     968                 :          0 :         if (ret < 0)
     969                 :            :                 printf("Fail to enable monitor:%d\n", ret);
     970                 :          0 : }
     971                 :            : 
     972                 :            : int
     973                 :          0 : main(int argc, char **argv)
     974                 :          0 : {
     975                 :            :         int diag;
     976                 :            :         int ret;
     977                 :            :         int i;
     978                 :            : 
     979                 :          0 :         char n_flag[] = "-n4";
     980                 :          0 :         char mp_flag[] = "--proc-type=secondary";
     981                 :          0 :         char *argp[argc + 2];
     982                 :            : 
     983                 :            :         /* catch ctrl-c so we can print on exit */
     984                 :          0 :         signal(SIGINT, signal_handler);
     985                 :            : 
     986                 :          0 :         argp[0] = argv[0];
     987                 :          0 :         argp[1] = n_flag;
     988                 :          0 :         argp[2] = mp_flag;
     989                 :            : 
     990                 :          0 :         for (i = 1; i < argc; i++)
     991                 :          0 :                 argp[i + 2] = argv[i];
     992                 :            : 
     993                 :            :         argc += 2;
     994                 :            : 
     995                 :          0 :         diag = rte_eal_init(argc, argp);
     996                 :          0 :         if (diag < 0)
     997                 :          0 :                 rte_panic("Cannot init EAL\n");
     998                 :            : 
     999                 :          0 :         if (rte_eth_dev_count_avail() == 0)
    1000                 :          0 :                 rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
    1001                 :            : 
    1002                 :          0 :         argc -= diag;
    1003                 :          0 :         argv += (diag - 2);
    1004                 :            : 
    1005                 :            :         /* parse app arguments */
    1006                 :          0 :         if (argc > 1) {
    1007                 :          0 :                 ret = launch_args_parse(argc, argv, argp[0]);
    1008                 :          0 :                 if (ret < 0)
    1009                 :          0 :                         rte_exit(EXIT_FAILURE, "Invalid argument\n");
    1010                 :            :         }
    1011                 :            : 
    1012                 :            :         /* create mempool, ring and vdevs info */
    1013                 :          0 :         create_mp_ring_vdev();
    1014                 :          0 :         enable_pdump();
    1015                 :          0 :         enable_primary_monitor();
    1016                 :          0 :         dump_packets();
    1017                 :            : 
    1018                 :          0 :         disable_primary_monitor();
    1019                 :          0 :         cleanup_pdump_resources();
    1020                 :            :         /* dump debug stats */
    1021                 :          0 :         print_pdump_stats();
    1022                 :            : 
    1023                 :          0 :         ret = rte_eal_cleanup();
    1024                 :          0 :         if (ret)
    1025                 :            :                 printf("Error from rte_eal_cleanup(), %d\n", ret);
    1026                 :            : 
    1027                 :            :         return 0;
    1028                 :            : }

Generated by: LCOV version 1.14