LCOV - code coverage report
Current view: top level - root/contrail/vrouter/utils - vif.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 267 1034 25.8 %
Date: 2026-11-09 02:10:49 Functions: 21 36 58.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * vif.c -- 'vrouter' interface utility
       3             :  *
       4             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       5             :  * Copyright Contributors to the OpenSDN project
       6             :  */
       7             : #include <stdio.h>
       8             : #include <assert.h>
       9             : #include <fcntl.h>
      10             : #include <unistd.h>
      11             : #include <string.h>
      12             : #include <stdlib.h>
      13             : #include <inttypes.h>
      14             : #include <getopt.h>
      15             : #include <stdbool.h>
      16             : #include <ctype.h>
      17             : #include <time.h>
      18             : 
      19             : #include "vr_os.h"
      20             : 
      21             : #include <sys/types.h>
      22             : #include <sys/socket.h>
      23             : #include <sys/ioctl.h>
      24             : 
      25             : #if defined(__linux__)
      26             : #include <asm/types.h>
      27             : 
      28             : #include <linux/netlink.h>
      29             : #include <linux/rtnetlink.h>
      30             : #include <linux/if_ether.h>
      31             : #endif
      32             : 
      33             : #if defined(__linux__)
      34             : #include <net/if.h>
      35             : #include <net/ethernet.h>
      36             : #include <netinet/ether.h>
      37             : #endif
      38             : 
      39             : #include <termios.h>
      40             : #include <sys/select.h>
      41             : #include <sys/time.h>
      42             : 
      43             : #include "vr_types.h"
      44             : #include "vr_message.h"
      45             : #include "vr_packet.h"
      46             : #include "vr_interface.h"
      47             : #include "vhost.h"
      48             : #include "vr_genetlink.h"
      49             : #include "nl_util.h"
      50             : #include "ini_parser.h"
      51             : 
      52             : 
      53             : #define LISTING_NUM_OF_LINE  3
      54             : #define MAX_OUTPUT_IF 32
      55             : 
      56             : #define SET_TIMEOUT_MS 1000
      57             : #define CORRECT_ERROR_CNT(cur_error_cnt_ptr, prev_error_cnt_ptr) \
      58             :     if (*((uint64_t *) cur_error_cnt_ptr) < *((uint64_t *) prev_error_cnt_ptr)) { \
      59             :        *((uint64_t *) cur_error_cnt_ptr) = *((uint64_t *) prev_error_cnt_ptr); }
      60             : 
      61             : #define COMPUTE_DIFFERENCE(new, old, counter, diff_time_ms) \
      62             :     new->counter = ((new->counter - old->counter) * 1000)/diff_time_ms
      63             : 
      64             : #define VHOST_TYPE_STRING           "vhost"
      65             : #define AGENT_TYPE_STRING           "agent"
      66             : #define PHYSICAL_TYPE_STRING        "physical"
      67             : #define VIRTUAL_TYPE_STRING         "virtual"
      68             : #define XEN_LL_TYPE_STRING          "xenll"
      69             : #define GATEWAY_TYPE_STRING         "gateway"
      70             : #define VIRTUAL_VLAN_TYPE_STRING    "virtual-vlan"
      71             : #define STATS_TYPE_STRING           "stats"
      72             : #define MONITORING_TYPE_STRING      "monitoring"
      73             : 
      74             : #define ETH_TRANSPORT_STRING        "eth"
      75             : #define PMD_TRASPORT_STRING         "pmd"
      76             : #define SOCKET_TRANSPORT_STRING     "socket"
      77             : #define VIRTUAL_TRANSPORT_STRING    "virtual"
      78             : 
      79             : static struct nl_client *cl;
      80             : static char flag_string[64], if_name[IFNAMSIZ];
      81             : static int if_kindex = -1, vrf_id, vr_ifindex = -1;
      82             : static int if_pmdindex = -1, vif_index = -1;
      83             : static bool need_xconnect_if = false;
      84             : static bool need_vif_id = false;
      85             : static int if_xconnect_kindex[VR_MAX_PHY_INF] = {-1, -1, -1};
      86             : static short vlan_id = -1;
      87             : static int vr_ifflags;
      88             : static unsigned int core = (unsigned)-1;
      89             : static int8_t vr_transport = 0;
      90             : 
      91             : static int add_set, create_set, get_set, list_set;
      92             : static int kindex_set, type_set, transport_set, help_set, set_set, vlan_set, dhcp_set;
      93             : static int vrf_set, mac_set, delete_set, policy_set, pmd_set, vindex_set, pci_set;
      94             : static int xconnect_set, vif_set, vhost_phys_set, core_set, rate_set, drop_set;
      95             : static int sock_dir_set, clear_stats_set;
      96             : 
      97             : static unsigned int vr_op, vr_if_type;
      98             : static bool dump_pending = false;
      99             : static bool vr_vrf_assign_dump = false;
     100             : static int dump_marker = -1, var_marker = -1;
     101             : 
     102             : static int platform;
     103             : 
     104             : static int8_t vr_ifmac[6];
     105             : static struct ether_addr *mac_opt;
     106             : 
     107             : static vr_interface_req prev_req[VR_MAX_INTERFACES];
     108             : static struct timeval last_time;
     109             : 
     110             : 
     111             : static bool first_rate_iter = false;
     112             : 
     113             : 
     114             : /*
     115             :  * How many times we partially ignore function call vr_interface_req_process.
     116             :  * For more information please read comment description for function:
     117             :  *  vr_interface_req_process
     118             :  */
     119             : static int ignore_number_interface = 0;
     120             : 
     121             : /*
     122             :  * How many interfaces we will print/count in rate statistics
     123             :  */
     124             : static int print_number_interface = 0;
     125             : 
     126             : static void Usage(void);
     127             : static void usage_internal(const char *msg);
     128             : static void list_header_print(void);
     129             : static void list_get_print(vr_interface_req *);
     130             : static void list_rate_print(vr_interface_req *);
     131             : static void rate_process(vr_interface_req *req, vr_interface_req *prev_req);
     132             : static void rate_stats_diff(vr_interface_req *, vr_interface_req *);
     133             : static void rate_stats(struct nl_client *, unsigned int);
     134             : static int is_stdin_hit();
     135             : static int is_number(const char *nptr);
     136             : 
     137             : static struct vr_util_flags flag_metadata[] = {
     138             :     {VIF_FLAG_POLICY_ENABLED,   "P",        "Policy"            },
     139             :     {VIF_FLAG_XCONNECT,         "X",        "Cross Connect"     },
     140             :     {VIF_FLAG_SERVICE_IF,       "S",        "Service Chain"     },
     141             :     {VIF_FLAG_MIRROR_RX,        "Mr",       "Receive Mirror"    },
     142             :     {VIF_FLAG_MIRROR_TX,        "Mt",       "Transmit Mirror"   },
     143             :     {VIF_FLAG_TX_CSUM_OFFLOAD,  "Tc",       "Transmit Checksum Offload"},
     144             :     {VIF_FLAG_L3_ENABLED,       "L3",       "Layer 3"           },
     145             :     {VIF_FLAG_L2_ENABLED,       "L2",       "Layer 2"           },
     146             :     {VIF_FLAG_DHCP_ENABLED,     "D",        "DHCP"              },
     147             :     {VIF_FLAG_VHOST_PHYS,       "Vp",       "Vhost Physical"    },
     148             :     {VIF_FLAG_PROMISCOUS,       "Pr",       "Promiscuous"       },
     149             :     {VIF_FLAG_NATIVE_VLAN_TAG,  "Vnt",      "Native Vlan Tagged"},
     150             :     {VIF_FLAG_NO_ARP_PROXY,     "Mnp",      "No MAC Proxy"      },
     151             :     {VIF_FLAG_PMD,              "Dpdk",     "DPDK PMD Interface"},
     152             :     {VIF_FLAG_FILTERING_OFFLOAD,"Rfl",      "Receive Filtering Offload"},
     153             :     {VIF_FLAG_MONITORED,        "Mon",      "Interface is Monitored"},
     154             :     {VIF_FLAG_UNKNOWN_UC_FLOOD, "Uuf",      "Unknown Unicast Flood"},
     155             :     {VIF_FLAG_VLAN_OFFLOAD,     "Vof",      "VLAN insert/strip offload"},
     156             :     {VIF_FLAG_DROP_NEW_FLOWS,   "Df",       "Drop New Flows"},
     157             :     {VIF_FLAG_MAC_LEARN,        "L",        "MAC Learning Enabled"},
     158             :     {VIF_FLAG_MAC_PROXY,        "Proxy",    "MAC Requests Proxied Always"},
     159             :     {VIF_FLAG_ETREE_ROOT,       "Er",       "Etree Root"},
     160             :     {VIF_FLAG_MIRROR_NOTAG,     "Mn",       "Mirror without Vlan Tag"},
     161             :     {VIF_FLAG_HBS_LEFT,         "HbsL",     "HBS Left Intf"},
     162             :     {VIF_FLAG_HBS_RIGHT,        "HbsR",     "HBS Right Intf"},
     163             :     {VIF_FLAG_IGMP_ENABLED,     "Ig",       "Igmp Trap Enabled"},
     164             :     {VIF_FLAG_MAC_IP_LEARNING,  "Ml",       "MAC-IP Learning Enabled"},
     165             : };
     166             : 
     167             : static char *
     168           3 : vr_get_if_type_string(int t)
     169             : {
     170           3 :     switch (t) {
     171           3 :     case VIF_TYPE_HOST:
     172           3 :         return "Host";
     173           0 :     case VIF_TYPE_AGENT:
     174           0 :         return "Agent";
     175           0 :     case VIF_TYPE_PHYSICAL:
     176           0 :         return "Physical";
     177           0 :     case VIF_TYPE_VIRTUAL:
     178           0 :         return "Virtual";
     179           0 :     case VIF_TYPE_XEN_LL_HOST:
     180           0 :         return "XenLL";
     181           0 :     case VIF_TYPE_GATEWAY:
     182           0 :         return "Gateway";
     183           0 :     case VIF_TYPE_STATS:
     184           0 :         return "Stats";
     185           0 :     case VIF_TYPE_VIRTUAL_VLAN:
     186           0 :         return "Virtual(Vlan)";
     187           0 :     case VIF_TYPE_MONITORING:
     188           0 :         return "Monitoring";
     189           0 :     default:
     190           0 :         return "Invalid";
     191             :     }
     192             : 
     193             :     return NULL;
     194             : }
     195             : 
     196             : static unsigned int
     197           0 : vr_get_if_type(char *type_str)
     198             : {
     199           0 :     if (!strncmp(type_str, VHOST_TYPE_STRING,
     200             :                 strlen(VHOST_TYPE_STRING)))
     201           0 :         return VIF_TYPE_HOST;
     202           0 :     else if (!strncmp(type_str, AGENT_TYPE_STRING,
     203             :                 strlen(AGENT_TYPE_STRING)))
     204           0 :         return VIF_TYPE_AGENT;
     205           0 :     else if (!strncmp(type_str, PHYSICAL_TYPE_STRING,
     206             :                 strlen(PHYSICAL_TYPE_STRING)))
     207           0 :         return VIF_TYPE_PHYSICAL;
     208           0 :     else if (!strncmp(type_str, VIRTUAL_VLAN_TYPE_STRING,
     209             :                 strlen(VIRTUAL_VLAN_TYPE_STRING)))
     210           0 :         return VIF_TYPE_VIRTUAL_VLAN;
     211           0 :     else if (!strncmp(type_str, VIRTUAL_TYPE_STRING,
     212             :                 strlen(VIRTUAL_TYPE_STRING)))
     213           0 :         return VIF_TYPE_VIRTUAL;
     214           0 :     else if (!strncmp(type_str, XEN_LL_TYPE_STRING,
     215             :                 strlen(XEN_LL_TYPE_STRING)))
     216           0 :         return VIF_TYPE_XEN_LL_HOST;
     217           0 :     else if (!strncmp(type_str, GATEWAY_TYPE_STRING,
     218             :                 strlen(GATEWAY_TYPE_STRING)))
     219           0 :         return VIF_TYPE_GATEWAY;
     220           0 :     else if (!strncmp(type_str, STATS_TYPE_STRING,
     221             :                 strlen(STATS_TYPE_STRING)))
     222           0 :         return VIF_TYPE_STATS;
     223           0 :     else if (!strncmp(type_str, MONITORING_TYPE_STRING,
     224             :                 strlen(MONITORING_TYPE_STRING)))
     225           0 :         return VIF_TYPE_MONITORING;
     226             :     else
     227           0 :         Usage();
     228             : 
     229           0 :     return 0;
     230             : }
     231             : 
     232             : static unsigned int
     233           0 : vr_get_if_transport(char *transport_str)
     234             : {
     235           0 :     if (!strncmp(transport_str, ETH_TRANSPORT_STRING,
     236             :                 strlen(ETH_TRANSPORT_STRING)))
     237           0 :         return VIF_TRANSPORT_ETH;
     238           0 :     else if (!strncmp(transport_str, PMD_TRASPORT_STRING,
     239             :                 strlen(PMD_TRASPORT_STRING)))
     240           0 :         return VIF_TRANSPORT_PMD;
     241           0 :     else if (!strncmp(transport_str, VIRTUAL_TRANSPORT_STRING,
     242             :                 strlen(VIRTUAL_TRANSPORT_STRING)))
     243           0 :         return VIF_TRANSPORT_VIRTUAL;
     244           0 :     else if (!strncmp(transport_str, SOCKET_TRANSPORT_STRING,
     245             :                 strlen(SOCKET_TRANSPORT_STRING)))
     246           0 :         return VIF_TRANSPORT_SOCKET;
     247             :     else
     248           0 :         Usage();
     249             : 
     250           0 :     return 0;
     251             : }
     252             : 
     253             : static char *
     254           3 : vr_if_flags(int flags)
     255             : {
     256             :     unsigned int i, array_size;
     257           3 :     unsigned int all_len = 0;
     258           3 :     memset(flag_string, 0, sizeof(flag_string));
     259             : 
     260           3 :     array_size = sizeof(flag_metadata) / sizeof(flag_metadata[0]);
     261          84 :     for (i = 0; i < array_size; i++) {
     262          81 :       if (flags & flag_metadata[i].vuf_flag) {
     263             :         unsigned int flag_len;
     264           8 :         flag_len = strlen(flag_metadata[i].vuf_flag_symbol);
     265           8 :         if (all_len + flag_len < sizeof(flag_string)) {
     266           8 :           strcat(flag_string, flag_metadata[i].vuf_flag_symbol);
     267           8 :           all_len += flag_len;
     268             :         }
     269             :         else
     270           0 :           break;
     271             :       }
     272             :     }
     273             : 
     274           3 :     return flag_string;
     275             : }
     276             : 
     277             : static void
     278           3 : vr_interface_print_header(void)
     279             : {
     280             :     unsigned int i, array_size;
     281             : 
     282           3 :     array_size = sizeof(flag_metadata) / sizeof(flag_metadata[0]);
     283             : 
     284           3 :     printf("Vrouter Interface Table\n\n");
     285             : 
     286           3 :     printf("Flags: ");
     287             : 
     288          84 :     for (i = 0; i < array_size; i++) {
     289          81 :         if (i) {
     290          78 :             if (!(i % 4))
     291          18 :                 printf("\n       ");
     292             :             else
     293          60 :                 printf(", ");
     294             :         }
     295          81 :         printf("%s=%s", flag_metadata[i].vuf_flag_symbol,
     296             :                 flag_metadata[i].vuf_flag_string);
     297             :     }
     298             : 
     299           3 :     printf("\n\n");
     300           3 :     return;
     301             : }
     302             : 
     303             : static void
     304           0 : drop_stats_req_process(void *s_req)
     305             : {
     306           0 :     vr_drop_stats_req *stats = (vr_drop_stats_req *)s_req;
     307           0 :     vr_print_drop_stats(stats, core);
     308             : 
     309           0 :     return;
     310             : }
     311             : 
     312             : static void
     313           0 : vrf_assign_req_process(void *s)
     314             : {
     315           0 :     vr_vrf_assign_req *req = (vr_vrf_assign_req *)s;
     316             : 
     317           0 :     printf("%d:%d, ", req->var_vlan_id, req->var_vif_vrf);
     318           0 :     var_marker = req->var_vlan_id;
     319             : 
     320           0 :     return;
     321             : }
     322             : 
     323             : static int
     324          21 : vr_interface_print_head_space(void)
     325             : {
     326             :     int i;
     327             : 
     328         273 :     for (i = 0; i < 12; i++)
     329         252 :         printf(" ");
     330          21 :     return i;
     331             : }
     332             : 
     333             : char *
     334           3 : vr_if_transport_string(vr_interface_req *req)
     335             : {
     336           3 :     switch (req->vifr_transport) {
     337           0 :     case VIF_TRANSPORT_VIRTUAL:
     338           0 :         return "Virtual";
     339             :         break;
     340             : 
     341           0 :     case VIF_TRANSPORT_ETH:
     342           0 :         return "Ethernet";
     343             :         break;
     344             : 
     345           3 :     case VIF_TRANSPORT_PMD:
     346           3 :         return "PMD";
     347             :         break;
     348             : 
     349           0 :     case VIF_TRANSPORT_SOCKET:
     350           0 :         return "Socket";
     351             :         break;
     352             : 
     353           0 :     default:
     354           0 :         break;
     355             :     }
     356             : 
     357           0 :     return "Unknown";
     358             : }
     359             : 
     360             : static void
     361           9 : vr_interface_core_print(void)
     362             : {
     363           9 :     if (core != (unsigned)-1) {
     364           0 :         printf("Core %u ", core);
     365             :     }
     366           9 : }
     367             : 
     368             : static void
     369           9 : vr_interface_nombufs_print(uint64_t nombufs)
     370             : {
     371           9 :     if (nombufs)
     372           0 :         printf(" no mbufs:%" PRId64, nombufs);
     373           9 :     printf("\n");
     374           9 : }
     375             : 
     376             : static void
     377          12 : vr_interface_pbem_counters_print(const char *title, bool print_always,
     378             :             uint64_t packets, uint64_t bytes, uint64_t errors,
     379             :             uint64_t nombufs)
     380             : {
     381          12 :     if (print_always || packets || bytes || errors) {
     382           6 :         vr_interface_print_head_space();
     383           6 :         vr_interface_core_print();
     384           6 :         printf("%s packets:%" PRId64 "  bytes:%" PRId64 " errors:%" PRId64,
     385             :                 title, packets, bytes, errors);
     386           6 :         vr_interface_nombufs_print(nombufs);
     387             :     }
     388          12 : }
     389             : 
     390             : static void
     391           6 : vr_interface_pesm_counters_print(const char *title, bool print_always,
     392             :             uint64_t packets, uint64_t errors, uint64_t syscalls,
     393             :             uint64_t nombufs)
     394             : {
     395           6 :     if (print_always || packets || errors) {
     396           3 :         vr_interface_print_head_space();
     397           3 :         vr_interface_core_print();
     398           3 :         printf("%s packets:%" PRId64 " errors:%" PRId64,
     399             :                 title, packets, errors);
     400           3 :         if (syscalls)
     401           0 :             printf(" syscalls:%" PRId64, syscalls);
     402           3 :         vr_interface_nombufs_print(nombufs);
     403             :     }
     404           6 : }
     405             : 
     406             : static void
     407           6 : vr_interface_pe_counters_print(const char *title, bool print_always,
     408             :             uint64_t packets, uint64_t errors)
     409             : {
     410           6 :     if (print_always || packets || errors) {
     411           0 :         vr_interface_print_head_space();
     412           0 :         vr_interface_core_print();
     413           0 :         printf("%s packets:%" PRId64 " errors:%" PRId64 "\n",
     414             :                 title, packets, errors);
     415             :     }
     416           6 : }
     417             : 
     418             : static void
     419           3 : vr_interface_e_per_lcore_counters_print(const char *title, bool print_always,
     420             :             uint64_t *errors, uint32_t size)
     421             : {
     422             :     unsigned int i;
     423             : 
     424           3 :     vr_interface_print_head_space();
     425           3 :     printf("%s errors to lcore", title);
     426          39 :     for (i = 0; i < size; i++) {
     427          36 :         printf(" %" PRId64 , errors[i]);
     428             :     }
     429           3 :     printf("\n");
     430           3 : }
     431             : 
     432             : /* Display Fabric(Master) & bond Slave information only on DPDK platforms */
     433             : static void
     434           0 : vr_interface_fabric_info(vr_interface_req *req)
     435             : {
     436             : 
     437             :     int i;
     438             :     char *p_name, *p_drv_name ;
     439           0 :     const char *fabric_link[] = {"DOWN", "UP"};
     440             : 
     441           0 :     if(req->vifr_type != VIF_TYPE_PHYSICAL)
     442           0 :         return;
     443             : 
     444           0 :     vr_interface_print_head_space();
     445           0 :     printf("Fabric Interface: %s  Status: %s  Driver: %s\n",
     446           0 :             req->vifr_fab_name, fabric_link[(req->vifr_intf_status &
     447             :                 0x01)], req->vifr_fab_drv_name);
     448             : 
     449           0 :     p_name = req->vifr_bond_slave_name;
     450           0 :     p_drv_name = req->vifr_bond_slave_drv_name;
     451             : 
     452           0 :     for(i = 0; i < req->vifr_num_bond_slave; i++) {
     453           0 :         vr_interface_print_head_space();
     454           0 :         printf("Slave Interface(%d): %s  Status: %s  Driver: %s\n",
     455           0 :                 i, p_name, fabric_link[(req->vifr_intf_status >>
     456           0 :                     (i + 1)) & 0x01], p_drv_name);
     457             : 
     458           0 :         p_name = strchr(p_name, '\0'); p_name++;
     459           0 :         p_drv_name = strchr(p_drv_name, '\0'); p_drv_name++;
     460             :     }
     461             : }
     462             : 
     463             : /* Display VLAN ID & VLAN fwd interface only on DPDK platforms */
     464             : static void
     465           0 : vr_interface_vlan_info(vr_interface_req *req)
     466             : {
     467           0 :     if(req->vifr_type != VIF_TYPE_PHYSICAL)
     468           0 :         return;
     469             : 
     470           0 :     if(req->vifr_vlan_tag != VLAN_ID_INVALID && req->vifr_vlan_name != NULL ) {
     471           0 :         vr_interface_print_head_space();
     472           0 :         printf("Vlan Id: %d",req->vifr_vlan_tag);
     473           0 :         if(strlen(req->vifr_vlan_name))
     474           0 :             printf(" VLAN fwd Interface: %s",req->vifr_vlan_name);
     475           0 :         printf("\n");
     476             :     }
     477             : }
     478             : 
     479             : static void
     480           3 : list_get_print(vr_interface_req *req)
     481             : {
     482             :     char ip6_addr[INET6_ADDRSTRLEN], ip_addr[INET_ADDRSTRLEN],
     483           3 :          name[50] = {0}, ip6_ip[16];
     484           3 :     bool print_zero = false;
     485             :     uint16_t proto, port, port_data;
     486           3 :     int printed = 0, len;
     487             :     unsigned int i;
     488             :     uint64_t *tmp;
     489             :     uint8_t aggr_data;
     490             :     uint32_t *ip;
     491             : 
     492           3 :     if (rate_set) {
     493           0 :         print_zero = true;
     494             :     }
     495             : 
     496           3 :     printed = printf("vif%d/%d", req->vifr_rid, req->vifr_idx);
     497          12 :     for (; printed < 12; printed++)
     498           9 :         printf(" ");
     499             : 
     500           3 :     if (req->vifr_flags & VIF_FLAG_PMD) {
     501           0 :         printf("PMD: %d", req->vifr_os_idx);
     502           3 :     } else if (platform == DPDK_PLATFORM || platform == VTEST_PLATFORM) {
     503           3 :         switch (req->vifr_type) {
     504           0 :             case VIF_TYPE_PHYSICAL:
     505           0 :                 if(req->vifr_flags & VIF_FLAG_MOCK_DEVICE)
     506           0 :                     printf("PCI: Mock");
     507             :                 else
     508           0 :                     printf("PCI: ""%.4" PRIx16 ":%.2" PRIx8 ":%.2" PRIx8 ".%" PRIx8,
     509           0 :                             (uint16_t)(req->vifr_os_idx >> 16),
     510           0 :                             (uint8_t)(req->vifr_os_idx >> 8) & 0xFF,
     511           0 :                             (uint8_t)(req->vifr_os_idx >> 3) & 0x1F,
     512           0 :                             (uint8_t)(req->vifr_os_idx & 0x7));
     513           0 :                 break;
     514             : 
     515           0 :             case VIF_TYPE_MONITORING:
     516           0 :                 printf("Monitoring: %s for vif%d/%d", req->vifr_name,
     517             :                         req->vifr_rid, req->vifr_os_idx);
     518           0 :                 break;
     519             : 
     520           3 :             default:
     521           3 :                 if (req->vifr_name)
     522           3 :                     printf("%s: %s", vr_if_transport_string(req),
     523             :                             req->vifr_name);
     524           3 :                 if (req->vifr_flags & VIF_FLAG_MOCK_DEVICE)
     525           3 :                     printf(" Mock");
     526           3 :                 break;
     527             :         }
     528             : 
     529             :     } else {
     530           0 :         if (req->vifr_os_idx > 0) {
     531           0 :             printf("OS: %s", if_indextoname(req->vifr_os_idx, name));
     532             :         } else {
     533           0 :             printf("    %s", req->vifr_name);
     534             :         }
     535             :     }
     536             : 
     537           3 :     if ((req->vifr_type == VIF_TYPE_PHYSICAL) &&
     538           0 :             (!(req->vifr_flags & VIF_FLAG_MOCK_DEVICE))) {
     539           0 :         if (req->vifr_speed >= 0) {
     540           0 :             printf(" (Speed %d,", req->vifr_speed);
     541           0 :             if (req->vifr_duplex >= 0)
     542           0 :                 printf(" Duplex %d", req->vifr_duplex);
     543           0 :             printf(")");
     544             :         }
     545           3 :     } else if (req->vifr_type == VIF_TYPE_VIRTUAL_VLAN) {
     546           0 :         printf(" Vlan(o/i)(,S): %d/%d", req->vifr_ovlan_id, req->vifr_vlan_id);
     547           0 :         if (req->vifr_src_mac_size && req->vifr_src_mac) {
     548           0 :             for (i = 0; i < (req->vifr_src_mac_size / VR_ETHER_ALEN); i = i + 1) {
     549           0 :                 printf(", "MAC_FORMAT, MAC_VALUE((uint8_t *)
     550             :                             (req->vifr_src_mac + (i * VR_ETHER_ALEN))));
     551           0 :                 printf(" Bridge Index: %d", req->vifr_bridge_idx[i]);
     552             :             }
     553             :         }
     554             :     }
     555             : 
     556           3 :     if (req->vifr_parent_vif_idx >= 0)
     557           0 :         printf(" Parent:vif0/%d", req->vifr_parent_vif_idx);
     558             : 
     559           3 :     if (req->vifr_nh_id != 0)
     560           0 :         printf(" NH: %d", req->vifr_nh_id);
     561             : 
     562           3 :     printf("\n");
     563             : 
     564           3 :     vr_interface_print_head_space();
     565           3 :     printf("Type:%s HWaddr:"MAC_FORMAT" IPaddr:%s\n",
     566             :             vr_get_if_type_string(req->vifr_type),
     567           3 :             MAC_VALUE((uint8_t *)req->vifr_mac), inet_ntop(AF_INET,
     568           3 :                 &req->vifr_ip, ip_addr, INET_ADDRSTRLEN));
     569           3 :     if (req->vifr_ip6_u || req->vifr_ip6_l) {
     570           0 :         tmp = (uint64_t *)ip6_ip;
     571           0 :         *tmp = req->vifr_ip6_u;
     572           0 :         *(tmp + 1) = req->vifr_ip6_l;
     573           0 :         vr_interface_print_head_space();
     574           0 :         printf("IP6addr:%s\n", inet_ntop(AF_INET6, ip6_ip, ip6_addr,
     575             :                                                     INET6_ADDRSTRLEN));
     576             :     }
     577           3 :     vr_interface_print_head_space();
     578           3 :     printf("Vrf:%d Mcast Vrf:%d Flags:%s QOS:%d Ref:%d", req->vifr_vrf,
     579           3 :             req->vifr_mcast_vrf, req->vifr_flags ?
     580           3 :             vr_if_flags(req->vifr_flags) : "NULL" ,
     581           3 :             req->vifr_qos_map_index, req->vifr_ref_cnt);
     582           3 :     if (req->vifr_flags & (VIF_FLAG_MIRROR_TX | VIF_FLAG_MIRROR_RX)) {
     583           0 :         printf(" Mirror index %d\n", req->vifr_mir_id);
     584             :     } else {
     585           3 :         printf("\n");
     586             :     }
     587             : 
     588           3 :     if (platform == DPDK_PLATFORM || platform == VTEST_PLATFORM) {
     589           3 :         vr_interface_pbem_counters_print("RX device", print_zero,
     590           3 :                 req->vifr_dev_ipackets, req->vifr_dev_ibytes,
     591           3 :                 req->vifr_dev_ierrors, req->vifr_dev_inombufs);
     592           3 :         vr_interface_pesm_counters_print("RX port  ", print_zero,
     593           3 :                 req->vifr_port_ipackets, req->vifr_port_ierrors,
     594           3 :                 req->vifr_port_isyscalls, req->vifr_port_inombufs);
     595           3 :         vr_interface_pe_counters_print("RX queue ", print_zero,
     596           3 :                 req->vifr_queue_ipackets, req->vifr_queue_ierrors);
     597             : 
     598           3 :         vr_interface_e_per_lcore_counters_print("RX queue", print_zero,
     599           3 :                 req->vifr_queue_ierrors_to_lcore,
     600             :                 req->vifr_queue_ierrors_to_lcore_size);
     601             :         /* Bond Master(Fabric)/slave, VLAN info not valid on vtest platforms */
     602           3 :         if(platform != VTEST_PLATFORM) {
     603           0 :             vr_interface_fabric_info(req);
     604           0 :             vr_interface_vlan_info(req);
     605             :         }
     606             :     }
     607             : 
     608           3 :     vr_interface_pbem_counters_print("RX", true, req->vifr_ipackets,
     609           3 :             req->vifr_ibytes, req->vifr_ierrors, 0);
     610           3 :     vr_interface_pbem_counters_print("TX", true, req->vifr_opackets,
     611           3 :             req->vifr_obytes, req->vifr_oerrors, 0);
     612           3 :     if (req->vifr_isid || req->vifr_pbb_mac_size) {
     613           0 :         vr_interface_print_head_space();
     614           0 :         printf("ISID: %d Bmac: "MAC_FORMAT"\n",
     615           0 :                 req->vifr_isid, MAC_VALUE((uint8_t *)req->vifr_pbb_mac));
     616             :     }
     617           3 :     vr_interface_print_head_space();
     618           3 :     printf("Drops:%" PRIu64 "\n", req->vifr_dpackets);
     619             : 
     620             : 
     621           3 :     if (req->vifr_in_mirror_md_size) {
     622           0 :         printed = vr_interface_print_head_space();
     623           0 :         len = printf("Ingress Mirror Metadata: ");
     624           0 :         printed += len;
     625           0 :         for (i = 0; i < req->vifr_in_mirror_md_size; i++) {
     626           0 :             printed += printf("%x ", 0xFF & req->vifr_in_mirror_md[i]);
     627           0 :             if (printed > 68) {
     628           0 :                 printf("\n");
     629           0 :                 printed = vr_interface_print_head_space();
     630           0 :                 printf("%*c", len, ' ');
     631           0 :                 printed += len;
     632             :             }
     633             :         }
     634           0 :         printf("\n");
     635             :     }
     636             : 
     637           3 :     if (req->vifr_out_mirror_md_size) {
     638           0 :         printed = vr_interface_print_head_space();
     639           0 :         len = printf("Egress Mirror Metadata: ");
     640           0 :         printed += len;
     641           0 :         for (i = 0; i < req->vifr_out_mirror_md_size; i++) {
     642           0 :             printed += printf("%x ", 0xFF & req->vifr_out_mirror_md[i]);
     643           0 :             if (printed > 68) {
     644           0 :                 printf("\n");
     645           0 :                 printed = vr_interface_print_head_space();
     646           0 :                 printf("%*c", len, ' ');
     647           0 :                 printed += len;
     648             :             }
     649             :         }
     650           0 :         printf("\n");
     651             : 
     652             :     }
     653             : 
     654           3 :     if (platform == DPDK_PLATFORM || platform == VTEST_PLATFORM) {
     655           3 :         vr_interface_pe_counters_print("TX queue ", print_zero,
     656           3 :                 req->vifr_queue_opackets, req->vifr_queue_oerrors);
     657           3 :         vr_interface_pesm_counters_print("TX port  ", print_zero,
     658           3 :                 req->vifr_port_opackets, req->vifr_port_oerrors,
     659           3 :                 req->vifr_port_osyscalls, 0);
     660           3 :         vr_interface_pbem_counters_print("TX device", print_zero,
     661           3 :                 req->vifr_dev_opackets, req->vifr_dev_obytes,
     662           3 :                 req->vifr_dev_oerrors, 0);
     663             :     }
     664             : 
     665           3 :     if (req->vifr_fat_flow_protocol_port_size) {
     666           0 :         printf("\n");
     667           0 :         vr_interface_print_head_space();
     668           0 :         printf("FatFlow rules: \n");
     669           0 :         for (i = 0; i < req->vifr_fat_flow_protocol_port_size; i++) {
     670           0 :             proto = VIF_FAT_FLOW_PROTOCOL(req->vifr_fat_flow_protocol_port[i]);
     671           0 :             port = VIF_FAT_FLOW_PORT(req->vifr_fat_flow_protocol_port[i]);
     672           0 :             port_data = VIF_FAT_FLOW_PORT_DATA(req->vifr_fat_flow_protocol_port[i]);
     673           0 :             aggr_data = VIF_FAT_FLOW_PREFIX_AGGR_DATA(req->vifr_fat_flow_protocol_port[i]);
     674           0 :             if (!proto) {
     675           0 :                 proto = port;
     676           0 :                 port = 0;
     677             :             }
     678             : 
     679           0 :             vr_interface_print_head_space();
     680           0 :             printf("\t");
     681           0 :             printf("%d:", proto);
     682           0 :             if (port) {
     683           0 :                 printf("%d ", port);
     684             :             } else {
     685           0 :                 printf("%c", '*');
     686             :             }
     687           0 :             if (port_data == VIF_FAT_FLOW_PORT_SIP_IGNORE)
     688           0 :                 printf(" - Sip");
     689           0 :             if (port_data == VIF_FAT_FLOW_PORT_DIP_IGNORE)
     690           0 :                 printf(" - Dip");
     691             : 
     692           0 :             switch (aggr_data) {
     693           0 :                 case VR_AGGREGATE_SRC_IPV4:
     694           0 :                      ip = (uint32_t *) &req->vifr_fat_flow_src_prefix_l[i];
     695           0 :                      printf(" AggrSrc %s/%d %d",
     696             :                             inet_ntop(AF_INET, ip, ip_addr, INET_ADDRSTRLEN),
     697           0 :                             req->vifr_fat_flow_src_prefix_mask[i],
     698           0 :                             req->vifr_fat_flow_src_aggregate_plen[i]);
     699           0 :                      break;
     700           0 :                 case VR_AGGREGATE_DST_IPV4:
     701           0 :                      ip = (uint32_t *) &req->vifr_fat_flow_dst_prefix_l[i];
     702           0 :                      printf(" AggrDst %s/%d %d",
     703             :                             inet_ntop(AF_INET, ip, ip_addr, INET_ADDRSTRLEN),
     704           0 :                             req->vifr_fat_flow_dst_prefix_mask[i],
     705           0 :                             req->vifr_fat_flow_dst_aggregate_plen[i]);
     706           0 :                      break;
     707           0 :                 case VR_AGGREGATE_SRC_DST_IPV4:
     708           0 :                      ip = (uint32_t *) &req->vifr_fat_flow_src_prefix_l[i];
     709           0 :                      printf(" AggrSrc %s/%d %d",
     710             :                             inet_ntop(AF_INET, ip, ip_addr, INET_ADDRSTRLEN),
     711           0 :                             req->vifr_fat_flow_src_prefix_mask[i],
     712           0 :                             req->vifr_fat_flow_src_aggregate_plen[i]);
     713           0 :                      ip = (uint32_t *) &req->vifr_fat_flow_dst_prefix_l[i];
     714           0 :                      printf(" AggrDst %s/%d %d",
     715             :                             inet_ntop(AF_INET, ip, ip_addr, INET_ADDRSTRLEN),
     716           0 :                             req->vifr_fat_flow_dst_prefix_mask[i],
     717           0 :                             req->vifr_fat_flow_dst_aggregate_plen[i]);
     718           0 :                      break;
     719           0 :                 case VR_AGGREGATE_SRC_IPV6:
     720           0 :                      tmp = (uint64_t *)ip6_ip;
     721           0 :                      *tmp = req->vifr_fat_flow_src_prefix_h[i];
     722           0 :                      *(tmp + 1) = req->vifr_fat_flow_src_prefix_l[i];
     723           0 :                      printf(" AggrSrc %s/%d %d",
     724             :                             inet_ntop(AF_INET6, ip6_ip, ip6_addr, INET6_ADDRSTRLEN),
     725           0 :                             req->vifr_fat_flow_src_prefix_mask[i],
     726           0 :                             req->vifr_fat_flow_src_aggregate_plen[i]);
     727           0 :                      break;
     728           0 :                 case VR_AGGREGATE_DST_IPV6:
     729           0 :                      tmp = (uint64_t *)ip6_ip;
     730           0 :                      *tmp = req->vifr_fat_flow_dst_prefix_h[i];
     731           0 :                      *(tmp + 1) = req->vifr_fat_flow_dst_prefix_l[i];
     732           0 :                      printf(" AggrDst %s/%d %d",
     733             :                             inet_ntop(AF_INET6, ip6_ip, ip6_addr, INET6_ADDRSTRLEN),
     734           0 :                             req->vifr_fat_flow_dst_prefix_mask[i],
     735           0 :                             req->vifr_fat_flow_dst_aggregate_plen[i]);
     736           0 :                      break;
     737           0 :                 case VR_AGGREGATE_SRC_DST_IPV6:
     738           0 :                      tmp = (uint64_t *)ip6_ip;
     739           0 :                      *tmp = req->vifr_fat_flow_src_prefix_h[i];
     740           0 :                      *(tmp + 1) = req->vifr_fat_flow_src_prefix_l[i];
     741           0 :                      printf(" AggrSrc %s/%d %d",
     742             :                             inet_ntop(AF_INET6, ip6_ip, ip6_addr, INET6_ADDRSTRLEN),
     743           0 :                             req->vifr_fat_flow_src_prefix_mask[i],
     744           0 :                             req->vifr_fat_flow_src_aggregate_plen[i]);
     745           0 :                      tmp = (uint64_t *)ip6_ip;
     746           0 :                      *tmp = req->vifr_fat_flow_dst_prefix_h[i];
     747           0 :                      *(tmp + 1) = req->vifr_fat_flow_dst_prefix_l[i];
     748           0 :                      printf(" AggrDst %s/%d %d",
     749             :                             inet_ntop(AF_INET6, ip6_ip, ip6_addr, INET6_ADDRSTRLEN),
     750           0 :                             req->vifr_fat_flow_dst_prefix_mask[i],
     751           0 :                             req->vifr_fat_flow_dst_aggregate_plen[i]);
     752           0 :                      break;
     753           0 :                 default:
     754           0 :                      break;
     755             :             }
     756             : 
     757           0 :             printf("\n");
     758             :         }
     759             :     }
     760           3 :     printf("\n");
     761           3 :     if (req->vifr_fat_flow_exclude_ip_list_size) {
     762           0 :         vr_interface_print_head_space();
     763           0 :         printf("FatFlows IPv4 exclude prefix list:\n");
     764           0 :         for (i = 0; i < req->vifr_fat_flow_exclude_ip_list_size; i++) {
     765           0 :              vr_interface_print_head_space();
     766           0 :              printf("\t%s\n", inet_ntop(AF_INET, &req->vifr_fat_flow_exclude_ip_list[i], ip_addr, INET_ADDRSTRLEN));
     767             :         }
     768           0 :         printf("\n");
     769             :     }
     770           3 :     if (req->vifr_fat_flow_exclude_ip6_u_list_size) {
     771           0 :         vr_interface_print_head_space();
     772           0 :         printf("FatFlows IPv6 exclude prefix list:\n");
     773           0 :         for (i = 0; i < req->vifr_fat_flow_exclude_ip6_u_list_size; i++) {
     774           0 :              tmp = (uint64_t *)ip6_ip;
     775           0 :              *tmp = req->vifr_fat_flow_exclude_ip6_u_list[i];
     776           0 :              *(tmp + 1) = req->vifr_fat_flow_exclude_ip6_l_list[i];
     777           0 :              vr_interface_print_head_space();
     778           0 :              printf("\t%s\n", inet_ntop(AF_INET6, ip6_ip, ip6_addr, INET6_ADDRSTRLEN));
     779             :         }
     780           0 :         printf("\n");
     781             :     } 
     782             : 
     783           3 :     if (get_set && req->vifr_flags & VIF_FLAG_SERVICE_IF) {
     784           0 :         vr_vrf_assign_dump = true;
     785           0 :         dump_pending = true;
     786           0 :         printf("VRF table(vlan:vrf):\n");
     787           0 :         vr_ifindex = req->vifr_idx;
     788             :     }
     789             : 
     790           3 :     return;
     791             : }
     792             : 
     793             : static void
     794           0 : list_header_print(void)
     795             : {
     796           0 :     int printed = 0;
     797             : 
     798           0 :     printed = printf("Interface name");
     799           0 :     for (; printed < 30; printed++)
     800           0 :         printf(" ");
     801             : 
     802           0 :     printed = printf("VIF ID");
     803           0 :     for (; printed < 30; printed++)
     804           0 :         printf(" ");
     805             : 
     806           0 :     printed = printf("RX");
     807           0 :     for (; printed < 30; printed++)
     808           0 :         printf(" ");
     809             : 
     810           0 :     printed = printf("TX");
     811           0 :     for (; printed < 30; printed++)
     812           0 :         printf(" ");
     813             : 
     814           0 :     printf("\n");
     815             : 
     816           0 :     printed = strlen("Errors");
     817           0 :     for (; printed < 30 * 2; printed++)
     818           0 :         printf(" ");
     819             : 
     820           0 :     printed = printf("Errors   Packets");
     821           0 :     for (; printed < 30; printed++)
     822           0 :         printf(" ");
     823             : 
     824           0 :     printf("Errors   Packets");
     825             : 
     826           0 :     printf("\n\n");
     827           0 : }
     828             : 
     829             : static void
     830           0 : list_rate_print(vr_interface_req *req)
     831             : {
     832           0 :     int printed = 0;
     833           0 :     uint64_t tx_errors = 0;
     834           0 :     uint64_t rx_errors = 0;
     835           0 :     unsigned int i = 0;
     836             : 
     837           0 :     rx_errors = (req->vifr_dev_ierrors + req->vifr_port_ierrors + req->vifr_queue_ierrors
     838           0 :                  + req->vifr_ierrors);
     839           0 :     tx_errors = (req->vifr_dev_oerrors + req->vifr_port_oerrors + req->vifr_queue_oerrors
     840           0 :                  + req->vifr_oerrors);
     841             : 
     842           0 :     printed = printf("%s: %s", vr_get_if_type_string(req->vifr_type),
     843             :                         req->vifr_name);
     844           0 :     for (; printed < 30; printed++)
     845           0 :         printf(" ");
     846           0 :     printed = printf("vif%d/%d", req->vifr_rid, req->vifr_idx);
     847           0 :     for (; printed < 24; printed++)
     848           0 :         printf(" ");
     849             : 
     850           0 :     printed = printf("%-7"PRIu64 "  %-7"PRIu64, rx_errors, req->vifr_ipackets);
     851           0 :     for (; printed < 30; printed++)
     852           0 :         printf(" ");
     853             : 
     854           0 :     printed = printf("%-7"PRIu64 "  %-7"PRIu64, tx_errors, req->vifr_opackets);
     855           0 :     for (; printed < 25; printed++)
     856           0 :         printf(" ");
     857           0 :     printf("\n\n\n");
     858           0 :     return;
     859             : }
     860             : 
     861             : static void
     862           0 : rate_process(vr_interface_req *req, vr_interface_req *prev_req)
     863             : {
     864           0 :     vr_interface_req rate_req_temp = {0};
     865           0 :     uint64_t *temp_prev_req_ptr = NULL;
     866             : 
     867           0 :     if (first_rate_iter) {
     868           0 :         temp_prev_req_ptr = prev_req->vifr_queue_ierrors_to_lcore;
     869           0 :         *prev_req = *req;
     870           0 :         prev_req->vifr_queue_ierrors_to_lcore = temp_prev_req_ptr;
     871           0 :         if (!prev_req->vifr_queue_ierrors_to_lcore) {
     872           0 :             prev_req->vifr_queue_ierrors_to_lcore =
     873           0 :                 malloc(req->vifr_queue_ierrors_to_lcore_size * sizeof(uint64_t));
     874           0 :             if (!prev_req->vifr_queue_ierrors_to_lcore)
     875           0 :                 return;
     876             :         }
     877             : 
     878           0 :         memcpy(prev_req->vifr_queue_ierrors_to_lcore,
     879           0 :             req->vifr_queue_ierrors_to_lcore,
     880           0 :             req->vifr_queue_ierrors_to_lcore_size * sizeof(uint64_t));
     881           0 :         rate_stats_diff(req, prev_req);
     882           0 :         return;
     883             :     }
     884             : 
     885           0 :     rate_req_temp = *req;
     886           0 :     rate_req_temp.vifr_queue_ierrors_to_lcore =
     887           0 :         calloc(req->vifr_queue_ierrors_to_lcore_size, sizeof(uint64_t));
     888             : 
     889           0 :     if (!rate_req_temp.vifr_queue_ierrors_to_lcore) {
     890           0 :         fprintf(stderr, "Fail, memory allocation. (%s:%d).", __FILE__ , __LINE__);
     891           0 :         exit(1);
     892             :     }
     893             : 
     894           0 :     memcpy(rate_req_temp.vifr_queue_ierrors_to_lcore,
     895           0 :             req->vifr_queue_ierrors_to_lcore,
     896           0 :             req->vifr_queue_ierrors_to_lcore_size * sizeof(uint64_t));
     897             : 
     898           0 :     rate_stats_diff(req, prev_req);
     899             : 
     900           0 :     temp_prev_req_ptr = prev_req->vifr_queue_ierrors_to_lcore;
     901           0 :     *prev_req = rate_req_temp;
     902           0 :     prev_req->vifr_queue_ierrors_to_lcore = temp_prev_req_ptr;
     903             : 
     904           0 :     memcpy(prev_req->vifr_queue_ierrors_to_lcore,
     905           0 :             rate_req_temp.vifr_queue_ierrors_to_lcore,
     906           0 :             rate_req_temp.vifr_queue_ierrors_to_lcore_size * sizeof(uint64_t));
     907             : 
     908           0 :     if ((rate_req_temp.vifr_queue_ierrors_to_lcore)) {
     909           0 :         free(rate_req_temp.vifr_queue_ierrors_to_lcore);
     910           0 :         rate_req_temp.vifr_queue_ierrors_to_lcore = NULL;
     911             :     }
     912             : }
     913             : 
     914             : /*
     915             :  * The function is called by functions sandesh_decode.
     916             :  * In case, when we have sent SANDESH_OP_DUMP (usually --list parameter) msg to nl_client,
     917             :  * then sandesh_decode calls vr_interface_req_process in "loop".
     918             :  * Variable dump_marker (dump_marker < next_interface.vif_id) sets which
     919             :  * interface is successor.
     920             :  *
     921             :  * For SANDESH_OP_DUMP msg we SHOULD change variable dump_marker;
     922             :  * Otherwise we can be in infinity loop.
     923             :  */
     924             : static void
     925           4 : interface_req_process(void *s)
     926             : {
     927           4 :     vr_interface_req *req = (vr_interface_req *)s;
     928             : 
     929           4 :     if(req->h_op == SANDESH_OP_RESET) {
     930           1 :         if(req->vifr_idx == -1) {
     931           1 :             if(req->vifr_core != 0) {
     932           0 :                 printf("\nVif stats cleared successfully on core %d for all interfacess \n\n",
     933           0 :                         req->vifr_core-1);
     934             :             } else {
     935           1 :                 printf("\nVif stats cleared successfully on all cores for all interfaces \n\n");
     936             :             }
     937             :         } else {
     938           0 :             if(req->vifr_core != 0) {
     939           0 :                 printf("\nVif stats cleared successfully for %s on core %d \n\n",
     940           0 :                         req->vifr_name, req->vifr_core-1);
     941             :             } else {
     942           0 :                 printf("\nVif stats cleared successfully for %s on all cores \n\n",
     943             :                         req->vifr_name);
     944             :             }
     945             :         }
     946           1 :         return;
     947             :     }
     948             : 
     949           3 :     if (add_set)
     950           0 :         vr_ifindex = req->vifr_idx;
     951             : 
     952           3 :     if (!get_set && !list_set)
     953           0 :         return;
     954             : 
     955           3 :     if (rate_set) {
     956             :         /* Compute for each "current" vif interfaces. */
     957           0 :         rate_process(req, &prev_req[req->vifr_idx % VR_MAX_INTERFACES]);
     958             : 
     959           0 :         if (list_set) {
     960             :             /*
     961             :              * We are in loop (which cannot be controlled by us)
     962             :              * (see function comment)
     963             :              *
     964             :              * Ignores first interfaces outputs.
     965             :              */
     966           0 :             if (ignore_number_interface > 0) {
     967           0 :                 ignore_number_interface--;
     968             :                 /*
     969             :                  * How many interface we should print
     970             :                  * Value of variable number_interface is computed:
     971             :                  * (get_terminal_lines - header_lines)/(lines_per_interface)
     972             :                  */
     973           0 :             } else if (print_number_interface >= 1) {
     974           0 :                 list_rate_print(req);
     975           0 :                 print_number_interface--;
     976             :             }
     977             :             /* Mandatory, otherwise we can be in infinity loop.*/
     978           0 :             dump_marker = req->vifr_idx;
     979           0 :             return;
     980             :         }
     981             :     }
     982           3 :     list_get_print(req);
     983           3 :     if (list_set){
     984             : 
     985           0 :         dump_marker = req->vifr_idx;
     986             :     }
     987             : 
     988           3 :     return;
     989             : }
     990             : 
     991             : static void
     992          12 : response_process(void *s)
     993             : {
     994          12 :     vr_response_common_process((vr_response *)s, &dump_pending);
     995          12 :     return;
     996             : }
     997             : 
     998             : static void
     999          12 : vif_fill_nl_callbacks()
    1000             : {
    1001          12 :     nl_cb.vr_drop_stats_req_process = drop_stats_req_process;
    1002          12 :     nl_cb.vr_vrf_assign_req_process = vrf_assign_req_process;
    1003          12 :     nl_cb.vr_interface_req_process = interface_req_process;
    1004          12 :     nl_cb.vr_response_process = response_process;
    1005          12 : }
    1006             : 
    1007             : /*
    1008             :  * create vhost interface in linux
    1009             :  */
    1010             : static int
    1011           0 : vhost_create(void)
    1012             : {
    1013             :     int ret;
    1014             : #if defined(__linux__)
    1015             :     struct vn_if vhost;
    1016             :     struct nl_response *resp;
    1017             : 
    1018           0 :     memset(&vhost, 0, sizeof(vhost));
    1019           0 :     strncpy(vhost.if_name, if_name, sizeof(vhost.if_name) - 1);
    1020           0 :     strncpy(vhost.if_kind, VHOST_KIND, sizeof(vhost.if_kind) - 1);
    1021           0 :     memcpy(vhost.if_mac, vr_ifmac, sizeof(vhost.if_mac));
    1022           0 :     ret = nl_build_if_create_msg(cl, &vhost, 0);
    1023           0 :     if (ret)
    1024           0 :         return ret;
    1025             : 
    1026           0 :     ret = nl_sendmsg(cl);
    1027           0 :     if (ret <= 0)
    1028           0 :         return ret;
    1029             : 
    1030           0 :     if ((ret = nl_recvmsg(cl)) > 0) {
    1031           0 :         resp = nl_parse_reply(cl);
    1032           0 :         if (resp && resp->nl_op)
    1033           0 :             printf("%s: %s\n", __func__, strerror(resp->nl_op));
    1034             :     }
    1035             : #else
    1036             : #error "Unsupported platform"
    1037             : #endif
    1038           0 :     return ret;
    1039             : }
    1040             : 
    1041             : static int
    1042          12 : vr_intf_op(struct nl_client *cl, unsigned int op)
    1043             : {
    1044          12 :     int ret = -EINVAL, vrf;
    1045          12 :     bool dump = false;
    1046             : 
    1047          12 :     if (create_set)
    1048           0 :         return vhost_create();
    1049             : 
    1050          12 :     if ((op == SANDESH_OP_DUMP &&  !(rate_set)) ||
    1051           3 :             ((op == SANDESH_OP_GET) && !(add_set) )) {
    1052           3 :         vr_interface_print_header();
    1053           9 :     } else if (rate_set) {
    1054           0 :        list_header_print();
    1055             :     }
    1056             : 
    1057           9 : op_retry:
    1058          12 :     switch (op) {
    1059           0 :     case SANDESH_OP_ADD:
    1060           0 :         if (set_set)
    1061           0 :             vrf = -1;
    1062             :         else
    1063           0 :             vrf = vrf_id;
    1064             : 
    1065           0 :         if (if_kindex < 0)
    1066           0 :             if_kindex = 0;
    1067             : 
    1068           0 :         if (vindex_set)
    1069           0 :             vr_ifindex = vif_index;
    1070             : 
    1071           0 :         if (vr_ifindex < 0)
    1072           0 :             vr_ifindex = if_kindex;
    1073             : 
    1074           0 :         ret = vr_send_interface_add(cl, 0, if_name, if_kindex, vr_ifindex,
    1075             :                 if_xconnect_kindex, vr_if_type, vrf, vr_ifflags, vr_ifmac, vr_transport, NULL);
    1076           0 :         break;
    1077             : 
    1078           8 :     case SANDESH_OP_DEL:
    1079           8 :         ret = vr_send_interface_delete(cl, 0, if_name, vr_ifindex);
    1080           8 :         break;
    1081             : 
    1082           3 :     case SANDESH_OP_GET:
    1083             :         /**
    1084             :          * Implementation of getting per-core vif statistics is based on this
    1085             :          * little trick to avoid making changes in how agent makes requests for
    1086             :          * statistics. From vRouter's and agent's point of view, request for
    1087             :          * stats for 0th core means a request for stats summed up for all the
    1088             :          * cores. So cores are enumerated starting with 1.
    1089             :          * Meanwhile, from user's point of view they are enumerated starting
    1090             :          * with 0 (e.g. vif --list --core 0 means 'vif statistics for the very
    1091             :          * first (0th) core'). This is how Linux enumerates CPUs, so it should
    1092             :          * be more intuitive for the user.
    1093             :          *
    1094             :          * Agent is not aware of possibility of asking for per-core stats. Its
    1095             :          * requests have vifr_core implicitly set to 0. So we need to make a
    1096             :          * conversion between those enumerating systems. The vif utility
    1097             :          * increments by 1 the core number user asked for. Then it is
    1098             :          * decremented back in vRouter.
    1099             :          */
    1100           3 :         if (!vr_vrf_assign_dump) {
    1101           3 :             ret = vr_send_interface_get(cl, 0, vr_ifindex, if_kindex,
    1102           3 :                     core + 1, drop_set);
    1103             :         } else {
    1104           0 :             dump = true;
    1105           0 :             ret = vr_send_vrf_assign_dump(cl, 0, vr_ifindex, var_marker);
    1106             :         }
    1107           3 :         break;
    1108             : 
    1109           0 :     case SANDESH_OP_DUMP:
    1110           0 :         dump = true;
    1111           0 :         ret = vr_send_interface_dump(cl, 0, dump_marker, core + 1);
    1112           0 :         break;
    1113             : 
    1114           1 :     case SANDESH_OP_RESET:
    1115           1 :         ret = vr_send_vif_clear_stats(cl, 0, vif_index, core);
    1116           1 :         break;
    1117             :     }
    1118             : 
    1119             : 
    1120          12 :     if (ret < 0)
    1121           0 :         return ret;
    1122             : 
    1123             : 
    1124          12 :     ret = vr_recvmsg(cl, dump);
    1125          12 :     if (ret <= 0)
    1126           0 :         return ret;
    1127             : 
    1128          12 :     if (set_set) {
    1129           0 :         ret = vr_send_vrf_assign_set(cl, 0, vr_ifindex, vlan_id, vrf_id);
    1130           0 :         if (ret < 0)
    1131           0 :             return ret;
    1132             : 
    1133           0 :         return vr_recvmsg(cl, dump);
    1134             :     }
    1135             : 
    1136          12 :     if (dump_pending) {
    1137           0 :         goto op_retry;
    1138             :     }
    1139             : 
    1140          12 :     return 0;
    1141             : }
    1142             : 
    1143             : static void
    1144           0 : usage_internal(const char *msg)
    1145             : {
    1146           0 :     printf("Invalid arguments for %s \n", msg);
    1147           0 :     exit(0);
    1148             : }
    1149             : 
    1150             : static void
    1151           0 : Usage()
    1152             : {
    1153           0 :     printf("Usage: vif [--create <intf_name> --mac <mac>]\n");
    1154           0 :     printf("\t   [--add <intf_name> --mac <mac> --vrf <vrf>\n");
    1155           0 :     printf("\t   \t--type [vhost|agent|physical|virtual|monitoring]\n");
    1156           0 :     printf("\t   \t--transport [eth|pmd|virtual|socket]\n");
    1157           0 :     printf("\t   \t--xconnect <physical interface name>\n");
    1158           0 :     printf("\t   \t--policy, --vhost-phys, --dhcp-enable]\n");
    1159           0 :     printf("\t   \t--vif <vif ID> --id <intf_id> --pmd --pci]\n");
    1160           0 :     printf("\t   [--delete <intf_id>|<intf_name>]\n");
    1161           0 :     printf("\t   [--get <intf_id>][--kernel][--core <core number>][--rate] [--get-drop-stats]\n");
    1162           0 :     printf("\t   [--set <intf_id> --vlan <vlan_id> --vrf <vrf_id>]\n");
    1163           0 :     printf("\t   [--list][--core <core number>][--rate]\n");
    1164           0 :     printf("\t   [--sock-dir <sock dir>]\n");
    1165           0 :     printf("\t   [--clear][--id <intf_id>][--core <core_number>]\n");
    1166           0 :     printf("\t   [--help]\n");
    1167             : 
    1168           0 :     exit(0);
    1169             : }
    1170             : 
    1171             : 
    1172             : enum if_opt_index {
    1173             :     ADD_OPT_INDEX,
    1174             :     CREATE_OPT_INDEX,
    1175             :     GET_OPT_INDEX,
    1176             :     RATE_OPT_INDEX,
    1177             :     DROP_OPT_INDEX,
    1178             :     LIST_OPT_INDEX,
    1179             :     VRF_OPT_INDEX,
    1180             :     MAC_OPT_INDEX,
    1181             :     DELETE_OPT_INDEX,
    1182             :     POLICY_OPT_INDEX,
    1183             :     PMD_OPT_INDEX,
    1184             :     PCI_OPT_INDEX,
    1185             :     KINDEX_OPT_INDEX,
    1186             :     TYPE_OPT_INDEX,
    1187             :     TRANSPORT_OPT_INDEX,
    1188             :     SET_OPT_INDEX,
    1189             :     VLAN_OPT_INDEX,
    1190             :     XCONNECT_OPT_INDEX,
    1191             :     VIF_OPT_INDEX,
    1192             :     DHCP_OPT_INDEX,
    1193             :     VHOST_PHYS_OPT_INDEX,
    1194             :     HELP_OPT_INDEX,
    1195             :     VINDEX_OPT_INDEX,
    1196             :     CORE_OPT_INDEX,
    1197             :     SOCK_DIR_OPT_INDEX,
    1198             :     CLEAR_STATS_OPT_INDEX,
    1199             :     MAX_OPT_INDEX
    1200             : };
    1201             : 
    1202             : static struct option long_options[] = {
    1203             :     [ADD_OPT_INDEX]         =   {"add",         required_argument,  &add_set,           1},
    1204             :     [CREATE_OPT_INDEX]      =   {"create",      required_argument,  &create_set,        1},
    1205             :     [GET_OPT_INDEX]         =   {"get",         required_argument,  &get_set,           1},
    1206             :     [RATE_OPT_INDEX]        =   {"rate",        no_argument,        &rate_set,          1},
    1207             :     [DROP_OPT_INDEX]        =   {"get-drop-stats",no_argument,      &drop_set,          1},
    1208             :     [LIST_OPT_INDEX]        =   {"list",        no_argument,        &list_set,          1},
    1209             :     [VRF_OPT_INDEX]         =   {"vrf",         required_argument,  &vrf_set,           1},
    1210             :     [MAC_OPT_INDEX]         =   {"mac",         required_argument,  &mac_set,           1},
    1211             :     [DELETE_OPT_INDEX]      =   {"delete",      required_argument,  &delete_set,        1},
    1212             :     [POLICY_OPT_INDEX]      =   {"policy",      no_argument,        &policy_set,        1},
    1213             :     [PMD_OPT_INDEX]         =   {"pmd",         no_argument,        &pmd_set,           1},
    1214             :     [PCI_OPT_INDEX]         =   {"pci",         no_argument,        &pci_set,           1},
    1215             :     [KINDEX_OPT_INDEX]      =   {"kernel",      no_argument,        &kindex_set,        1},
    1216             :     [TYPE_OPT_INDEX]        =   {"type",        required_argument,  &type_set,          1},
    1217             :     [TRANSPORT_OPT_INDEX]   =   {"transport",   required_argument,  &transport_set,     1},
    1218             :     [SET_OPT_INDEX]         =   {"set",         required_argument,  &set_set,           1},
    1219             :     [VLAN_OPT_INDEX]        =   {"vlan",        required_argument,  &vlan_set,          1},
    1220             :     [VHOST_PHYS_OPT_INDEX]  =   {"vhost-phys",  no_argument,        &vhost_phys_set,    1},
    1221             :     [XCONNECT_OPT_INDEX]    =   {"xconnect",    required_argument,  &xconnect_set,      1},
    1222             :     [VIF_OPT_INDEX]         =   {"vif",         required_argument,  &vif_set,           1},
    1223             :     [DHCP_OPT_INDEX]        =   {"dhcp-enable", no_argument,        &dhcp_set,          1},
    1224             :     [HELP_OPT_INDEX]        =   {"help",        no_argument,        &help_set,          1},
    1225             :     [VINDEX_OPT_INDEX]      =   {"id",          required_argument,  &vindex_set,        1},
    1226             :     [CORE_OPT_INDEX]        =   {"core",        required_argument,  &core_set,          1},
    1227             :     [SOCK_DIR_OPT_INDEX]    =   {"sock-dir",    required_argument,  &sock_dir_set,      1},
    1228             :     [CLEAR_STATS_OPT_INDEX] =   {"clear",       no_argument,        &clear_stats_set,   1},
    1229             :     [MAX_OPT_INDEX]         =   { NULL,         0,                  NULL,               0},
    1230             : };
    1231             : 
    1232             : 
    1233             : /* Safer than raw strtoul call that can segment fault with NULL strings.
    1234             :    sets errno if any addtional errors are detected.*/
    1235             : static unsigned long
    1236          11 : safer_strtoul(const char *nptr, char **endptr, int base)
    1237             : {
    1238          11 :     if (nptr == NULL) {
    1239           0 :         errno = EINVAL;
    1240           0 :         return 0;
    1241             :     } else {
    1242          11 :         return strtoul(nptr, endptr, base);
    1243             :     }
    1244             : }
    1245             : 
    1246             : static int
    1247           3 : is_number(const char *nptr)
    1248             : {
    1249             :     unsigned int i;
    1250           3 :     if (nptr == NULL) {
    1251           0 :         errno = EINVAL;
    1252           0 :         return 0;
    1253             :     } else {
    1254          15 :         for (i = 0; i < strlen(nptr); i++) {
    1255          12 :             if (!isdigit(nptr[i])) {
    1256           0 :                 return 0;
    1257             :             }
    1258             :         }
    1259             :     }
    1260           3 :     return 1;
    1261             : }
    1262             : 
    1263             : static void
    1264          24 : parse_long_opts(int option_index, char *opt_arg)
    1265             : {
    1266          24 :     int i = 0;
    1267             :     char *sep_arg;
    1268          24 :     errno = 0;
    1269          24 :    int retVal = -1;
    1270             :    
    1271             : 
    1272          24 :     if (!*(long_options[option_index].flag))
    1273           0 :         *(long_options[option_index].flag) = 1;
    1274             : 
    1275          24 :     switch (option_index) {
    1276           0 :         case ADD_OPT_INDEX:
    1277           0 :             strncpy(if_name, opt_arg, sizeof(if_name) - 1);
    1278           0 :             if_kindex = if_nametoindex(opt_arg);
    1279           0 :             if (isdigit(opt_arg[0]))
    1280           0 :                 if_pmdindex = strtol(opt_arg, NULL, 0);
    1281           0 :             vr_op = SANDESH_OP_ADD;
    1282           0 :             break;
    1283             : 
    1284           0 :         case CREATE_OPT_INDEX:
    1285           0 :             strncpy(if_name, opt_arg, sizeof(if_name) - 1);
    1286           0 :             break;
    1287             : 
    1288           0 :         case VRF_OPT_INDEX:
    1289           0 :             if (is_number(opt_arg))
    1290           0 :                 vrf_id = safer_strtoul(opt_arg, NULL, 0);
    1291             :             else
    1292           0 :                 usage_internal("vif set --vrf");
    1293             : 
    1294           0 :             if (errno)
    1295           0 :                 Usage();
    1296           0 :             break;
    1297             : 
    1298           0 :         case MAC_OPT_INDEX:
    1299           0 :             mac_opt = ether_aton(opt_arg);
    1300           0 :             if (mac_opt)
    1301           0 :                 memcpy(vr_ifmac, mac_opt, sizeof(vr_ifmac));
    1302           0 :             break;
    1303             : 
    1304           8 :         case DELETE_OPT_INDEX:
    1305           8 :             vr_op = SANDESH_OP_DEL;
    1306           8 :             if (isdigit(opt_arg[0]))
    1307           8 :                 vr_ifindex = safer_strtoul(opt_arg, NULL, 0);
    1308             :             else
    1309           0 :                 strncpy(if_name, opt_arg, sizeof(if_name) - 1);
    1310           8 :             if (errno)
    1311           0 :                 Usage();
    1312           8 :             break;
    1313             : 
    1314           3 :         case GET_OPT_INDEX:
    1315           3 :             vr_op = SANDESH_OP_GET;
    1316           3 :             if (is_number(opt_arg))
    1317           3 :                 vr_ifindex = safer_strtoul(opt_arg, NULL, 0);
    1318             :             else
    1319           0 :                 usage_internal("vif --get");
    1320             : 
    1321           3 :             if (errno)
    1322           0 :                 Usage();
    1323           3 :             break;
    1324             : 
    1325           0 :         case VIF_OPT_INDEX:
    1326             :             /* we carry monitored vif index in OS index field */
    1327           0 :             if (is_number(opt_arg))
    1328           0 :                 if_kindex = safer_strtoul(opt_arg, NULL, 0);
    1329             :             else
    1330           0 :                 usage_internal("vif add --vif");
    1331             : 
    1332           0 :             if (errno)
    1333           0 :                 Usage();
    1334           0 :             break;
    1335             : 
    1336           0 :         case VINDEX_OPT_INDEX:
    1337           0 :             if (is_number(opt_arg))
    1338           0 :                 vif_index = safer_strtoul(opt_arg, NULL, 0);
    1339             :             else
    1340           0 :                 usage_internal("vif add --id");
    1341             : 
    1342           0 :             if (errno)
    1343           0 :                 Usage();
    1344           0 :             break;
    1345             : 
    1346           0 :         case POLICY_OPT_INDEX:
    1347           0 :             vr_ifflags |= VIF_FLAG_POLICY_ENABLED;
    1348           0 :             break;
    1349             : 
    1350           0 :         case PMD_OPT_INDEX:
    1351           0 :             vr_ifflags |= VIF_FLAG_PMD;
    1352           0 :             break;
    1353             : 
    1354           0 :         case LIST_OPT_INDEX:
    1355           0 :             vr_op = SANDESH_OP_DUMP;
    1356           0 :             break;
    1357             : 
    1358           0 :         case CORE_OPT_INDEX:
    1359           0 :             core = (unsigned)strtol(opt_arg, NULL, 0);
    1360           0 :             if (errno) {
    1361           0 :                 printf("Error parsing core %s: %s (%d)\n", opt_arg,
    1362           0 :                         strerror(errno), errno);
    1363           0 :                 Usage();
    1364             :             }
    1365           0 :             break;
    1366             : 
    1367           0 :         case TYPE_OPT_INDEX:
    1368           0 :             vr_if_type = vr_get_if_type(optarg);
    1369           0 :             if (vr_if_type == VIF_TYPE_HOST)
    1370           0 :                 need_xconnect_if = true;
    1371           0 :             if (vr_if_type == VIF_TYPE_MONITORING) {
    1372           0 :                 if (platform != DPDK_PLATFORM)
    1373           0 :                     Usage();
    1374             : 
    1375           0 :                 need_vif_id = true;
    1376             :                 /* set default values for mac and vrf */
    1377           0 :                 vrf_id = 0;
    1378           0 :                 vrf_set = 1;
    1379           0 :                 vr_ifmac[0] = 0x2; /* locally administered */
    1380           0 :                 mac_set = 1;
    1381             :             }
    1382           0 :             break;
    1383             : 
    1384           0 :          case TRANSPORT_OPT_INDEX:
    1385           0 :             vr_transport = vr_get_if_transport(optarg);
    1386           0 :             break;
    1387             : 
    1388           0 :         case SET_OPT_INDEX:
    1389           0 :             vr_op = SANDESH_OP_ADD;
    1390           0 :             if (is_number(opt_arg))
    1391           0 :                 vr_ifindex = safer_strtoul(opt_arg, NULL, 0);
    1392             :             else
    1393           0 :                 usage_internal("vif --set");
    1394             : 
    1395           0 :             if (errno)
    1396           0 :                 Usage();
    1397           0 :             break;
    1398             : 
    1399           0 :         case VLAN_OPT_INDEX:
    1400           0 :             vr_ifflags |= VIF_FLAG_SERVICE_IF;
    1401           0 :             if (is_number(opt_arg))
    1402           0 :                 vlan_id = safer_strtoul(opt_arg, NULL, 0);
    1403             :             else
    1404           0 :                 usage_internal("vif set --vlan");
    1405           0 :             if (errno)
    1406           0 :                 Usage();
    1407           0 :             break;
    1408             : 
    1409           0 :         case XCONNECT_OPT_INDEX:
    1410           0 :             opt_arg = strdup(opt_arg);
    1411           0 :             while ((sep_arg = strsep(&opt_arg, ",")) != NULL) {
    1412           0 :                 if(platform == DPDK_PLATFORM) {
    1413             :                     /* we need to check cross_connect index has be passed or
    1414             :                      * not for kernel & DPDK based platforms */
    1415             :                     /*Incase of DPDK platform, vif_idx is passed for xconnect */
    1416           0 :                     if_xconnect_kindex[i++] = safer_strtoul(sep_arg, NULL, 0);
    1417             :                 } else {
    1418           0 :                     retVal = if_nametoindex(sep_arg);
    1419           0 :                     if(0 == retVal) {
    1420           0 :                        break;
    1421             :                     }
    1422           0 :                     if_xconnect_kindex[i++] = retVal;
    1423             :                 }
    1424           0 :                 if (isdigit(sep_arg[0])) {
    1425           0 :                     if_pmdindex = strtol(sep_arg, NULL, 0);
    1426           0 :                 } else if (!if_xconnect_kindex[i]) {
    1427           0 :                     printf("%s does not seem to be a valid physical interface name\n",
    1428             :                            sep_arg);
    1429           0 :                     Usage();
    1430             :                 }
    1431           0 :                 if (if_pmdindex != -1)
    1432           0 :                     break;
    1433             :             }
    1434           0 :             break;
    1435             : 
    1436           0 :         case DHCP_OPT_INDEX:
    1437           0 :             vr_ifflags |= VIF_FLAG_DHCP_ENABLED;
    1438           0 :             break;
    1439             : 
    1440           0 :         case VHOST_PHYS_OPT_INDEX:
    1441           0 :             vr_ifflags |= VIF_FLAG_VHOST_PHYS;
    1442           0 :             break;
    1443             : 
    1444          12 :         case SOCK_DIR_OPT_INDEX:
    1445          12 :             vr_socket_dir = opt_arg;
    1446          12 :             break;
    1447             : 
    1448           1 :         case CLEAR_STATS_OPT_INDEX:
    1449           1 :             clear_stats_set = 1;
    1450           1 :             vr_op = SANDESH_OP_RESET;
    1451           1 :             break;
    1452           0 :         default:
    1453           0 :             break;
    1454             :     }
    1455             : 
    1456          24 :     return;
    1457             : }
    1458             : 
    1459             : static void
    1460          12 : validate_options(void)
    1461             : {
    1462          12 :     unsigned int sum_opt = 0, i;
    1463             : 
    1464         336 :     for (i = 0; i < (sizeof(long_options) / sizeof(long_options[0])); i++) {
    1465         324 :         if (long_options[i].flag)
    1466         312 :             sum_opt += *(long_options[i].flag);
    1467             :     }
    1468             : 
    1469             :     /*
    1470             :      * Reduce sum_opt by 1 so that rest of the validation logic doesn't take
    1471             :      * sock_dir_set into account
    1472             :      */
    1473          12 :     if (sock_dir_set) {
    1474          12 :         sum_opt -=1;
    1475             :     }
    1476             : 
    1477          12 :     if (!sum_opt || help_set)
    1478           0 :         Usage();
    1479             : 
    1480          12 :     if (pmd_set || pci_set) {
    1481           0 :         if_kindex = if_pmdindex;
    1482           0 :         if_xconnect_kindex[0] = if_pmdindex;
    1483             :     }
    1484             : 
    1485          12 :     if (create_set) {
    1486           0 :         if ((sum_opt > 1) && (sum_opt != 2 || !mac_set))
    1487           0 :             Usage();
    1488           0 :         return;
    1489             :     }
    1490          12 :     if (get_set) {
    1491           3 :         if ((sum_opt > 1) && (sum_opt != 3) && (sum_opt != 4) &&
    1492           0 :                 (!kindex_set && !core_set && !rate_set && !drop_set))
    1493           0 :             Usage();
    1494           3 :         return;
    1495             :     }
    1496           9 :     if (delete_set) {
    1497           8 :         if (sum_opt > 1)
    1498           0 :             Usage();
    1499           8 :         return;
    1500             :     }
    1501           1 :     if (list_set) {
    1502           0 :         if (drop_set)
    1503           0 :             Usage();
    1504           0 :         if (!core_set) {
    1505           0 :             if (rate_set && !(sum_opt > 2))
    1506           0 :                 return;
    1507           0 :             if (sum_opt > 1)
    1508           0 :                 Usage();
    1509             :         } else {
    1510           0 :             if(rate_set && !(sum_opt > 3))
    1511           0 :                return;
    1512           0 :             if (sum_opt != 2)
    1513           0 :                 Usage();
    1514             :         }
    1515           0 :         return;
    1516             :     }
    1517             : 
    1518           1 :     if (add_set) {
    1519           0 :         if (get_set || list_set)
    1520           0 :             Usage();
    1521           0 :         if (!vrf_set || !mac_set || !type_set)
    1522           0 :             Usage();
    1523           0 :         if (need_xconnect_if && !xconnect_set)
    1524           0 :             Usage();
    1525           0 :         if (need_vif_id && !vif_set)
    1526           0 :             Usage();
    1527           0 :         return;
    1528             :     }
    1529             : 
    1530           1 :     if (set_set) {
    1531           0 :         if (sum_opt != 3 || !vrf_set || !vlan_set)
    1532           0 :             Usage();
    1533           0 :         return;
    1534             :     }
    1535             : 
    1536             :     /**
    1537             :      * Statistics per CPU core could be requested as an additional parameter
    1538             :      * to --list or --get.
    1539             :      */
    1540           1 :     if(core_set){
    1541           0 :         if (clear_stats_set)
    1542           0 :             return;
    1543             :     }
    1544           1 :     if (core_set) {
    1545           0 :         if (!list_set || !get_set)
    1546           0 :             Usage();
    1547             :     }
    1548           1 :     if (rate_set) {
    1549           0 :         if (!get_set) {
    1550           0 :             Usage();
    1551             :         }
    1552             :     }
    1553             : 
    1554           1 :     return;
    1555             : }
    1556             : 
    1557             : 
    1558             : static void
    1559           0 : rate_stats_diff(vr_interface_req *req, vr_interface_req *prev_req)
    1560             : {
    1561             :     struct timeval now;
    1562           0 :     int64_t diff_ms = 0;
    1563           0 :     unsigned int i = 0;
    1564             : 
    1565           0 :     gettimeofday(&now, NULL);
    1566           0 :     diff_ms = (now.tv_sec - last_time.tv_sec) * 1000;
    1567           0 :     diff_ms += (now.tv_usec - last_time.tv_usec) / 1000;
    1568           0 :     assert(diff_ms > 0);
    1569             : 
    1570             :     /* TODO:
    1571             :      * Sometimes error counters have decreasing trend.
    1572             :      *
    1573             :      * Workaround:
    1574             :      * If previous value is bigger than current value, then we assign
    1575             :      * previous value to current value => difference is equal to 0
    1576             :      */
    1577             : 
    1578           0 :     CORRECT_ERROR_CNT(&(req->vifr_dev_ierrors), &(prev_req->vifr_dev_ierrors));
    1579           0 :     CORRECT_ERROR_CNT(&(req->vifr_port_ierrors), &(prev_req->vifr_port_ierrors));
    1580           0 :     CORRECT_ERROR_CNT(&(req->vifr_queue_ierrors), &(prev_req->vifr_queue_ierrors));
    1581           0 :     CORRECT_ERROR_CNT(&(req->vifr_ierrors), &(prev_req->vifr_ierrors));
    1582             : 
    1583           0 :     CORRECT_ERROR_CNT(&(req->vifr_dev_oerrors), &(prev_req->vifr_dev_oerrors));
    1584           0 :     CORRECT_ERROR_CNT(&(req->vifr_port_oerrors), &(prev_req->vifr_port_oerrors));
    1585           0 :     CORRECT_ERROR_CNT(&(req->vifr_queue_oerrors), &(prev_req->vifr_queue_oerrors));
    1586           0 :     CORRECT_ERROR_CNT(&(req->vifr_oerrors), &(prev_req->vifr_oerrors));
    1587             : 
    1588             :     /* RX */
    1589           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_dev_ibytes, diff_ms);
    1590           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_dev_ipackets, diff_ms);
    1591           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_dev_ierrors, diff_ms);
    1592           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_dev_inombufs, diff_ms);
    1593             : 
    1594           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_port_isyscalls, diff_ms);
    1595           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_port_ipackets, diff_ms);
    1596           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_port_ierrors, diff_ms);
    1597           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_port_inombufs, diff_ms);
    1598             : 
    1599           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_queue_ierrors, diff_ms);
    1600           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_queue_ipackets, diff_ms);
    1601             : 
    1602           0 :     for (i = 0; i < req->vifr_queue_ierrors_to_lcore_size; i++) {
    1603           0 :         COMPUTE_DIFFERENCE(req, prev_req, vifr_queue_ierrors_to_lcore[i], diff_ms);
    1604             :     }
    1605             : 
    1606           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_ibytes, diff_ms);
    1607           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_ipackets, diff_ms);
    1608           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_ierrors, diff_ms);
    1609             : 
    1610             :     /* TX */
    1611           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_obytes, diff_ms);
    1612           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_opackets, diff_ms);
    1613           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_oerrors, diff_ms);
    1614             : 
    1615           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_queue_oerrors, diff_ms);
    1616           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_queue_opackets, diff_ms);
    1617             : 
    1618           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_port_osyscalls, diff_ms);
    1619           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_port_opackets, diff_ms);
    1620           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_port_oerrors, diff_ms);
    1621             : 
    1622           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_dev_obytes, diff_ms);
    1623           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_dev_opackets, diff_ms);
    1624           0 :     COMPUTE_DIFFERENCE(req, prev_req, vifr_dev_oerrors, diff_ms);
    1625           0 :  }
    1626             : 
    1627             : static void
    1628           0 : rate_stats(struct nl_client *cl, unsigned int vr_op)
    1629             : {
    1630             :     struct tm *tm;
    1631             :     time_t secs;
    1632           0 :     char fmt[80] = {0};
    1633           0 :     int ret = 0;
    1634           0 :     char kb_input[2] = {0};
    1635           0 :     struct winsize terminal_size = {0};
    1636           0 :     int local_ignore_number_interface = ignore_number_interface;
    1637           0 :     int local_print_number_interface = print_number_interface;
    1638           0 :     first_rate_iter = true;
    1639             : 
    1640             :     while (true) {
    1641           0 :         while (!is_stdin_hit() || get_set) {
    1642           0 :             ignore_number_interface = local_ignore_number_interface;
    1643           0 :             gettimeofday(&last_time, NULL);
    1644           0 :             first_rate_iter || usleep(SET_TIMEOUT_MS * 1000);
    1645             :             /* Get terminal parameters. */
    1646           0 :             ioctl(STDOUT_FILENO, TIOCGWINSZ, &terminal_size);
    1647             : 
    1648           0 :             print_number_interface = (terminal_size.ws_row - 9) / LISTING_NUM_OF_LINE ;
    1649           0 :             print_number_interface =
    1650           0 :                 (print_number_interface > MAX_OUTPUT_IF? MAX_OUTPUT_IF: print_number_interface);
    1651           0 :             local_print_number_interface = print_number_interface;
    1652           0 :             if (print_number_interface <= 0) {
    1653           0 :                 printf("Size of terminal is too small.\n");
    1654           0 :                 first_rate_iter = true;
    1655           0 :                 continue;
    1656             :             }
    1657           0 :             ret = system(CLEAN_SCREEN_CMD);
    1658           0 :             if (ret == -1) {
    1659           0 :                 fprintf(stderr, "Error: system() failed.\n");
    1660           0 :                 exit(1);
    1661             :             }
    1662           0 :             printf("Interface rate statistics\n");
    1663           0 :             printf("-------------------------\n\n");
    1664           0 :             if (vr_intf_op(cl, vr_op)) {
    1665           0 :                 fprintf(stderr, "Communication problem with vRouter.\n\n");
    1666           0 :                 exit(1);
    1667             :             }
    1668           0 :             if(list_set) {
    1669           0 :                 printf("Key 'q' for quit, key 'k' for previous page, key 'j' for next page.\n");
    1670             :             }
    1671           0 :             secs = last_time.tv_sec;
    1672           0 :             tm = localtime(&secs);
    1673           0 :             if (tm) {
    1674           0 :                 strftime(fmt, sizeof(fmt), "%Y-%m-%d %H:%M:%S %z", tm);
    1675           0 :                 printf("%s \n", fmt);
    1676             :             }
    1677             : 
    1678             :             /* We need reinitialize dump_marker variable, because we are in loop */
    1679           0 :             dump_marker = -1;
    1680           0 :             first_rate_iter = false;
    1681             :         }
    1682             : 
    1683             :         /*
    1684             :          * We must get minimum 2 characters,
    1685             :          * otherwise we will be in outer loop, always.
    1686             :          */
    1687             :         /* To suppress the warning return if EOF. */
    1688           0 :         if (fgets(kb_input, 2, stdin) == NULL)
    1689           0 :             return;
    1690             : 
    1691           0 :         switch (tolower(kb_input[0])) {
    1692           0 :             case 'q':
    1693           0 :                 return;
    1694             : 
    1695           0 :             case 'k':
    1696           0 :                 local_ignore_number_interface =
    1697           0 :                     (local_ignore_number_interface - local_print_number_interface <= 0)?
    1698             :                      0:
    1699             :                      (local_ignore_number_interface - local_print_number_interface);
    1700           0 :                 break;
    1701             : 
    1702           0 :             case 'j':
    1703           0 :                 local_ignore_number_interface =
    1704             :                         (local_ignore_number_interface + local_print_number_interface);
    1705           0 :                 break;
    1706             : 
    1707           0 :             default:
    1708           0 :                 break;
    1709             :         }
    1710           0 :         fflush(NULL);
    1711             :     }
    1712             : }
    1713             : 
    1714             : static int
    1715           0 : is_stdin_hit()
    1716             : {
    1717             :     struct timeval tv;
    1718             :     fd_set fds;
    1719             : 
    1720           0 :     tv.tv_sec = 0;
    1721           0 :     tv.tv_usec = 0;
    1722             : 
    1723           0 :     FD_ZERO(&fds);
    1724           0 :     FD_SET(STDIN_FILENO, &fds);
    1725           0 :     select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
    1726           0 :     return FD_ISSET(STDIN_FILENO, &fds);
    1727             : }
    1728             : 
    1729             : int
    1730          12 : main(int argc, char *argv[])
    1731             : {
    1732             :     int ret, opt, option_index;
    1733          12 :     unsigned int i = 0;
    1734             : 
    1735             :     static struct termios old_term_set, new_term_set;
    1736             : 
    1737             :     /*
    1738             :      * the proto of the socket changes based on whether we are creating an
    1739             :      * interface in linux or doing an operation in vrouter
    1740             :      */
    1741          12 :     unsigned int sock_proto = NETLINK_GENERIC;
    1742             : 
    1743          12 :     vif_fill_nl_callbacks();
    1744             : 
    1745          12 :     parse_ini_file();
    1746          12 :     platform = get_platform();
    1747             : 
    1748          36 :     while ((opt = getopt_long(argc, argv, "ba:c:d:g:klm:t:T:v:p:C:DPi:s:",
    1749          36 :                     long_options, &option_index)) >= 0) {
    1750          24 :         switch (opt) {
    1751           0 :             case 'a':
    1752           0 :                 add_set = 1;
    1753           0 :                 parse_long_opts(ADD_OPT_INDEX, optarg);
    1754           0 :                 break;
    1755             : 
    1756           0 :             case 'c':
    1757           0 :                 create_set = 1;
    1758           0 :                 parse_long_opts(CREATE_OPT_INDEX, optarg);
    1759           0 :                 break;
    1760             : 
    1761           0 :             case 'd':
    1762           0 :                 delete_set = 1;
    1763           0 :                 parse_long_opts(DELETE_OPT_INDEX, optarg);
    1764           0 :                 break;
    1765             : 
    1766           0 :             case 'g':
    1767           0 :                 get_set = 1;
    1768           0 :                 parse_long_opts(GET_OPT_INDEX, optarg);
    1769           0 :                 break;
    1770             : 
    1771           0 :             case 'k':
    1772           0 :                 kindex_set = 1;
    1773           0 :                 parse_long_opts(KINDEX_OPT_INDEX, optarg);
    1774           0 :                 break;
    1775             : 
    1776           0 :             case 'l':
    1777             :             case 'b':
    1778           0 :                 list_set = 1;
    1779           0 :                 parse_long_opts(LIST_OPT_INDEX, NULL);
    1780           0 :                 break;
    1781             : 
    1782           0 :             case 'm':
    1783           0 :                 mac_set = 1;
    1784           0 :                 parse_long_opts(MAC_OPT_INDEX, optarg);
    1785           0 :                 break;
    1786             : 
    1787           0 :             case 'v':
    1788           0 :                 vrf_set = 1;
    1789           0 :                 parse_long_opts(VRF_OPT_INDEX, optarg);
    1790           0 :                 break;
    1791             : 
    1792           0 :             case 'p':
    1793           0 :                 policy_set = 1;
    1794           0 :                 parse_long_opts(POLICY_OPT_INDEX, NULL);
    1795           0 :                 break;
    1796             : 
    1797           0 :             case 'D':
    1798           0 :                 pmd_set = 1;
    1799           0 :                 parse_long_opts(PMD_OPT_INDEX, NULL);
    1800           0 :                 break;
    1801             : 
    1802           0 :             case 'P':
    1803           0 :                 pci_set = 1;
    1804           0 :                 parse_long_opts(PCI_OPT_INDEX, NULL);
    1805           0 :                 break;
    1806             : 
    1807           0 :             case 't':
    1808           0 :                 type_set = 1;
    1809           0 :                 parse_long_opts(TYPE_OPT_INDEX, optarg);
    1810           0 :                 break;
    1811             : 
    1812           0 :             case 'T':
    1813           0 :                 transport_set = 1;
    1814           0 :                 parse_long_opts(TRANSPORT_OPT_INDEX, optarg);
    1815           0 :                 break;
    1816             : 
    1817           0 :             case 'i':
    1818           0 :                 vindex_set = 1;
    1819           0 :                 parse_long_opts(VINDEX_OPT_INDEX, NULL);
    1820           0 :                 break;
    1821             : 
    1822           0 :             case 'C':
    1823           0 :                 core_set = 1;
    1824           0 :                 parse_long_opts(CORE_OPT_INDEX, optarg);
    1825           0 :                 break;
    1826           0 :             case 's':
    1827           0 :                 sock_dir_set = 1;
    1828           0 :                 parse_long_opts(SOCK_DIR_OPT_INDEX, optarg);
    1829           0 :                 break;
    1830          24 :             case 0:
    1831          24 :                 parse_long_opts(option_index, optarg);
    1832          24 :                 break;
    1833             : 
    1834           0 :             case '?':
    1835             :             default:
    1836           0 :                 Usage();
    1837             :         }
    1838             :     }
    1839             : 
    1840          12 :     validate_options();
    1841             : 
    1842          12 :     sock_proto = VR_NETLINK_PROTO_DEFAULT;
    1843             : #if defined(__linux__)
    1844          12 :     if (create_set)
    1845           0 :         sock_proto = NETLINK_ROUTE;
    1846             : #endif
    1847             : 
    1848          12 :     if (sock_dir_set) {
    1849          12 :         set_platform_vtest();
    1850             :         /* Reinit platform variable since platform is changed to vtest now */
    1851          12 :         platform = get_platform();
    1852             :     }
    1853          12 :     cl = vr_get_nl_client(sock_proto);
    1854          12 :     if (!cl) {
    1855           0 :         printf("Error registering NetLink client: %s (%d)\n",
    1856           0 :                 strerror(errno), errno);
    1857           0 :         exit(-ENOMEM);
    1858             :     }
    1859          12 :     if (add_set) {
    1860             :         /*
    1861             :          * for addition, we need to see whether the interface already
    1862             :          * exists in vrouter or not. so, get can return error if the
    1863             :          * interface does not exist in vrouter
    1864             :          */
    1865           0 :         vr_ignore_nl_errors = true;
    1866           0 :         vr_intf_op(cl, SANDESH_OP_GET);
    1867           0 :         vr_ignore_nl_errors = false;
    1868             :     }
    1869          12 :     if (!rate_set) {
    1870          12 :         vr_intf_op(cl, vr_op);
    1871             : 
    1872             :     } else {
    1873           0 :         fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK);
    1874             :         /*
    1875             :          * tc[get/set]attr functions are for changing terminal behavior.
    1876             :          * We dont have to write enter (newline) for getting character from terminal.
    1877             :          *
    1878             :          */
    1879           0 :         tcgetattr(STDIN_FILENO, &old_term_set);
    1880           0 :         new_term_set = old_term_set;
    1881           0 :         new_term_set.c_lflag &= ~(ICANON);
    1882           0 :         tcsetattr(STDIN_FILENO, TCSANOW, &new_term_set);
    1883             : 
    1884           0 :         rate_stats(cl, vr_op);
    1885           0 :         tcsetattr(STDIN_FILENO, TCSANOW, &old_term_set);
    1886           0 :         for (i = 0; i < VR_MAX_INTERFACES; i++) {
    1887           0 :             if (prev_req[i].vifr_queue_ierrors_to_lcore) {
    1888           0 :                 free(prev_req[i].vifr_queue_ierrors_to_lcore);
    1889           0 :                 prev_req[i].vifr_queue_ierrors_to_lcore = NULL;
    1890             :             }
    1891             :         }
    1892             : 
    1893             :     }
    1894          12 :     return 0;
    1895             : }

Generated by: LCOV version 1.14