LCOV - code coverage report
Current view: top level - root/contrail/vrouter/utils - dpdkinfo.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 59 182 32.4 %
Date: 2026-11-09 02:10:49 Functions: 7 8 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * dpdkinfo.c - CLI dpdkinfo to get info. about bond, lacp, mem etc.
       3             :  *
       4             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       5             :  * Copyright Contributors to the OpenSDN project
       6             :  */
       7             : 
       8             : #include <stdio.h>
       9             : #include <stdlib.h>
      10             : #include <unistd.h>
      11             : #include <string.h>
      12             : #include <errno.h>
      13             : #include <inttypes.h>
      14             : #include <stdlib.h>
      15             : #include <stdbool.h>
      16             : #include <getopt.h>
      17             : 
      18             : #include <sys/types.h>
      19             : #include <sys/socket.h>
      20             : 
      21             : #include <net/if.h>
      22             : 
      23             : #include "ini_parser.h"
      24             : #include "vr_os.h"
      25             : #include "vr_types.h"
      26             : #include "vr_nexthop.h"
      27             : #include "ini_parser.h"
      28             : #include "nl_util.h"
      29             : #include "ini_parser.h"
      30             : #include "vr_packet.h"
      31             : #include "vr_interface.h"
      32             : 
      33             : static struct nl_client *cl;
      34             : static bool dump_pending = false;
      35             : static int dump_marker = -1;
      36             : /* For supporting multiple CLI clients, Message buffer table id is stored and
      37             :  * resend if dump_pending is true */
      38             : /* Optional parameter: buffsz -> Send buffer size for the Output buffer(outbuf)
      39             :  * */
      40             : static int buff_table_id, buffsz;
      41             : 
      42             : static int help_set, ver_set, bond_set, lacp_set, mempool_set, stats_set,
      43             :              xstats_set, lcore_set, app_set, ddp_set, sock_dir_set, link_set;
      44             : static unsigned int core = (unsigned)-1;
      45             : static unsigned int stats_index = 0;
      46             : /* For few  CLI, Inbuf has to send to vrouter for processing(i.e kind of filter
      47             : */
      48             : static uint8_t *vr_info_inbuf;
      49             : 
      50             : static vr_info_msg_en msginfo;
      51             : 
      52             : enum opt_index {
      53             :     HELP_OPT_INDEX,
      54             :     VER_OPT_INDEX,
      55             :     BOND_OPT_INDEX,
      56             :     LACP_OPT_INDEX,
      57             :     MEMPOOL_OPT_INDEX,
      58             :     STATS_OPT_INDEX,
      59             :     XSTATS_OPT_INDEX,
      60             :     BUFFSZ_OPT_INDEX,
      61             :     LCORE_OPT_INDEX,
      62             :     APP_OPT_INDEX,
      63             :     DDP_OPT_INDEX,
      64             :     SOCK_DIR_OPT_INDEX,
      65             :     LINK_OPT_INDEX,
      66             :     MAX_OPT_INDEX,
      67             : };
      68             : 
      69             : static struct option long_options[] = {
      70             :     [HELP_OPT_INDEX]    =   {"help",    no_argument,        &help_set,      1},
      71             :     [VER_OPT_INDEX]    =   {"version",    no_argument,        &ver_set,      1},
      72             :     [BOND_OPT_INDEX]    =   {"bond",    no_argument,        &bond_set,      1},
      73             :     [LACP_OPT_INDEX]    =   {"lacp",    required_argument,        &lacp_set,      1},
      74             :     [MEMPOOL_OPT_INDEX] =   {"mempool", required_argument,        &mempool_set,      1},
      75             :     [STATS_OPT_INDEX]    =   {"stats",    required_argument,        &stats_set,      1},
      76             :     [XSTATS_OPT_INDEX]    =   {"xstats",  optional_argument,        &xstats_set,      1},
      77             :     [LCORE_OPT_INDEX]    =   {"lcore",    no_argument,        &lcore_set,      1},
      78             :     [APP_OPT_INDEX]    =   {"app",    no_argument,        &app_set,      1},
      79             :     [DDP_OPT_INDEX]    =   {"ddp",    required_argument,        &ddp_set,      1},
      80             :     [BUFFSZ_OPT_INDEX]  =   {"buffsz",  required_argument,  &buffsz,        1},
      81             :     [SOCK_DIR_OPT_INDEX]  = {"sock-dir", required_argument, &sock_dir_set,  1},
      82             :     [LINK_OPT_INDEX]    =   {"link", required_argument, &link_set,  1},
      83             :     [MAX_OPT_INDEX]     =   {NULL,    0,                  0,              0},
      84             : };
      85             : 
      86             : static void
      87           0 : Usage()
      88             : {
      89           0 :     printf("Usage: dpdkinfo [--help]\n");
      90           0 :     printf("                 --version|-v\
      91             :                                                       Show DPDK Version\n");
      92           0 :     printf("                 --bond|-b\
      93             :                                                          Show Master/Slave bond information\n");
      94           0 :     printf("                 --lacp|-l     <all/conf>\
      95             :                                           Show LACP information from DPDK\n");
      96           0 :     printf("                 --mempool|-m  <all/<mempool-name>>\
      97             :                                 Show Mempool information\n");
      98           0 :     printf("                 --stats|-n    <eth>\
      99             :                                                Show Stats information\n");
     100           0 :     printf("                 --xstats|-x   < =all/ =0(Master)/ =1(Slave(0))/ =2(Slave(1))>\
     101             :      Show Extended Stats information\n");
     102           0 :     printf("                 --lcore|-c\
     103             :                                                         Show Lcore information\n");
     104           0 :     printf("                 --app|-a\
     105             :                                                           Show App information\n");
     106           0 :     printf("                 --ddp|-d      <list>\
     107             :                                                    Show DDP information for X710 NIC\n");
     108           0 :     printf("       Optional: --buffsz      <value>\
     109             :                                              Send output buffer size (less than 1000Mb)\n");
     110           0 :     exit(-EINVAL);
     111             : }
     112             : 
     113             : static void
     114           1 : validate_options(void)
     115             : {
     116           1 :     if(!(ver_set || bond_set || lacp_set || mempool_set ||
     117           0 :         stats_set || xstats_set || lcore_set || app_set|| ddp_set || link_set))
     118           0 :         Usage();
     119             : 
     120           1 :     return;
     121             : }
     122             : 
     123             : /*
     124             :  * Response messages are sent through character buffer via Sandesh and it has
     125             :  * a limitation of sending upto 4K(PAGE_SIZE) for each iteration.
     126             :  * */
     127             : static void
     128           1 : dpdkinfo_resp_cb_process(void *s_req)
     129             : {
     130           1 :     int ret = 0;
     131           1 :     vr_info_req *resp = (vr_info_req *)s_req;
     132           1 :     if(resp != NULL && resp->vdu_proc_info) {
     133             :         /* Print the Message buffer(character buffer)
     134             :          * sent by vRouter(Server) */
     135           1 :         printf("%s", resp->vdu_proc_info);
     136             :     }
     137             : 
     138             :     /* For Sandesh DUMP, we should update the marker id and buff_table_id for
     139             :      * the next interation. */
     140           1 :     if (resp->h_op == SANDESH_OP_DUMP) {
     141           1 :         dump_marker = resp->vdu_index;
     142           1 :         buff_table_id = resp->vdu_buff_table_id;
     143             :     }
     144           1 : }
     145             : 
     146             : static void
     147           1 : response_process(void *s)
     148             : {
     149           1 :     vr_response_common_process((vr_response *)s, &dump_pending);
     150           1 : }
     151             : 
     152             : static void
     153           1 : dpdkinfo_fill_nl_callbacks()
     154             : {
     155           1 :     nl_cb.vr_info_req_process = dpdkinfo_resp_cb_process;
     156           1 :     nl_cb.vr_response_process = response_process;
     157           1 : }
     158             : 
     159             : static void
     160           2 : parse_long_opts(int opt_index, char *opt_arg)
     161             : {
     162           2 :     errno = 0;
     163             : 
     164           2 :     switch (opt_index) {
     165           0 :     case VER_OPT_INDEX:
     166           0 :         msginfo = INFO_VER_DPDK;
     167           0 :         break;
     168             : 
     169           0 :     case BOND_OPT_INDEX:
     170           0 :         msginfo = INFO_BOND;
     171           0 :         break;
     172             : 
     173           0 :     case LACP_OPT_INDEX:
     174           0 :         msginfo = INFO_LACP;
     175           0 :         if (!strcmp(opt_arg, "all") || !strcmp(opt_arg, "conf")){
     176           0 :             vr_info_inbuf = opt_arg;
     177             :         } else {
     178           0 :             Usage();
     179             :         }
     180           0 :         break;
     181             : 
     182           1 :     case MEMPOOL_OPT_INDEX:
     183           1 :         msginfo = INFO_MEMPOOL;
     184           1 :         vr_info_inbuf = opt_arg;
     185           1 :         break;
     186             : 
     187           0 :     case STATS_OPT_INDEX:
     188           0 :         msginfo = INFO_STATS;
     189           0 :         if (strcmp(opt_arg,"eth") == 0){
     190           0 :             vr_info_inbuf = opt_arg;
     191             :         } else {
     192           0 :             Usage();
     193             :         }
     194           0 :         break;
     195             : 
     196           0 :     case XSTATS_OPT_INDEX:
     197           0 :         msginfo = INFO_XSTATS;
     198           0 :         if (!opt_arg){
     199           0 :             opt_arg = "";
     200             :         }
     201           0 :         if (!strcmp(opt_arg, "all") || !strcmp(opt_arg, "") ||
     202           0 :             !strcmp(opt_arg, "0") || ((atoi(opt_arg) > 0) &&
     203           0 :                            (atoi(opt_arg) <= VR_INTERFACE_BOND_MAX_SLAVES))){
     204           0 :             vr_info_inbuf = opt_arg;
     205             :         } else {
     206           0 :             Usage();
     207             :         }
     208           0 :         break;
     209             : 
     210           0 :     case LCORE_OPT_INDEX:
     211           0 :         msginfo = INFO_LCORE;
     212           0 :         break;
     213             : 
     214           0 :     case APP_OPT_INDEX:
     215           0 :         msginfo = INFO_APP;
     216           0 :         break;
     217             : 
     218           0 :     case DDP_OPT_INDEX:
     219           0 :         msginfo = INFO_DDP;
     220           0 :         if (!strcmp(opt_arg, "list")){
     221           0 :             vr_info_inbuf = opt_arg;
     222             :         } else {
     223           0 :             Usage();
     224             :         }
     225           0 :         break;
     226             : 
     227           1 :     case SOCK_DIR_OPT_INDEX:
     228           1 :         vr_socket_dir = opt_arg;
     229           1 :         break;
     230             : 
     231           0 :     case BUFFSZ_OPT_INDEX:
     232             :         /* Setting buffsz limit to 1000Mb */
     233           0 :         if ((unsigned)strtol(opt_arg, NULL, 0) >= 0x3E800000){
     234           0 :             Usage();
     235             :         }
     236           0 :         buffsz = (unsigned)strtol(opt_arg, NULL, 0);
     237           0 :         break;
     238             : 
     239           0 :     case LINK_OPT_INDEX:
     240           0 :         msginfo = INFO_LINK;
     241           0 :         vr_info_inbuf = opt_arg;
     242           0 :         break;
     243             : 
     244           0 :     case HELP_OPT_INDEX:
     245             :     default:
     246           0 :         Usage();
     247             :     }
     248             : 
     249           2 :     return;
     250             : }
     251             : 
     252             : /* vr_get_dpdkinfo API send request to vRouter(server) and uses
     253             :  * h_op = DUMP for message request.
     254             :  *  */
     255             : static int
     256           1 : vr_get_dpdkinfo(struct nl_client *cl)
     257             : {
     258             :     int ret;
     259           1 :     bool dump = true;
     260             : 
     261           1 : op_retry:
     262           1 :     ret = vr_send_info_dump(cl, 0, dump_marker, buff_table_id, msginfo, buffsz,
     263             :             vr_info_inbuf);
     264           1 :     if (ret < 0)
     265           0 :         return ret;
     266             : 
     267           1 :     ret = vr_recvmsg(cl, dump);
     268           1 :     if (ret <= 0)
     269           0 :         return ret;
     270             : 
     271             :     /* Will loop through till it reaches end of buffer */
     272           1 :     if (dump_pending)
     273           0 :         goto op_retry;
     274           1 :     return 0;
     275             : }
     276             : 
     277             : int
     278           1 : main(int argc, char *argv[])
     279             : {
     280             :     char opt;
     281           1 :     int ret, option_index, log_core = 0, i = 0;
     282           1 :     int platform = 0;
     283             : 
     284             :     /* Register callback function for Netlink message */
     285           1 :     dpdkinfo_fill_nl_callbacks();
     286             : 
     287           1 :     parse_ini_file();
     288             : 
     289           3 :     while (((opt = getopt_long(argc, argv, "-:hvbl:m:sn:p:d:cax::",
     290           3 :                         long_options, &option_index)) >= 0)) {
     291           2 :         switch (opt) {
     292           0 :         case 'v':
     293           0 :             ver_set = 1;
     294           0 :             msginfo = INFO_VER_DPDK;
     295           0 :             break;
     296             : 
     297           0 :         case 'b':
     298           0 :             bond_set = 1;
     299           0 :             msginfo = INFO_BOND;
     300           0 :             break;
     301             : 
     302           0 :         case 'l':
     303           0 :             lacp_set = 1;
     304           0 :             msginfo = INFO_LACP;
     305           0 :             parse_long_opts(LACP_OPT_INDEX, optarg);
     306           0 :             break;
     307             : 
     308           0 :         case 'm':
     309           0 :             mempool_set = 1;
     310           0 :             msginfo = INFO_MEMPOOL;
     311           0 :             parse_long_opts(MEMPOOL_OPT_INDEX, optarg);
     312           0 :             break;
     313             : 
     314           0 :         case 'n':
     315           0 :             stats_set = 1;
     316           0 :             msginfo = INFO_STATS;
     317           0 :             parse_long_opts(STATS_OPT_INDEX, optarg);
     318           0 :             break;
     319             : 
     320           0 :         case 's':
     321           0 :             sock_dir_set = 1;
     322           0 :             parse_long_opts(SOCK_DIR_OPT_INDEX, optarg);
     323           0 :             break;
     324             : 
     325           0 :         case 'x':
     326           0 :             xstats_set = 1;
     327           0 :             msginfo = INFO_XSTATS;
     328           0 :             parse_long_opts(XSTATS_OPT_INDEX, optarg);
     329           0 :             break;
     330             : 
     331           0 :         case 'c':
     332           0 :             lcore_set = 1;
     333           0 :             msginfo = INFO_LCORE;
     334           0 :             break;
     335             : 
     336           0 :         case 'a':
     337           0 :             app_set = 1;
     338           0 :             msginfo = INFO_APP;
     339           0 :             break;
     340             : 
     341           0 :         case 'p':
     342           0 :             link_set = 1;
     343           0 :             msginfo = INFO_LINK;
     344           0 :             parse_long_opts(LINK_OPT_INDEX, optarg);
     345           0 :             break;
     346             : 
     347           0 :         case 'd':
     348           0 :             ddp_set = 1;
     349           0 :             msginfo = INFO_DDP;
     350           0 :             parse_long_opts(DDP_OPT_INDEX, optarg);
     351           0 :             break;
     352             : 
     353           2 :         case 0:
     354           2 :             parse_long_opts(option_index, optarg);
     355           2 :             break;
     356             : 
     357           0 :         case 'h':
     358             :         default:
     359           0 :             Usage();
     360             :         }
     361             :     }
     362           1 :     validate_options();
     363             : 
     364             :     /* Support for running from VTEST(vRouter UT Framework)*/
     365           1 :     if (sock_dir_set) {
     366           1 :         set_platform_vtest();
     367             :     }
     368           1 :     platform = get_platform();
     369           1 :     if ((platform != DPDK_PLATFORM) && (platform != VTEST_PLATFORM)) {
     370           0 :         Usage();
     371             :     }
     372             : 
     373           1 :     cl = vr_get_nl_client(VR_NETLINK_PROTO_DEFAULT);
     374           1 :     if (!cl)
     375           0 :         return -1;
     376             : 
     377           1 :     vr_get_dpdkinfo(cl);
     378             : 
     379           1 :     return 0;
     380             : }

Generated by: LCOV version 1.14