LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dpdk - vr_dpdk_info.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 31 720 4.3 %
Date: 2026-08-03 02:19:58 Functions: 2 20 10.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * vr_dpdk_info.c - DPDK specific callback functions for vr_info .
       3             :  *
       4             :  * Copyright (c) 2020 Juniper Networks, Inc. All rights reserved.
       5             :  */
       6             : #include <vr_os.h>
       7             : #include <vr_types.h>
       8             : #include <string.h>
       9             : #include <sys/types.h>
      10             : #include <sys/stat.h>
      11             : #include <fcntl.h>
      12             : 
      13             : #include <vr_packet.h>
      14             : #include <rte_eth_bond.h>
      15             : #include <rte_ethdev.h>
      16             : #include <rte_port_ethdev.h>
      17             : #include <rte_eth_bond_8023ad.h>
      18             : #include <rte_pmd_i40e.h>
      19             : #include <rte_malloc.h>
      20             : #include <rte_mempool.h>
      21             : #include "vr_message.h"
      22             : #include "vr_btable.h"
      23             : #include "vr_dpdk.h"
      24             : #include "vrouter.h"
      25             : 
      26             : #define SEPERATOR 70
      27             : #define LINE 200
      28             : #define MAXBITS 8
      29             : #define I40E_MAX_PROFILE_NUM 16
      30             : 
      31             : enum segments {
      32             :     RX_PACKETS,
      33             :     RX_BYTES,
      34             :     TX_PACKETS,
      35             :     TX_BYTES,
      36             :     ERRORS,
      37             :     OTHERS
      38             : };
      39             : 
      40             : /* NOTE: Callback API's need to be registered in vrouter/include/vr_info.h
      41             :  * under VR_INFO_REG(X) macro.
      42             :  * All callback API's should start with "dpdk_<fn.name>"
      43             :  * Register Format: X(MSG, <fn.name>) \
      44             :  *              eg: X(INFO_BOND, info_get_bond)
      45             :  */
      46             : 
      47             : int
      48           0 : dpdk_info_get_dpdk_version(VR_INFO_ARGS)
      49             : {
      50             :     extern const char *ContrailBuildInfo;
      51             : 
      52           0 :     VR_INFO_BUF_INIT();
      53             : 
      54           0 :     VI_PRINTF("DPDK Version: %s\n",
      55             :         rte_version());
      56           0 :     VI_PRINTF("vRouter version: %s\n\n", ContrailBuildInfo);
      57           0 :     return 0;
      58             : }
      59             : 
      60             : int
      61           0 : get_port_states(VR_INFO_ARGS, uint8_t state)
      62             : {
      63           0 :    VR_INFO_DEC();
      64           0 :    int i = 0, cur = 0;
      65           0 :    char *states[] = {"ACT", "TIMEOUT", "AGG", "SYNC", "COL", "DIST",
      66             :                      "DEF", "EXP"};
      67           0 :    uint8_t orig_state = state;
      68           0 :    char port_states[LINE] = "";
      69             : 
      70             :    /* Iterating through each bit */
      71           0 :    while (i <= MAXBITS){
      72           0 :        if ((1 & state) && (cur < LINE)){
      73           0 :            cur += snprintf(port_states + cur, LINE - cur, "%s ", states[i]);
      74             :        }
      75           0 :        state  = state >> 1;
      76           0 :        i++;
      77             :    }
      78           0 :    VI_PRINTF("\tport state: %d (%s) \n\n", orig_state, port_states);
      79           0 :    return 0;
      80             : }
      81             : 
      82             : /* dpdk_info_get_bond provide the bond master & slave information */
      83             : static int
      84           0 : dpdk_bond_mode_8023ad(VR_INFO_ARGS, uint16_t port_id)
      85             : {
      86           0 :     VR_INFO_DEC();
      87             :     int ret;
      88           0 :     char *lacp_rate[] = {"slow", "fast"};
      89             : 
      90           0 :     VI_PRINTF("802.3ad info :\n");
      91             : 
      92           0 :     VI_PRINTF("LACP Rate: %s\n",
      93             :             lacp_rate[rte_eth_bond_lacp_rate_get(port_id)]);
      94             : 
      95           0 :     ret = rte_eth_bond_8023ad_agg_selection_get(port_id);
      96           0 :     switch(ret) {
      97           0 :         case AGG_COUNT:
      98           0 :             VI_PRINTF("Aggregator selection policy (ad_select): Count\n");
      99           0 :             break;
     100           0 :         case AGG_BANDWIDTH:
     101           0 :             VI_PRINTF("Aggregator selection policy (ad_select): Bandwidth\n");
     102           0 :             break;
     103           0 :         case AGG_STABLE:
     104           0 :             VI_PRINTF("Aggregator selection policy (ad_select): Stable\n");
     105           0 :             break;
     106           0 :         default:
     107           0 :             VI_PRINTF("Aggregator selection policy (ad_select): Null\n");
     108             :     }
     109             : 
     110           0 :     return 0;
     111             : }
     112             : 
     113             : static int
     114           0 : dpdk_bond_info_mii_status(VR_INFO_ARGS, uint16_t port_id,
     115             :                                    struct rte_eth_link *link)
     116             : {
     117           0 :     VR_INFO_DEC();
     118           0 :     char *status[] = {"DOWN", "UP"};
     119             : 
     120           0 :     VI_PRINTF("MII status: %s\n", status[link->link_status]);
     121           0 :     VI_PRINTF("MII Link Speed: %d Mbps\n", link->link_speed);
     122           0 :     if(rte_eth_bond_mode_get(port_id) == BONDING_MODE_8023AD) {
     123           0 :         VI_PRINTF("MII Polling Interval (ms): %d\n",
     124             :                 rte_eth_bond_link_monitoring_get(port_id));
     125             :     }
     126           0 :     return 0;
     127             : }
     128             : 
     129             : static int
     130           0 : dpdk_bond_info_show_slave(VR_INFO_ARGS, uint16_t port_id,
     131             :                                struct vr_dpdk_ethdev *ethdev)
     132             : {
     133           0 :     VR_INFO_DEC();
     134             :     int i, ret;
     135             :     uint16_t slave_id;
     136           0 :     char *duplex[] = {"half", "full"};
     137             :     struct rte_ether_addr mac_addr;
     138             :     struct rte_eth_link link;
     139             :     char name[VR_INTERFACE_NAME_LEN];
     140             :     struct rte_eth_bond_8023ad_slave_info info;
     141             : 
     142             :     /* Display bond slave inforamtion */
     143           0 :     for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
     144           0 :         slave_id = ethdev->ethdev_slaves[i];
     145             : 
     146           0 :         ret = rte_eth_dev_get_name_by_port(slave_id, name);
     147           0 :         if (ret != 0) {
     148           0 :             RTE_LOG(ERR, VROUTER, "%s: Error getting slave interface name "
     149             :                                     "slave_id:%d \n", __func__, slave_id);
     150           0 :             return VR_INFO_FAILED;
     151             :         }
     152             : 
     153             : 
     154           0 :         VI_PRINTF("Slave Interface(%d): %s \n", i, name);
     155           0 :         VI_PRINTF("Slave Interface Driver: %s\n",
     156             :             rte_eth_devices[slave_id].device->driver->name);
     157             : 
     158           0 :         rte_eth_link_get_nowait(slave_id, &link);
     159           0 :         ret = dpdk_bond_info_mii_status(msg_req, slave_id, &link);
     160           0 :         if (ret < 0) {
     161           0 :             return VR_INFO_FAILED;
     162             :         }
     163             : 
     164           0 :         ret = rte_eth_bond_8023ad_slave_info(port_id, slave_id, &info);
     165           0 :         if (ret == 0) {
     166           0 :             VI_PRINTF("Permanent HW addr:"MAC_FORMAT "\n",
     167             :                           MAC_VALUE(info.actor.system.addr_bytes));
     168           0 :             VI_PRINTF("Aggregator ID: %d\n", info.agg_port_id);
     169             : 
     170           0 :             VI_PRINTF("Duplex: %s\n", duplex[link.link_duplex]);
     171             : 
     172           0 :             rte_eth_macaddr_get(slave_id, &mac_addr);
     173           0 :             VI_PRINTF("Bond MAC addr:"MAC_FORMAT "\n",
     174             :                         MAC_VALUE(mac_addr.addr_bytes));
     175             : 
     176           0 :             VI_PRINTF("Details actor lacp pdu: \n");
     177           0 :             VI_PRINTF("\tsystem priority: %"PRIu16"\n",
     178             :                         htons(info.actor.system_priority));
     179           0 :             VI_PRINTF("\tsystem mac address:"MAC_FORMAT "\n",
     180             :                         MAC_VALUE(info.actor.system.addr_bytes));
     181           0 :             VI_PRINTF("\tport key: %"PRIu16"\n", htons(info.actor.key));
     182           0 :             VI_PRINTF("\tport priority: %"PRIu16 "\n",
     183             :                         htons(info.actor.port_priority));
     184           0 :             VI_PRINTF("\tport number: %"PRIu16"\n",
     185             :                         htons(info.actor.port_number));
     186           0 :             get_port_states(msg_req, info.actor_state);
     187             : 
     188           0 :             VI_PRINTF("Details partner lacp pdu: \n");
     189           0 :             VI_PRINTF("\tsystem priority: %"PRIu16"\n",
     190             :                         htons(info.partner.system_priority));
     191           0 :             VI_PRINTF("\tsystem mac address:"MAC_FORMAT "\n",
     192             :                         MAC_VALUE(info.partner.system.addr_bytes));
     193           0 :             VI_PRINTF("\tport key: %"PRIu16"\n", htons(info.partner.key));
     194           0 :             VI_PRINTF("\tport priority: %"PRIu16"\n",
     195             :                         htons(info.partner.port_priority));
     196           0 :             VI_PRINTF("\tport number: %"PRIu16"\n",
     197             :                         htons(info.partner.port_number));
     198           0 :             get_port_states(msg_req, info.partner_state);
     199             :         } else {
     200           0 :             VI_PRINTF("\n");
     201             :         }
     202             :     }
     203           0 :     return 0;
     204             : }
     205             : 
     206             : static int
     207           0 : dpdk_bond_info_show_master(VR_INFO_ARGS, uint16_t port_id,
     208             :     struct vr_dpdk_ethdev *ethdev)
     209             : {
     210           0 :     VR_INFO_DEC();
     211             :     int ret, bond_mode;
     212             :     uint16_t slave_id;
     213             :     struct rte_eth_link link;
     214             :     struct rte_eth_bond_8023ad_slave_info info;
     215             : 
     216             :     /* Get bond mode */
     217           0 :     bond_mode = rte_eth_bond_mode_get(port_id);
     218           0 :     switch (bond_mode) {
     219           0 :     case BONDING_MODE_ROUND_ROBIN:
     220           0 :         VI_PRINTF("Bonding Mode: Round Robin\n");
     221           0 :         break;
     222           0 :     case BONDING_MODE_ACTIVE_BACKUP:
     223           0 :         VI_PRINTF("Bonding Mode: Active Backup\n");
     224           0 :         break;
     225           0 :     case BONDING_MODE_BALANCE:
     226           0 :         VI_PRINTF("Bonding Mode: Balance\n");
     227           0 :         break;
     228           0 :     case BONDING_MODE_BROADCAST:
     229           0 :         VI_PRINTF("Bonding Mode: Broadcast\n");
     230           0 :         break;
     231           0 :     case BONDING_MODE_8023AD:
     232           0 :         VI_PRINTF("Bonding Mode: 802.3AD Dynamic Link Aggregation\n");
     233           0 :         break;
     234           0 :     case BONDING_MODE_TLB:
     235           0 :         VI_PRINTF("Bonding Mode: Adaptive TLB(Trnasmit Load Balancing)\n");
     236           0 :         break;
     237           0 :     case BONDING_MODE_ALB:
     238           0 :         VI_PRINTF("Bonding Mode: Adaptive Load Balancing(Tx/Rx)\n");
     239           0 :         break;
     240           0 :     default:
     241           0 :         VI_PRINTF("Bonding Mode: None\n");
     242             :     }
     243             : 
     244             :     /* Transmit Hash Policy */
     245           0 :     ret = rte_eth_bond_xmit_policy_get(port_id);
     246           0 :     switch (ret) {
     247           0 :     case BALANCE_XMIT_POLICY_LAYER2:
     248           0 :         VI_PRINTF("Transmit Hash Policy: Layer 2 (Ethernet MAC)\n");
     249           0 :         break;
     250           0 :     case BALANCE_XMIT_POLICY_LAYER23:
     251           0 :         VI_PRINTF("Transmit Hash Policy: Layer 2+3 (Ethernet MAC + "
     252             :             "IP Addresses) transmit load balancing\n");
     253           0 :         break;
     254           0 :     case BALANCE_XMIT_POLICY_LAYER34:
     255           0 :         VI_PRINTF("Transmit Hash Policy: Layer 3+4 (IP Addresses + "
     256             :             "UDP Ports) transmit load balancing\n");
     257           0 :         break;
     258           0 :     default:
     259           0 :         VI_PRINTF("Transmit Hash Policy: None\n");
     260             :     }
     261             : 
     262           0 :     rte_eth_link_get_nowait(port_id, &link);
     263           0 :     ret = dpdk_bond_info_mii_status(msg_req, port_id, &link);
     264           0 :     if (ret < 0) {
     265           0 :         return VR_INFO_FAILED;
     266             :     }
     267             : 
     268           0 :     VI_PRINTF("Up Delay (ms): %d\n",
     269             :         rte_eth_bond_link_up_prop_delay_get(port_id));
     270           0 :     VI_PRINTF("Down Delay (ms): %d\n",
     271             :         rte_eth_bond_link_down_prop_delay_get(port_id));
     272           0 :     if(rte_eth_devices[port_id].device &&
     273           0 :             rte_eth_devices[port_id].device->driver) {
     274           0 :         VI_PRINTF("Driver: %s\n\n",
     275             :             rte_eth_devices[port_id].device->driver->name);
     276             :     }
     277             : 
     278           0 :     if (bond_mode == BONDING_MODE_8023AD) {
     279           0 :         ret = dpdk_bond_mode_8023ad(msg_req, port_id);
     280           0 :         if (ret < 0) {
     281           0 :             return VR_INFO_FAILED;
     282             :         }
     283             :     }
     284             : 
     285           0 :     slave_id = ethdev->ethdev_slaves[0];
     286             : 
     287           0 :     ret = rte_eth_bond_8023ad_slave_info(port_id, slave_id, &info);
     288           0 :     if (ret != 0) {
     289           0 :         RTE_LOG(ERR, VROUTER, "%s: Error getting slave info bond:%d slave:%d\n",
     290             :                                 __func__, port_id, slave_id);
     291           0 :         return VR_INFO_FAILED;
     292             :     }
     293             : 
     294           0 :     VI_PRINTF("System priority: %"PRIu16"\n", htons(info.actor.system_priority));
     295           0 :     VI_PRINTF("System MAC address:"MAC_FORMAT "\n",
     296             :         MAC_VALUE(info.actor.system.addr_bytes));
     297           0 :     VI_PRINTF("Active Aggregator Info: \n");
     298           0 :     VI_PRINTF("\tAggregator ID: %"PRIu16"\n", htons(info.agg_port_id));
     299           0 :     VI_PRINTF("\tNumber of ports: %d \n", ethdev->ethdev_nb_slaves);
     300           0 :     VI_PRINTF("\tActor Key: %"PRIu16"\n", htons(info.actor.key));
     301           0 :     VI_PRINTF("\tPartner Key: %"PRIu16"\n", htons(info.partner.key));
     302           0 :     VI_PRINTF("\tPartner Mac Address: "MAC_FORMAT "\n\n",
     303             :         MAC_VALUE(info.partner.system.addr_bytes));
     304           0 :     return 0;
     305             : }
     306             : 
     307             : /* dpdk_info_get_bond provide the bond master & slave information */
     308             : int
     309           0 : dpdk_info_get_bond(VR_INFO_ARGS)
     310             : {
     311             :     uint16_t port_id;
     312             :     struct vr_dpdk_bond_port_list port_list;
     313             :     struct vr_dpdk_ethdev *ethdev;
     314           0 :     char name[VR_INTERFACE_NAME_LEN] = "";
     315             :     int ret, i;
     316             : 
     317             :     /* If output buffer size(--buffsz) is sent from CLI, then allocate with
     318             :        that size else allocate with default size */
     319           0 :     VR_INFO_BUF_INIT();
     320             :     /* Get the port_id list for master, Incase of non-bond devices, it return here */
     321           0 :     if (!dpdk_find_bond_port_id_list(&port_list)) {
     322           0 :         RTE_LOG(ERR, VROUTER, "%s: Port Id list is invalid\n", __func__);
     323           0 :         return -1;
     324             :     }
     325             : 
     326           0 :     VI_PRINTF("No. of bond id available: %d\n", port_list.intf_count);
     327           0 :     for (i = 0; i < port_list.intf_count ; i++) {
     328           0 :         port_id = port_list.intf_list[i];
     329             :         /* Get the ethdev for master port. */
     330           0 :         ethdev = &vr_dpdk.ethdevs[port_id];
     331           0 :         if (ethdev == NULL ||
     332           0 :             ethdev->ethdev_ptr == NULL) {
     333           0 :             RTE_LOG(ERR, VROUTER, "%s: Ethdev not available port: %d\n",
     334             :                                    __func__, port_id);
     335           0 :             continue;
     336             :         }
     337             : 
     338           0 :         rte_eth_dev_get_name_by_port(port_id, name);
     339           0 :         VI_PRINTF("=================================================\n");
     340           0 :         VI_PRINTF("|| Bond : %s No. of bond slaves: %d ||\n",
     341             :                     name, ethdev->ethdev_nb_slaves);
     342           0 :         VI_PRINTF("=================================================\n");
     343             : 
     344           0 :         ret = dpdk_bond_info_show_master(msg_req, port_id, ethdev);
     345           0 :         if (ret < 0) {
     346           0 :             RTE_LOG(ERR, VROUTER, "%s failed to show master info port_id:%d(ret:%d)\n",
     347             :                     __func__, port_id, ret);
     348             :         }
     349             : 
     350           0 :         ret = dpdk_bond_info_show_slave(msg_req, port_id, ethdev);
     351           0 :         if (ret < 0) {
     352           0 :             RTE_LOG(ERR, VROUTER, "%s failed to show slave info port_id:%d(ret:%d)\n",
     353             :                     __func__, port_id, ret);
     354             :         }
     355             :     }
     356           0 :     return 0;
     357             : }
     358             : 
     359             : static int
     360           0 : display_lacp_conf(VR_INFO_ARGS, uint16_t port_id)
     361             : {
     362             : 
     363           0 :     VR_INFO_DEC();
     364           0 :     char *lacp_rate[] = {"slow","fast"};
     365             :     struct rte_eth_bond_8023ad_conf conf;
     366             : 
     367             :     /* Check LACP protocol is configured for the bond interface. */
     368           0 :     VI_PRINTF("LACP Rate: %s\n\n",
     369             :         lacp_rate[rte_eth_bond_lacp_rate_get(port_id)]);
     370             : 
     371           0 :     rte_eth_bond_8023ad_conf_get(port_id, &conf);
     372             : 
     373           0 :     VI_PRINTF("Fast periodic (ms): %d\n", conf.fast_periodic_ms);
     374           0 :     VI_PRINTF("Slow periodic (ms): %d\n", conf.slow_periodic_ms);
     375           0 :     VI_PRINTF("Short timeout (ms): %d\n", conf.short_timeout_ms);
     376           0 :     VI_PRINTF("Long timeout (ms): %d\n", conf.long_timeout_ms);
     377           0 :     VI_PRINTF("Aggregate wait timeout (ms): %d\n",
     378             :         conf.aggregate_wait_timeout_ms);
     379           0 :     VI_PRINTF("Tx period (ms): %d\n", conf.tx_period_ms);
     380           0 :     VI_PRINTF("Update timeout (ms): %d\n", conf.update_timeout_ms);
     381           0 :     VI_PRINTF("Rx marker period (ms): %d\n\n", conf.rx_marker_period_ms);
     382           0 :     return 0;
     383             : 
     384             : }
     385             : 
     386             : int
     387           0 : dpdk_info_get_lacp(VR_INFO_ARGS)
     388             : {
     389             : 
     390           0 :     uint16_t port_id, slave_id = 0;
     391             :     struct vr_dpdk_ethdev *ethdev;
     392             :     struct vr_dpdk_bond_port_list port_list;
     393           0 :     int i, j, ret = 0;
     394           0 :     char name[VR_INTERFACE_NAME_LEN] = "";
     395             :     struct rte_eth_bond_8023ad_slave_info info;
     396             :     uint64_t lacp_rx_cnt, lacp_tx_cnt;
     397             : 
     398             : 
     399           0 :     VR_INFO_BUF_INIT();
     400             : 
     401             :     /* expecting buf string to be either all or conf */
     402           0 :     if ((strcmp(msg_req->inbuf, "all") &&
     403           0 :         (strcmp(msg_req->inbuf, "conf")))) {
     404           0 :         RTE_LOG(ERR, VROUTER, "Invalid argument.\n");
     405           0 :         return -1;
     406             :     }
     407             : 
     408             :     /* Get the port_id list for master, Incase of non-bond devices,
     409             :        it return here. */
     410           0 :     if (!dpdk_find_bond_port_id_list(&port_list)) {
     411           0 :         RTE_LOG(ERR, VROUTER, "%s: Port Id is invalid\n", __func__);
     412           0 :         return -1;
     413             :     }
     414             : 
     415           0 :     VI_PRINTF("No. of bond ids: %d\n", port_list.intf_count);
     416           0 :     for (j = 0; j < port_list.intf_count; j++) {
     417           0 :         port_id = port_list.intf_list[j];
     418             : 
     419           0 :         rte_eth_dev_get_name_by_port(port_id, name);
     420           0 :         VI_PRINTF("=======================================\n");
     421           0 :         VI_PRINTF("|| Bond Interface(%d): %s ||\n", port_id, name);
     422           0 :         VI_PRINTF("=======================================\n");
     423             : 
     424           0 :         if (strcmp(msg_req->inbuf, "all") == 0) {
     425           0 :             ret = display_lacp_conf(msg_req, port_id);
     426             : 
     427           0 :             ethdev = &vr_dpdk.ethdevs[port_id];
     428           0 :             if (ethdev == NULL ||
     429           0 :                 ethdev->ethdev_ptr == NULL) {
     430           0 :                 RTE_LOG(ERR, VROUTER, "%s: Ethdev not available port id: %d\n",
     431             :                                        __func__, port_id);
     432           0 :                 continue;
     433             :             }
     434             : 
     435             :             /* Displaying bond slave inforamtion */
     436           0 :             for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
     437           0 :                 slave_id = ethdev->ethdev_slaves[i];
     438             : 
     439           0 :                 ret = rte_eth_dev_get_name_by_port(slave_id, name);
     440           0 :                 if (ret != 0) {
     441           0 :                     RTE_LOG(ERR, VROUTER, "%s: Error getting dev name "
     442             :                             "port: %d slave: %d \n", __func__, port_id, slave_id);
     443           0 :                     continue;
     444             :                 }
     445             : 
     446           0 :                 VI_PRINTF("Slave Interface(%d): %s \n", i, name);
     447             : 
     448           0 :                 ret = rte_eth_bond_8023ad_slave_info(port_id, slave_id, &info);
     449           0 :                 if (ret == 0) {
     450           0 :                     VI_PRINTF("Details actor lacp pdu: \n");
     451           0 :                     ret = get_port_states(msg_req, info.actor_state);
     452           0 :                     if (ret < 0)
     453           0 :                         RTE_LOG(ERR, VROUTER, "Failed to get stats for actor port: %d\n",
     454             :                                                port_id);
     455             : 
     456           0 :                     VI_PRINTF("Details partner lacp pdu: \n");
     457           0 :                     ret = get_port_states(msg_req, info.partner_state);
     458           0 :                     if (ret < 0)
     459           0 :                         RTE_LOG(ERR, VROUTER, "Failed to get stats for partner port=%d\n",
     460             :                                                port_id);
     461             :                 } else {
     462           0 :                     VI_PRINTF("Port id: %d slave id: %d Link status: DOWN\n\n", port_id, slave_id);
     463             :                 }
     464             :             }
     465             : 
     466           0 :             VI_PRINTF("LACP Packet Statistics:\n");
     467           0 :             VI_PRINTF("\t\t Tx \t Rx\n");
     468             : 
     469           0 :             for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
     470           0 :                 slave_id = ethdev->ethdev_slaves[i];
     471             : 
     472           0 :                 ret = rte_eth_dev_get_name_by_port(slave_id, name);
     473           0 :                 if (ret != 0) {
     474           0 :                     RTE_LOG(ERR, VROUTER, "%s: Error getting dev name id:%d\n",
     475             :                                             __func__, slave_id);
     476             :                 }
     477             : 
     478           0 :                 lacp_tx_cnt = rte_eth_bond_8023ad_lacp_tx_count(slave_id, 0);
     479             :                 if (lacp_tx_cnt < 0) {
     480             :                     RTE_LOG(ERR, VROUTER, "Failed to get lacp tx count  port=%d\n",
     481             :                                            port_id);
     482             :                     continue;
     483             :                 }
     484             : 
     485           0 :                 lacp_rx_cnt = rte_eth_bond_8023ad_lacp_rx_count(slave_id, 0);
     486             :                 if (lacp_rx_cnt < 0) {
     487             :                     RTE_LOG(ERR, VROUTER, "Failed to get lacp rx count  port=%d\n",
     488             :                                            port_id);
     489             :                     continue;
     490             :                 }
     491             : 
     492           0 :                 VI_PRINTF("%s\t%"PRId64"\t%"PRId64"\n", name, lacp_tx_cnt, lacp_rx_cnt);
     493             :             }
     494           0 :             VI_PRINTF("\n");
     495           0 :         } else if (strcmp(msg_req->inbuf, "conf") == 0) {
     496           0 :             ret = display_lacp_conf(msg_req, port_id);
     497             :         }
     498             :     }
     499           0 :     return 0;
     500             : }
     501             : 
     502             : static void
     503           3 : walk_cb(struct rte_mempool *mp, void *arg __rte_unused)
     504             : {
     505           3 :     vr_info_t *msg_req = (vr_info_t * ) arg;
     506           3 :     VR_INFO_DEC();
     507             : 
     508             :     /* redefining VR_INFO_FAILED to prevent VI_PRINTF
     509             :        to return non-void value */
     510             :     #undef VR_INFO_FAILED
     511             :     #define VR_INFO_FAILED
     512             : 
     513             :     /* redefining VR_INFO_MSG_TRUNC to prevent VI_PRINTF
     514             :        to return non-void value */
     515             :     #undef VR_INFO_MSG_TRUNC
     516             :     #define VR_INFO_MSG_TRUNC
     517             : 
     518           3 :     VI_PRINTF("%-20s\t", mp->name);
     519           3 :     VI_PRINTF("%d\t", mp->size);
     520           3 :     VI_PRINTF("%d\t", rte_mempool_in_use_count(mp));
     521           3 :     VI_PRINTF("%d\t\n", rte_mempool_avail_count(mp));
     522             : 
     523             :     #undef VR_INFO_FAILED
     524             :     #define VR_INFO_FAILED - 1
     525             : 
     526             :     #undef VR_INFO_MSG_TRUNC
     527             :     #define VR_INFO_MSG_TRUNC - 2
     528           3 :     return;
     529             : }
     530             : 
     531             : int
     532           1 : dpdk_info_get_mempool(VR_INFO_ARGS)
     533           1 : {
     534           1 :     int reqd_mempool = 0;
     535           1 :     struct rte_mempool *mp = NULL;
     536             :     struct rte_mempool_memhdr *memhdr;
     537           1 :     unsigned lcore_id = 0, common_count = 0, cache_count = 0, count = 0;
     538           1 :     size_t mem_len = 0;
     539           1 :     char col_names[] = "Name\t\t\tSize\tUsed\tAvailable";
     540             :     /* Adding 25 to extend the seperator a bit */
     541           1 :     int col_size = (sizeof(col_names) / sizeof(col_names[0])) + 25;
     542           1 :     char seperator[col_size];
     543             : 
     544           1 :     VR_INFO_BUF_INIT();
     545             : 
     546           1 :     if (strcmp(msg_req->inbuf, "all") == 0) {
     547           1 :         reqd_mempool = 1;
     548             :     }
     549           1 :     switch (reqd_mempool) {
     550           0 :     case 0:
     551           0 :         mp = rte_mempool_lookup(msg_req->inbuf);
     552           0 :         if (mp == NULL) {
     553           0 :             RTE_LOG(ERR, VROUTER, "Mempool name does not exists.\n");
     554           0 :             return -1;
     555             :         }
     556             : 
     557           0 :         VI_PRINTF("%s\n", mp->name);
     558           0 :         VI_PRINTF("flags = %x\n", mp->flags);
     559           0 :         VI_PRINTF("nb_mem_chunks = %u\n", mp->nb_mem_chunks);
     560           0 :         VI_PRINTF("size = %"
     561             :             PRIu32 "\n", mp->size);
     562           0 :         VI_PRINTF("populated_size = %"
     563             :             PRIu32 "\n", mp->populated_size);
     564           0 :         VI_PRINTF("header_size = %"
     565             :             PRIu32 "\n", mp->header_size);
     566           0 :         VI_PRINTF("elt_size = %"
     567             :             PRIu32 "\n", mp->elt_size);
     568           0 :         VI_PRINTF("trailer_size = %"
     569             :             PRIu32 "\n", mp->trailer_size);
     570           0 :         VI_PRINTF("total_obj_size = %"
     571             :             PRIu32 "\n",
     572             :             mp->header_size + mp->elt_size + mp->trailer_size);
     573           0 :         VI_PRINTF("private_data_size = %"
     574             :             PRIu32 "\n", mp->private_data_size);
     575             : 
     576           0 :         STAILQ_FOREACH(memhdr, &mp->mem_list, next)
     577           0 :         mem_len += memhdr->len;
     578           0 :         if (mem_len != 0) {
     579           0 :             VI_PRINTF("avg bytes/object = %#Lf\n",
     580             :                 (long double) mem_len / mp->size);
     581             :         }
     582             : 
     583           0 :         VI_PRINTF("Internal cache infos:\n");
     584           0 :         VI_PRINTF("\tcache_size=%"
     585             :             PRIu32 "\n", mp->cache_size);
     586             : 
     587           0 :         if (mp->cache_size == 0) {
     588           0 :             count = 0;
     589             :         } else {
     590           0 :             for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
     591           0 :                 cache_count = mp->local_cache[lcore_id].len;
     592           0 :                 if (cache_count != 0) {
     593           0 :                     VI_PRINTF("\tcache_count[%u]=%"
     594             :                         PRIu32 "\n", lcore_id, cache_count);
     595             :                 }
     596           0 :                 count += cache_count;
     597             :             }
     598             :         }
     599           0 :         VI_PRINTF("total_cache_count=%u\n", count);
     600           0 :         common_count = rte_mempool_ops_get_count(mp);
     601           0 :         if ((cache_count + common_count) > mp->size) {
     602           0 :             common_count = mp->size - cache_count;
     603             :         }
     604           0 :         VI_PRINTF("common_pool_count=%u\n\n", common_count);
     605           0 :         break;
     606             : 
     607           1 :     case 1:
     608           1 :         memset(seperator, '-', col_size);
     609           1 :         seperator[col_size-1] = '\0';
     610           1 :         VI_PRINTF("%s\n", seperator);
     611           1 :         VI_PRINTF("%s\n", col_names);
     612           1 :         VI_PRINTF("%s\n", seperator);
     613           1 :         rte_mempool_walk(walk_cb, msg_req);
     614           1 :         VI_PRINTF("\n\n");
     615           1 :         break;
     616             : 
     617             :     }
     618           1 :     return 0;
     619             : }
     620             : 
     621             : static int
     622           0 : display_eth_stats(VR_INFO_ARGS, struct rte_eth_stats eth_stats)
     623             : {
     624             : 
     625           0 :     VR_INFO_DEC();
     626             :     int i, queue_size;
     627             :     char seperator[SEPERATOR];
     628             : 
     629           0 :     VI_PRINTF("RX Device Packets:%"
     630             :         PRId64 ", Bytes:%"
     631             :         PRId64 ", Errors:%"
     632             :         PRId64 ", Nombufs:%"
     633             :         PRId64 "\n", eth_stats.ipackets,
     634             :         eth_stats.ibytes, eth_stats.ierrors, eth_stats.rx_nombuf);
     635           0 :     VI_PRINTF("Dropped RX Packets:%"
     636             :         PRId64 "\n", eth_stats.imissed);
     637           0 :     VI_PRINTF("TX Device Packets:%"
     638             :         PRId64 ", Bytes:%"
     639             :         PRId64 ", Errors:%"
     640             :         PRId64 "\n", eth_stats.opackets, eth_stats.obytes, eth_stats.oerrors);
     641             : 
     642           0 :     queue_size = sizeof(eth_stats.q_ipackets) / sizeof(eth_stats.q_ipackets[0]);
     643           0 :     memset(seperator, '-', SEPERATOR);
     644           0 :     seperator[SEPERATOR-1] = '\0';
     645             : 
     646           0 :     VI_PRINTF("%s", "Queue Rx:");
     647           0 :     for (i = 0; i < queue_size; i++) {
     648           0 :         if (eth_stats.q_ipackets[i] != 0) {
     649           0 :             VI_PRINTF(" [%d]", i);
     650           0 :             VI_PRINTF("%"
     651             :                 PRId64 " ", eth_stats.q_ipackets[i]);
     652             :         }
     653             :     }
     654           0 :     VI_PRINTF("\n");
     655             : 
     656           0 :     VI_PRINTF("%s", "      Tx:");
     657           0 :     for (i = 0; i < queue_size; i++) {
     658           0 :         if (eth_stats.q_opackets[i] != 0) {
     659           0 :             VI_PRINTF(" [%d]", i);
     660           0 :             VI_PRINTF("%"
     661             :                 PRId64 " ", eth_stats.q_opackets[i]);
     662             :         }
     663             :     }
     664           0 :     VI_PRINTF("\n");
     665             : 
     666           0 :     VI_PRINTF("%s", "      Rx Bytes:");
     667           0 :     for (i = 0; i < queue_size; i++) {
     668           0 :         if (eth_stats.q_ibytes[i] != 0) {
     669           0 :             VI_PRINTF(" [%d]", i);
     670           0 :             VI_PRINTF("%"
     671             :                 PRId64 " ", eth_stats.q_ibytes[i]);
     672             :         }
     673             :     }
     674           0 :     VI_PRINTF("\n");
     675             : 
     676           0 :     VI_PRINTF("%s", "      Tx Bytes:");
     677           0 :     for (i = 0; i < queue_size; i++) {
     678           0 :         if (eth_stats.q_obytes[i] != 0) {
     679           0 :             VI_PRINTF(" [%d]", i);
     680           0 :             VI_PRINTF("%"
     681             :                 PRId64 " ", eth_stats.q_obytes[i]);
     682             :         }
     683             :     }
     684           0 :     VI_PRINTF("\n");
     685             : 
     686           0 :     VI_PRINTF("%s", "      Errors:");
     687           0 :     for (i = 0; i < queue_size; i++) {
     688           0 :         if (eth_stats.q_errors[i] != 0) {
     689           0 :             VI_PRINTF(" [%d]", i);
     690           0 :             VI_PRINTF("%"
     691             :                 PRId64 " ", eth_stats.q_errors[i]);
     692             :         }
     693             :     }
     694           0 :     VI_PRINTF("\n");
     695           0 :     VI_PRINTF("%s\n\n", seperator);
     696           0 :     return 0;
     697             : }
     698             : 
     699             : int
     700           0 : dpdk_info_get_stats(VR_INFO_ARGS)
     701             : {
     702             : 
     703           0 :     uint16_t port_id, slave_id = 0;
     704           0 :     int i, j, ret = 0;
     705             :     struct rte_eth_stats eth_stats;
     706             :     struct vr_dpdk_ethdev *ethdev;
     707             :     struct vr_dpdk_bond_port_list port_list;
     708           0 :     char name[VR_INTERFACE_NAME_LEN] = "";
     709             : 
     710           0 :     VR_INFO_BUF_INIT();
     711             : 
     712             :     /* msg req buf is not eth, return */
     713           0 :     if (strcmp(msg_req->inbuf, "eth")) {
     714           0 :         RTE_LOG(ERR, VROUTER, "Invalid argument.\n");
     715           0 :         return -1;
     716             :     }
     717             : 
     718             :     /* Get the port_id list for master, Incase of non-bond devices,
     719             :        it return here.
     720             :      */
     721           0 :     if (!dpdk_find_bond_port_id_list(&port_list)) {
     722           0 :         RTE_LOG(ERR, VROUTER, "%s: Port Id is invalid\n", __func__);
     723           0 :         return -1;
     724             :     }
     725             : 
     726           0 :     VI_PRINTF("No. of bond ids: %d\n", port_list.intf_count);
     727           0 :     for (j = 0; j < port_list.intf_count; j++) {
     728           0 :         port_id = port_list.intf_list[j];
     729             :         /* Get the ethdev for master port. */
     730           0 :         ethdev = &vr_dpdk.ethdevs[port_id];
     731           0 :         if (ethdev == NULL ||
     732           0 :             ethdev->ethdev_ptr == NULL) {
     733           0 :             RTE_LOG(ERR, VROUTER, "%s: Ethdev not available port id: %d\n",
     734             :                                   __func__, port_id);
     735           0 :             continue;
     736             :         }
     737             : 
     738           0 :         if (rte_eth_stats_get(port_id, &eth_stats) != 0) {
     739           0 :             continue;
     740             :         }
     741             : 
     742           0 :         rte_eth_dev_get_name_by_port(port_id, name);
     743           0 :         if (strcmp(msg_req->inbuf, "eth") == 0) {
     744           0 :             VI_PRINTF("Master %s Info: No. of slaves: %d\n",
     745             :                        name, ethdev->ethdev_nb_slaves);
     746           0 :             VI_PRINTF("============================================\n");
     747           0 :             ret = display_eth_stats(msg_req, eth_stats);
     748             : 
     749             :             /* Displaying slave stats */
     750           0 :             for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
     751           0 :                 slave_id = ethdev->ethdev_slaves[i];
     752           0 :                 ret = rte_eth_dev_get_name_by_port(slave_id, name);
     753           0 :                 if (ret != 0) {
     754           0 :                     RTE_LOG(ERR, VROUTER, "%s: Error getting dev name "
     755             :                             "port: %d slave: %d\n", __func__, port_id, slave_id);
     756           0 :                     continue;
     757             :                 }
     758           0 :                 VI_PRINTF("Slave Info(%s): \n", name);
     759           0 :                 if (rte_eth_stats_get(slave_id, &eth_stats) != 0) {
     760           0 :                     RTE_LOG(ERR, VROUTER, "%s: Error getting interface stats "
     761             :                             "port: %d slave: %d\n", __func__, port_id, slave_id);
     762           0 :                     continue;
     763             :                 }
     764           0 :                 ret = display_eth_stats(msg_req, eth_stats);
     765             :             }
     766             :         }
     767             :     }
     768             : 
     769           0 :     return 0;
     770             : }
     771             : 
     772             : static int
     773           0 : __display_xstats(VR_INFO_ARGS, uint16_t port_id, int xstats_count, bool is_all,
     774             :         uint64_t *values, struct rte_eth_xstat_name *xstats_names)
     775           0 : {
     776             : 
     777           0 :     VR_INFO_DEC();
     778           0 :     int ret, i, segment_lookup[VR_DPDK_BOND_MAX_SLAVES][xstats_count],
     779           0 :         rpi = 0, rbi = 0, tpi = 0, tbi = 0, ei = 0, oth = 0;
     780             :     char seperator[SEPERATOR];
     781           0 :     memset(seperator, '-', SEPERATOR);
     782           0 :     seperator[SEPERATOR-1] = '\0';
     783             : 
     784           0 :     if (xstats_count != rte_eth_xstats_get_names_by_id(port_id, xstats_names,
     785             :         xstats_count, NULL)) {
     786           0 :         RTE_LOG(ERR, VROUTER, "Cannot get xstat names\n");
     787           0 :         return VR_INFO_FAILED;
     788             :     }
     789             : 
     790           0 :     ret = rte_eth_xstats_get_by_id(port_id, NULL, values, xstats_count);
     791           0 :     if (ret < 0 || ret > xstats_count) {
     792           0 :         RTE_LOG(ERR, VROUTER, "Cannot get xstats\n");
     793           0 :         return VR_INFO_FAILED;
     794             :     }
     795             :     /* Adding the indices of respective segments in segment_lookup array */
     796           0 :     for (i = 0; i < xstats_count; i++) {
     797           0 :         if (strstr(xstats_names[i].name, "rx") &&
     798           0 :             strstr(xstats_names[i].name, "packets")) {
     799           0 :             segment_lookup[RX_PACKETS][rpi++] = i;
     800           0 :         } else if (strstr(xstats_names[i].name, "tx") &&
     801           0 :               strstr(xstats_names[i].name, "packets")) {
     802           0 :             segment_lookup[TX_PACKETS][tpi++] = i;
     803           0 :         } else if (strstr(xstats_names[i].name, "rx") &&
     804           0 :               strstr(xstats_names[i].name, "bytes")) {
     805           0 :             segment_lookup[RX_BYTES][rbi++] = i;
     806           0 :         } else if (strstr(xstats_names[i].name, "tx") &&
     807           0 :               strstr(xstats_names[i].name, "bytes")) {
     808           0 :             segment_lookup[TX_BYTES][tbi++] = i;
     809           0 :         } else if (strstr(xstats_names[i].name, "errors")) {
     810           0 :             segment_lookup[ERRORS][ei++] = i;
     811             :         } else {
     812           0 :             segment_lookup[OTHERS][oth++] = i;
     813             :         }
     814             :     }
     815             : 
     816             :     /* Printing xstats name and value segment-wise */
     817           0 :     VI_PRINTF("Rx Packets: \n");
     818           0 :     for (i = 0; i < rpi - 1; i++) {
     819           0 :         if (values[segment_lookup[RX_PACKETS][i]] != 0 || is_all) {
     820           0 :             VI_PRINTF("\t%s: %"PRIu64 "\n",
     821             :                 xstats_names[segment_lookup[RX_PACKETS][i]].name,
     822             :                 values[segment_lookup[RX_PACKETS][i]]);
     823             :         }
     824             :     }
     825           0 :     VI_PRINTF("Tx Packets: \n");
     826           0 :     for (i = 0; i < tpi - 1; i++) {
     827           0 :         if (values[segment_lookup[TX_PACKETS][i]] != 0 || is_all) {
     828           0 :             VI_PRINTF("\t%s: %"PRIu64 "\n",
     829             :                 xstats_names[segment_lookup[TX_PACKETS][i]].name,
     830             :                 values[segment_lookup[TX_PACKETS][i]]);
     831             :         }
     832             :     }
     833           0 :     VI_PRINTF("Rx Bytes: \n");
     834           0 :     for (i = 0; i < rbi - 1; i++) {
     835           0 :         if (values[segment_lookup[RX_BYTES][i]] != 0 || is_all) {
     836           0 :             VI_PRINTF("\t%s: %"PRIu64 "\n",
     837             :                 xstats_names[segment_lookup[RX_BYTES][i]].name,
     838             :                 values[segment_lookup[RX_BYTES][i]]);
     839             :         }
     840             :     }
     841           0 :     VI_PRINTF("Tx Bytes: \n");
     842           0 :     for (i = 0; i < tbi - 1; i++) {
     843           0 :         if (values[segment_lookup[TX_BYTES][i]] != 0 || is_all) {
     844           0 :             VI_PRINTF("\t%s: %"PRIu64 "\n",
     845             :                 xstats_names[segment_lookup[TX_BYTES][i]].name,
     846             :                 values[segment_lookup[TX_BYTES][i]]);
     847             :         }
     848             :     }
     849           0 :     VI_PRINTF("Errors: \n");
     850           0 :     for (i = 0; i < ei - 1; i++) {
     851           0 :         if (values[segment_lookup[ERRORS][i]] != 0 || is_all) {
     852           0 :             VI_PRINTF("\t%s: %"PRIu64 "\n",
     853             :                 xstats_names[segment_lookup[ERRORS][i]].name,
     854             :                 values[segment_lookup[ERRORS][i]]);
     855             :         }
     856             :     }
     857           0 :     VI_PRINTF("Others: \n");
     858           0 :     for (i = 0; i < oth - 1; i++) {
     859           0 :         if (values[segment_lookup[OTHERS][i]] != 0 || is_all) {
     860           0 :             VI_PRINTF("\t%s: %"PRIu64 "\n",
     861             :                 xstats_names[segment_lookup[OTHERS][i]].name,
     862             :                 values[segment_lookup[OTHERS][i]]);
     863             :         }
     864             :     }
     865             : 
     866           0 :     VI_PRINTF("%s\n\n", seperator);
     867           0 :     return 0;
     868             : }
     869             : 
     870             : static int
     871           0 : display_xstats(VR_INFO_ARGS, uint16_t port_id, int xstats_count, bool is_all)
     872             : {
     873           0 :     struct rte_eth_xstat_name *xstats_names = NULL;
     874           0 :     uint64_t *values = NULL;
     875           0 :     int ret = 0;
     876             : 
     877           0 :     values = (uint64_t *)vr_zalloc(
     878             :             sizeof( *values) * xstats_count, VR_INFO_REQ_OBJECT);
     879           0 :     if (values == NULL) {
     880           0 :         RTE_LOG(ERR, VROUTER, "Cannot allocate memory for xstats\n");
     881           0 :         ret = VR_INFO_FAILED;
     882           0 :         goto exit;
     883             :     }
     884             : 
     885           0 :     xstats_names = (struct rte_eth_xstat_name *)vr_zalloc(
     886             :             sizeof(struct rte_eth_xstat_name) * xstats_count, VR_INFO_REQ_OBJECT);
     887           0 :     if (xstats_names == NULL) {
     888           0 :         RTE_LOG(ERR, VROUTER, "Cannot allocate memory for xstat names\n");
     889           0 :         ret = VR_INFO_FAILED;
     890           0 :         goto exit;
     891             :     }
     892             : 
     893           0 :     ret = __display_xstats(msg_req, port_id, xstats_count, is_all, values,
     894             :             xstats_names);
     895             : 
     896           0 : exit:
     897           0 :     if (values) {
     898           0 :         vr_free(values, VR_INFO_REQ_OBJECT);
     899           0 :         values = NULL;
     900             :     }
     901           0 :     if (xstats_names) {
     902           0 :         vr_free(xstats_names, VR_INFO_REQ_OBJECT);
     903           0 :         xstats_names = NULL;
     904             :     }
     905             : 
     906           0 :     return ret;
     907             : }
     908             : 
     909             : int
     910           0 : dpdk_info_get_xstats(VR_INFO_ARGS)
     911             : {
     912             : 
     913           0 :     uint16_t port_id, slave_id = 0;
     914           0 :     int i, j, reqd_interface, ret = 0, slave = 0, xstats_count = -1;
     915           0 :     char name[VR_INTERFACE_NAME_LEN] = "";
     916           0 :     struct vrouter *router = vrouter_get(0);
     917           0 :     struct vr_dpdk_ethdev *ethdev = NULL;
     918             :     struct vr_dpdk_bond_port_list port_list;
     919           0 :     bool is_all = false;
     920             : 
     921           0 :     VR_INFO_BUF_INIT();
     922             : 
     923           0 :     is_all = !strcmp(msg_req->inbuf, "all");
     924             : 
     925             :     /* Get the port_id list for master, Incase of non-bond devices,
     926             :        it return here. */
     927           0 :     if (dpdk_find_bond_port_id_list(&port_list)) {
     928           0 :         VI_PRINTF("No. of bond ids: %d\n", port_list.intf_count);
     929           0 :         for (j = 0; j < port_list.intf_count; j++) {
     930           0 :             port_id = port_list.intf_list[j];
     931             :             /* Get the ethdev for master port. */
     932           0 :             ethdev = &vr_dpdk.ethdevs[port_id];
     933           0 :             if (ethdev->ethdev_ptr == NULL) {
     934           0 :                 RTE_LOG(ERR, VROUTER, "Ethdev not available for port=%d\n", port_id);
     935           0 :                 continue;
     936             :             }
     937             : 
     938           0 :             rte_eth_dev_get_name_by_port(port_id, name);
     939           0 :             VI_PRINTF("=======================================\n");
     940           0 :             VI_PRINTF("|| Bond Interface(%d): %s ||\n", port_id, name);
     941           0 :             VI_PRINTF("=======================================\n");
     942             : 
     943           0 :             if (!strcmp(msg_req->inbuf, "") || is_all) {
     944           0 :                 reqd_interface = 0;
     945           0 :             } else if (!strcmp(msg_req->inbuf, "0") ||
     946           0 :                     (atoi(msg_req->inbuf) > 0 &&
     947           0 :                      atoi(msg_req->inbuf) <= ethdev->ethdev_nb_slaves)) {
     948           0 :                 reqd_interface = 1;
     949             :             } else {
     950           0 :                 VI_PRINTF("There are only %d slaves available.\n\n",
     951             :                         ethdev->ethdev_nb_slaves);
     952           0 :                 continue;
     953             :             }
     954             : 
     955           0 :             xstats_count = rte_eth_xstats_get_names_by_id(port_id, NULL, 0, NULL);
     956           0 :             if (xstats_count < 0) {
     957           0 :                 RTE_LOG(ERR, VROUTER, "Cannot get xstats count port=%d\n", port_id);
     958           0 :                 continue;
     959             :             }
     960             : 
     961           0 :             switch (reqd_interface) {
     962           0 :                 case 0:
     963           0 :                     VI_PRINTF("Master Info: \n");
     964           0 :                     ret = display_xstats(msg_req, port_id, xstats_count, is_all);
     965           0 :                     if (ret < 0) {
     966           0 :                         RTE_LOG(ERR, VROUTER, "Failed to display xstats port=%d\n", port_id);
     967           0 :                         continue;
     968             :                     }
     969             : 
     970             :                     /* Displaying slave stats */
     971           0 :                     for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
     972           0 :                         slave_id = ethdev->ethdev_slaves[i];
     973           0 :                         ret = rte_eth_dev_get_name_by_port(slave_id, name);
     974           0 :                         if (ret != 0) {
     975           0 :                             RTE_LOG(ERR, VROUTER, "%s: Error getting dev  name "
     976             :                                     "port=%d slave=%d\n", __func__, port_id, slave_id);
     977           0 :                             continue;
     978             :                         }
     979           0 :                         VI_PRINTF("Slave Info(%d):%s \n", i, name);
     980             : 
     981           0 :                         xstats_count = rte_eth_xstats_get_names_by_id(slave_id, NULL,
     982             :                                 0, NULL);
     983           0 :                         if (xstats_count < 0) {
     984           0 :                             RTE_LOG(ERR, VROUTER, "Cannot get xstats count "
     985             :                                     "port=%d slave=%d\n", port_id, slave_id);
     986           0 :                             continue;
     987             :                         }
     988           0 :                         ret = display_xstats(msg_req, slave_id, xstats_count, is_all);
     989           0 :                         if (ret < 0) {
     990           0 :                             RTE_LOG(ERR, VROUTER, "Failed to display xstats "
     991             :                                     "port=%d slave=%d\n", port_id, slave_id);
     992           0 :                             continue;
     993             :                         }
     994             :                     }
     995           0 :                     break;
     996           0 :                 case 1:
     997           0 :                     if (!strcmp(msg_req->inbuf, "0")) {
     998           0 :                         VI_PRINTF("Master Info: \n");
     999           0 :                         ret = display_xstats(msg_req, port_id, xstats_count, is_all);
    1000           0 :                         if (ret < 0)
    1001           0 :                             continue;
    1002             : 
    1003             :                     } else {
    1004           0 :                         slave = atoi(msg_req->inbuf) - 1;
    1005           0 :                         slave_id = ethdev->ethdev_slaves[slave];
    1006           0 :                         ret = rte_eth_dev_get_name_by_port(slave_id, name);
    1007           0 :                         if (ret != 0) {
    1008           0 :                             RTE_LOG(ERR, VROUTER, "%s: Error getting bond interface namei "
    1009             :                                     "port=%d slave=%d\n", __func__, port_id, slave_id);
    1010           0 :                             continue;
    1011             :                         }
    1012           0 :                         VI_PRINTF("Slave Info(%d):%s \n", slave, name);
    1013           0 :                         xstats_count = rte_eth_xstats_get_names_by_id(slave_id, NULL,
    1014             :                                 0, NULL);
    1015           0 :                         if (xstats_count < 0) {
    1016           0 :                             RTE_LOG(ERR, VROUTER, "Cannot get xstats count "
    1017             :                                     "port=%d slave=%d\n", port_id, slave_id);
    1018           0 :                             continue;
    1019             :                         }
    1020           0 :                         ret = display_xstats(msg_req, slave_id, xstats_count, is_all);
    1021           0 :                         if (ret < 0)
    1022           0 :                             continue;
    1023             :                     }
    1024           0 :                     break;
    1025             :             }
    1026             :         }
    1027             :     }else {
    1028             :         /* if bond is not configured */
    1029           0 :         if (strcmp(msg_req->inbuf, "") == 0 || is_all) {
    1030           0 :             if (router->vr_eth_if[0]) {
    1031           0 :                 ethdev = (struct vr_dpdk_ethdev* ) router->vr_eth_if[0]->vif_os;
    1032             :             }
    1033           0 :             if (!ethdev) {
    1034           0 :                 RTE_LOG(ERR, VROUTER, "%s: ethdev null\n", __func__);
    1035           0 :                 return -1;
    1036             :             }
    1037             : 
    1038           0 :             port_id = ethdev->ethdev_port_id;
    1039           0 :             xstats_count = rte_eth_xstats_get_names_by_id(port_id, NULL,
    1040             :                                                             0, NULL);
    1041           0 :             if (xstats_count < 0) {
    1042           0 :                 RTE_LOG(ERR, VROUTER, "Cannot get xstats count\n");
    1043           0 :                 return -1;
    1044             :             }
    1045             : 
    1046           0 :             ret = display_xstats(msg_req, port_id, xstats_count, is_all);
    1047           0 :             if (ret < 0)
    1048           0 :                 goto err;
    1049             : 
    1050             :         } else {
    1051           0 :             RTE_LOG(ERR, VROUTER, "Invalid argument.\n");
    1052           0 :             return -1;
    1053             :         }
    1054             :     }
    1055             : 
    1056           0 :     return 0;
    1057           0 : err:
    1058           0 :     return ret;
    1059             : }
    1060             : 
    1061             : int
    1062           0 : dpdk_info_get_lcore(VR_INFO_ARGS)
    1063             : {
    1064             :     struct vr_dpdk_queue *rx_queue;
    1065             :     struct vr_dpdk_lcore *lcore;
    1066             :     unsigned char *name;
    1067             :     int i;
    1068             : 
    1069           0 :     VR_INFO_BUF_INIT();
    1070             : 
    1071           0 :     VI_PRINTF("No. of forwarding lcores: %d \n\n", vr_dpdk.nb_fwd_lcores);
    1072             : 
    1073           0 :     for (i = 0; i < vr_dpdk.nb_fwd_lcores; i++) {
    1074           0 :         VI_PRINTF("Lcore %d: \n",  (VR_DPDK_FWD_LCORE_ID + i));
    1075           0 :         lcore = vr_dpdk.lcores[VR_DPDK_FWD_LCORE_ID + i];
    1076           0 :         SLIST_FOREACH(rx_queue, &lcore->lcore_rx_head, q_next) {
    1077           0 :             name = rx_queue->q_vif->vif_name;
    1078           0 :             VI_PRINTF("\tInterface: %-20s", name);
    1079           0 :             VI_PRINTF("Queue ID: %"
    1080             :                 PRId16 " \n", rx_queue->vring_queue_id);
    1081             :         }
    1082           0 :         VI_PRINTF("\n");
    1083             :     }
    1084             : 
    1085           0 :     return 0;
    1086             : }
    1087             : 
    1088             : int
    1089           0 : dpdk_info_get_app(VR_INFO_ARGS)
    1090             : {
    1091             : 
    1092             :     uint16_t port_id;
    1093           0 :     struct vr_dpdk_ethdev *ethdev = NULL;
    1094             :     struct rte_eth_dev_info dev_info;
    1095           0 :     struct vr_dpdk_tapdev *tapdev = vr_dpdk.tapdevs;
    1096             :     struct vr_dpdk_bond_port_list port_list;
    1097             :     size_t soff;
    1098           0 :     struct vrouter *router = vrouter_get(0);
    1099           0 :     int i, j = 0, k = 0;
    1100             :     struct vr_interface *vif;
    1101           0 :     bool monitoring_intf = false, sriov_flag = false;
    1102           0 :     char name[VR_INTERFACE_NAME_LEN] = "";
    1103             : 
    1104           0 :     VR_INFO_BUF_INIT();
    1105             : 
    1106           0 :     VI_PRINTF("No. of lcores: %d \n", vr_num_cpus);
    1107           0 :     VI_PRINTF("No. of forwarding lcores: %d \n", vr_dpdk.nb_fwd_lcores);
    1108             : 
    1109             :     /* Get the port_id list for master, Incase of non-bond devices, */
    1110           0 :     if (!dpdk_find_bond_port_id_list(&port_list)) {
    1111           0 :         RTE_LOG(ERR, VROUTER, "%s: Port Id list is invalid\n", __func__);
    1112           0 :         return -1;
    1113             :     }
    1114             : 
    1115             :     /* Display vlan information */
    1116           0 :     if (vr_dpdk.vlan_vif){
    1117           0 :         VI_PRINTF("Vlan vif: %s \n", vr_dpdk.vlan_vif->vif_name);
    1118           0 :         VI_PRINTF("Vlan name: %s \n", vr_dpdk.vlan_name);
    1119           0 :         VI_PRINTF("Vlan tag: %d \n", vr_dpdk.vlan_tag);
    1120             :     }
    1121             : 
    1122           0 :     VI_PRINTF("No. of bond id available: %d\n", port_list.intf_count);
    1123           0 :     for (j = 0; j < port_list.intf_count ; j++) {
    1124           0 :         port_id = port_list.intf_list[j];
    1125           0 :         ethdev = &vr_dpdk.ethdevs[port_id];
    1126           0 :         if (ethdev == NULL ||
    1127           0 :             ethdev->ethdev_ptr == NULL) {
    1128           0 :             RTE_LOG(ERR, VROUTER, "%s: Ethdev not available\n", __func__);
    1129           0 :             continue;
    1130             :         }
    1131             : 
    1132             :         /* Display Ethdev information */
    1133           0 :         if (ethdev->ethdev_ptr) {
    1134           0 :             rte_eth_dev_get_name_by_port(port_id, name);
    1135           0 :             rte_eth_dev_info_get(port_id, &dev_info);
    1136           0 :             VI_PRINTF("Ethdev (Master: %s):\n", name);
    1137           0 :             VI_PRINTF("================================\n");
    1138           0 :             VI_PRINTF("\tMax rx queues: %"PRIu16"\n", dev_info.max_rx_queues);
    1139           0 :             VI_PRINTF("\tMax tx queues: %"PRIu16"\n", dev_info.max_tx_queues);
    1140           0 :             VI_PRINTF("\tEthdev nb rx queues: %"PRIu16"\n",
    1141             :                     ethdev->ethdev_nb_rx_queues);
    1142           0 :             VI_PRINTF("\tEthdev nb tx queues: %"PRIu16"\n",
    1143             :                     ethdev->ethdev_nb_tx_queues);
    1144           0 :             VI_PRINTF("\tEthdev nb rss queues: %"PRIu16"\n",
    1145             :                     ethdev->ethdev_nb_rss_queues);
    1146           0 :             VI_PRINTF("\tEthdev reta size: %"PRIu16"\n", ethdev->ethdev_reta_size);
    1147           0 :             VI_PRINTF("\tEthdev port id: %"PRIu16"\n", ethdev->ethdev_port_id);
    1148           0 :             VI_PRINTF("\tEthdev nb slaves: %d \n", ethdev->ethdev_nb_slaves);
    1149           0 :             VI_PRINTF("\tEthdev slaves: ");
    1150           0 :             for (i = 0; i < VR_DPDK_BOND_MAX_SLAVES; i++){
    1151           0 :                 VI_PRINTF("%"PRIu16 " ", ethdev->ethdev_slaves[i]);
    1152             :             }
    1153           0 :             VI_PRINTF("\n\n");
    1154             :         }
    1155             : 
    1156           0 :         for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
    1157           0 :             VI_PRINTF("Ethdev (Slave %d): %s\n", i, rte_eth_devices[i].data->name);
    1158           0 :             VI_PRINTF("\tNb rx queues: %"PRIu16"\n",
    1159             :                     rte_eth_devices[i].data->nb_rx_queues);
    1160           0 :             VI_PRINTF("\tNb tx queues: %"PRIu16"\n",
    1161             :                     rte_eth_devices[i].data->nb_tx_queues);
    1162           0 :             VI_PRINTF("\tEthdev reta size: %"PRIu16"\n\n", dev_info.reta_size);
    1163             :         }
    1164             :     }
    1165             : 
    1166             :     /* Display Tapdev information */
    1167           0 :     if(tapdev) {
    1168           0 :         VI_PRINTF("Tapdev:\n");
    1169           0 :         while (tapdev[k].tapdev_fd){
    1170           0 :             VI_PRINTF("\tfd: %d", tapdev[k].tapdev_fd);
    1171           0 :             if(tapdev[k].tapdev_vif) {
    1172           0 :                 VI_PRINTF("\tvif name: %s \n", tapdev[k].tapdev_vif->vif_name);
    1173             :             }
    1174           0 :             k++;
    1175             :         }
    1176             :     }
    1177           0 :     VI_PRINTF("\n");
    1178             : 
    1179             :     /* Display Monitoring interfaces */
    1180           0 :     for (i = 0; i < router->vr_max_interfaces; i++){
    1181           0 :          if (vr_dpdk.monitorings[i] != 0 &&
    1182           0 :                  vr_dpdk.monitorings[i] != VR_MAX_INTERFACES){
    1183           0 :              if (!monitoring_intf){
    1184           0 :                  VI_PRINTF("Monitorings:\n");
    1185           0 :                  monitoring_intf = true;
    1186             :              }
    1187           0 :              vif = router->vr_interfaces[i];
    1188           0 :              VI_PRINTF("\t%s\n", vif->vif_name);
    1189             :          }
    1190             :     }
    1191             : 
    1192             :     /* Display SRIOV information */
    1193           0 :     VR_DPDK_RTE_ETH_FOREACH_DEV(i){
    1194           0 :          rte_eth_dev_info_get(i, &dev_info);
    1195             :          /* Check PMD name suffix to detect SR-IOV virtual function. */
    1196           0 :          soff = strlen(dev_info.driver_name) - sizeof(VR_DPDK_VF_PMD_SFX) + 1;
    1197           0 :          if (soff > 0 &&
    1198           0 :                strncmp(dev_info.driver_name + soff, VR_DPDK_VF_PMD_SFX,
    1199             :                sizeof(VR_DPDK_VF_PMD_SFX)) == 0){
    1200           0 :              if (dev_info.max_tx_queues < vr_dpdk.nb_fwd_lcores
    1201             :                     /* We also need 2 TX queues for Netlink and Packet lcores. */
    1202             :                     + VR_DPDK_FWD_LCORE_ID - VR_DPDK_PACKET_LCORE_ID) {
    1203           0 :                  if (!sriov_flag){
    1204           0 :                      VI_PRINTF("Sriov:\n");
    1205           0 :                      sriov_flag = true;
    1206             :                  }
    1207           0 :                  VI_PRINTF("\tLcore: %d", VR_DPDK_FWD_LCORE_ID);
    1208           0 :                  VI_PRINTF("\tEthdev port id: %d", i);
    1209           0 :                  VI_PRINTF("\tDriver Name: %s\n", dev_info.driver_name);
    1210           0 :                 break;
    1211             :              }
    1212             :          }
    1213             :     }
    1214             : 
    1215           0 :     VI_PRINTF("\n");
    1216             : 
    1217           0 :     return 0;
    1218             : }
    1219             : 
    1220             : int
    1221           0 : dpdk_info_get_ddp(VR_INFO_ARGS)
    1222             : {
    1223             :     struct rte_pmd_i40e_profile_list *p_list;
    1224             :     struct rte_pmd_i40e_profile_info *p_info;
    1225             :     uint32_t p_num, size, i;
    1226             :     int ret;
    1227           0 :     uint16_t port_id = 0;
    1228           0 :     VR_INFO_BUF_INIT();
    1229             : 
    1230           0 :     if (strcmp(msg_req->inbuf, "list") != 0) {
    1231           0 :         return -1;
    1232             :     }
    1233             : 
    1234           0 :     size = I40E_MAX_PROFILE_NUM * sizeof(struct rte_pmd_i40e_profile_list);
    1235             : 
    1236           0 :     p_list = (struct rte_pmd_i40e_profile_list *)vr_zalloc(size,
    1237             :                         VR_INFO_REQ_OBJECT);
    1238           0 :     if(!p_list) {
    1239           0 :         RTE_LOG(ERR, VROUTER, "%s: Memory allocation failed\n", __func__);
    1240           0 :         return -1;
    1241             :     }
    1242             : 
    1243           0 :     ret = rte_pmd_i40e_get_ddp_list(port_id, (uint8_t *)p_list, size);
    1244             : 
    1245           0 :     if (!ret) {
    1246           0 :         p_num = p_list->p_count;
    1247           0 :         VI_PRINTF("Profile count is: %d\n\n", p_num);
    1248           0 :         if(p_num == 0) {
    1249           0 :             VI_PRINTF("DDP profile is not enabled \n\n");
    1250             :         }
    1251             : 
    1252           0 :         for (i = 0; i < p_num; i++) {
    1253           0 :                 p_info = &p_list->p_info[i];
    1254           0 :                 VI_PRINTF("Profile %d:\n", i);
    1255           0 :                 VI_PRINTF("Track id:     0x%x\n", p_info->track_id);
    1256           0 :                 VI_PRINTF("Version:      %d.%d.%d.%d\n",
    1257             :                        p_info->version.major,
    1258             :                        p_info->version.minor,
    1259             :                        p_info->version.update,
    1260             :                        p_info->version.draft);
    1261           0 :                 VI_PRINTF("Profile name: %s\n\n", p_info->name);
    1262             :         }
    1263             :     }
    1264             : 
    1265           0 :     if(p_list)
    1266           0 :         vr_free(p_list, VR_INFO_REQ_OBJECT);
    1267             : 
    1268           0 :     if(ret == -ENOTSUP) {
    1269           0 :         VI_PRINTF("DDP works only on X710 NIC series \n\n");
    1270           0 :     } else if (ret < 0) {
    1271           0 :         VI_PRINTF("Failed to get ddp list, return value is %d \n\n", ret);
    1272             :     }
    1273             : 
    1274           0 :     return 0;
    1275             : }
    1276             : 
    1277             : int
    1278           0 : dpdk_link_status_change(VR_INFO_ARGS) {
    1279           0 :     uint16_t port_id = VR_DPDK_INVALID_PORT_ID;
    1280           0 :     int i, idx = -1;
    1281             :     char args[7], oper[4];
    1282             :     char *ptr;
    1283           0 :     unsigned bond_type = VR_DPDK_BOND_MASTER;
    1284             :     struct vr_dpdk_bond_member_info member_info;
    1285           0 :     struct vrouter *router = vrouter_get(0);
    1286             : 
    1287           0 :     VR_INFO_BUF_INIT();
    1288           0 :     memcpy(args, msg_req->inbuf, 7);
    1289             : 
    1290           0 :     ptr = strtok(args, ",");
    1291           0 :     while (ptr != NULL) {
    1292           0 :         if (ptr[0] >= '0' && ptr[0] <= '2')
    1293           0 :             idx = atoi(&ptr[0]);
    1294             :         else
    1295           0 :             memcpy(oper, ptr, 4);
    1296           0 :         ptr = strtok(NULL, ",");
    1297             :     }
    1298             : 
    1299           0 :     if (idx == -1) {
    1300           0 :         VI_PRINTF("Invalid vif ID!\n");
    1301           0 :         return -1;
    1302             :     }
    1303           0 :     for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
    1304           0 :         if (vr_dpdk.ethdevs[i].ethdev_vif_idx == idx) {
    1305           0 :             port_id = vr_dpdk.ethdevs[i].ethdev_port_id;
    1306           0 :             break;
    1307             :         }
    1308             :     }
    1309             : 
    1310           0 :     if (port_id == VR_DPDK_INVALID_PORT_ID) {
    1311           0 :         RTE_LOG(ERR, VROUTER, "Port Id is invalid\n");
    1312           0 :         return -1;
    1313             :     }
    1314             : 
    1315             :     /* Set msginfo */
    1316           0 :     memset(&member_info, 0, sizeof(member_info));
    1317           0 :     strcpy(member_info.intf_name, (char *)router->vr_interfaces[idx]->vif_name);
    1318             : 
    1319           0 :     if(rte_eth_devices[port_id].device->driver->name != NULL)
    1320           0 :         snprintf(member_info.intf_drv_name, (VR_INTERFACE_NAME_LEN - 1),
    1321           0 :                 "%s", rte_eth_devices[port_id].device->driver->name);
    1322             : 
    1323           0 :     if (!strncmp(oper, "up", 2)) {
    1324           0 :         member_info.status = 1;
    1325           0 :     } else if (!strncmp(oper, "down", 4)) {
    1326           0 :         member_info.status = 0;
    1327             :     } else {
    1328           0 :         VI_PRINTF("Enter link operation 'up' or 'down'\n\n");
    1329           0 :         return -1;
    1330             :     }
    1331           0 :     vr_dpdk_nl_send_bond_intf_state(&member_info, bond_type, idx);
    1332             : 
    1333           0 :     return 0;
    1334             : }

Generated by: LCOV version 1.14