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

Generated by: LCOV version 1.14