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

Generated by: LCOV version 1.14