LCOV - code coverage report
Current view: top level - plugins/lldp - lldp_cli.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 3 294 1.0 %
Date: 2023-10-26 01:39:38 Functions: 6 22 27.3 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2011-2016 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : /**
      17             :  * @file
      18             :  * @brief LLDP CLI handling
      19             :  *
      20             :  */
      21             : #include <vnet/ethernet/ethernet.h>
      22             : #include <vnet/ip/ip.h>
      23             : #include <lldp/lldp.h>
      24             : #include <lldp/lldp_node.h>
      25             : 
      26             : #ifndef ETHER_ADDR_LEN
      27             : #include <net/ethernet.h>
      28             : #endif
      29             : 
      30             : static clib_error_t *
      31           0 : lldp_cfg_err_to_clib_err (lldp_cfg_err_t e)
      32             : {
      33             : 
      34           0 :   switch (e)
      35             :     {
      36           0 :     case lldp_ok:
      37           0 :       return 0;
      38           0 :     case lldp_not_supported:
      39           0 :       return clib_error_return (0, "not supported");
      40           0 :     case lldp_invalid_arg:
      41           0 :       return clib_error_return (0, "invalid argument");
      42           0 :     case lldp_internal_error:
      43           0 :       return clib_error_return (0, "internal error");
      44             :     }
      45           0 :   return 0;
      46             : }
      47             : 
      48             : lldp_cfg_err_t
      49           0 : lldp_cfg_intf_set (u32 hw_if_index, u8 ** port_desc, u8 ** mgmt_ip4,
      50             :                    u8 ** mgmt_ip6, u8 ** mgmt_oid, int enable)
      51             : {
      52           0 :   clib_error_t *error = 0;
      53           0 :   lldp_main_t *lm = &lldp_main;
      54           0 :   vnet_main_t *vnm = lm->vnet_main;
      55           0 :   ethernet_main_t *em = &ethernet_main;
      56             :   const vnet_hw_interface_t *hi;
      57             :   const ethernet_interface_t *eif;
      58             : 
      59           0 :   if (pool_is_free_index (vnm->interface_main.hw_interfaces, hw_if_index))
      60             :     {
      61           0 :       return lldp_invalid_arg;
      62             :     }
      63             : 
      64           0 :   hi = vnet_get_hw_interface (vnm, hw_if_index);
      65           0 :   eif = ethernet_get_interface (em, hw_if_index);
      66           0 :   if (!eif)
      67             :     {
      68           0 :       return lldp_not_supported;
      69             :     }
      70             : 
      71           0 :   if (enable)
      72             :     {
      73           0 :       lldp_intf_t *n = lldp_get_intf (lm, hw_if_index);
      74           0 :       if (n)
      75             :         {
      76             :           /* already enabled */
      77           0 :           return lldp_ok;
      78             :         }
      79           0 :       n = lldp_create_intf (lm, hw_if_index);
      80             : 
      81           0 :       if (port_desc && *port_desc)
      82             :         {
      83           0 :           n->port_desc = *port_desc;
      84           0 :           *port_desc = NULL;
      85             :         }
      86             : 
      87           0 :       if (mgmt_ip4 && *mgmt_ip4)
      88             :         {
      89           0 :           n->mgmt_ip4 = *mgmt_ip4;
      90           0 :           *mgmt_ip4 = NULL;
      91             :         }
      92             : 
      93           0 :       if (mgmt_ip6 && *mgmt_ip6)
      94             :         {
      95           0 :           n->mgmt_ip6 = *mgmt_ip6;
      96           0 :           *mgmt_ip6 = NULL;
      97             :         }
      98             : 
      99           0 :       if (mgmt_oid && *mgmt_oid)
     100             :         {
     101           0 :           n->mgmt_oid = *mgmt_oid;
     102           0 :           *mgmt_oid = NULL;
     103             :         }
     104             : 
     105             :       /* Add MAC address to an interface's filter */
     106           0 :       if (hi->caps & VNET_HW_IF_CAP_MAC_FILTER)
     107             :         {
     108             :           error =
     109           0 :             vnet_hw_interface_add_del_mac_address (lm->vnet_main,
     110             :                                                    hw_if_index,
     111             :                                                    lldp_mac_addr,
     112             :                                                    1 /* is_add */ );
     113           0 :           if (error)
     114             :             {
     115           0 :               clib_error_free (error);
     116           0 :               lldp_delete_intf (lm, n);
     117           0 :               return lldp_internal_error;
     118             :             }
     119             :         }
     120             : 
     121             :       const vnet_sw_interface_t *sw =
     122           0 :         vnet_get_sw_interface (lm->vnet_main, hi->sw_if_index);
     123           0 :       if (sw->flags & (VNET_SW_INTERFACE_FLAG_ADMIN_UP))
     124             :         {
     125           0 :           lldp_schedule_intf (lm, n);
     126             :         }
     127             :     }
     128             :   else
     129             :     {
     130           0 :       lldp_intf_t *n = lldp_get_intf (lm, hi->sw_if_index);
     131           0 :       lldp_delete_intf (lm, n);
     132             :       /* Remove MAC address from the interface's filter */
     133           0 :       if ((n) && (hi->caps & VNET_HW_IF_CAP_MAC_FILTER))
     134             :         {
     135             :           error =
     136           0 :             vnet_hw_interface_add_del_mac_address (lm->vnet_main,
     137             :                                                    hw_if_index,
     138             :                                                    lldp_mac_addr,
     139             :                                                    0 /* is_add */ );
     140           0 :           if (error)
     141             :             {
     142           0 :               clib_error_free (error);
     143             :             }
     144             :         }
     145             :     }
     146             : 
     147           0 :   return lldp_ok;
     148             : }
     149             : 
     150             : static clib_error_t *
     151           0 : lldp_intf_cmd (vlib_main_t * vm, unformat_input_t * input,
     152             :                vlib_cli_command_t * cmd)
     153             : {
     154           0 :   lldp_main_t *lm = &lldp_main;
     155           0 :   vnet_main_t *vnm = lm->vnet_main;
     156           0 :   u32 sw_if_index = (u32) ~ 0;
     157           0 :   int enable = 1;
     158           0 :   u8 *port_desc = NULL;
     159           0 :   u8 *mgmt_ip4 = NULL, *mgmt_ip6 = NULL, *mgmt_oid = NULL;
     160             :   ip4_address_t ip4_addr;
     161             :   ip6_address_t ip6_addr;
     162             : 
     163           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     164             :     {
     165           0 :       if (unformat (input, "sw_if_index %d", &sw_if_index))
     166             :         ;
     167           0 :       if (unformat
     168             :           (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
     169             :         ;
     170           0 :       else if (unformat (input, "disable"))
     171           0 :         enable = 0;
     172           0 :       else if (unformat (input, "port-desc %s", &port_desc))
     173             :         ;
     174             :       else
     175           0 :         if (unformat (input, "mgmt-ip4 %U", unformat_ip4_address, &ip4_addr))
     176             :         {
     177           0 :           vec_validate (mgmt_ip4, sizeof (ip4_address_t) - 1);
     178           0 :           clib_memcpy (mgmt_ip4, &ip4_addr, sizeof (ip4_addr));
     179             :         }
     180             :       else
     181           0 :         if (unformat (input, "mgmt-ip6 %U", unformat_ip6_address, &ip6_addr))
     182             :         {
     183           0 :           vec_validate (mgmt_ip6, sizeof (ip6_address_t) - 1);
     184           0 :           clib_memcpy (mgmt_ip6, &ip6_addr, sizeof (ip6_addr));
     185             :         }
     186           0 :       else if (unformat (input, "mgmt-oid %s", &mgmt_oid))
     187             :         ;
     188             :       else
     189           0 :         break;
     190             :     }
     191             : 
     192           0 :   if (sw_if_index == (u32) ~ 0)
     193           0 :     return clib_error_return (0, "Interface name is invalid!");
     194             : 
     195           0 :   return lldp_cfg_err_to_clib_err (lldp_cfg_intf_set (sw_if_index,
     196             :                                                       &port_desc, &mgmt_ip4,
     197             :                                                       &mgmt_ip6, &mgmt_oid,
     198             :                                                       enable));
     199             : }
     200             : 
     201             : lldp_cfg_err_t
     202           0 : lldp_cfg_set (u8 ** host, int hold_time, int tx_interval)
     203             : {
     204           0 :   lldp_main_t *lm = &lldp_main;
     205           0 :   int reschedule = 0;
     206             : 
     207           0 :   if (host && *host)
     208             :     {
     209           0 :       vec_free (lm->sys_name);
     210           0 :       lm->sys_name = *host;
     211           0 :       *host = NULL;
     212             :     }
     213             : 
     214           0 :   if (hold_time)
     215             :     {
     216           0 :       if (hold_time < LLDP_MIN_TX_HOLD || hold_time > LLDP_MAX_TX_HOLD)
     217             :         {
     218           0 :           return lldp_invalid_arg;
     219             :         }
     220           0 :       if (lm->msg_tx_hold != hold_time)
     221             :         {
     222           0 :           lm->msg_tx_hold = hold_time;
     223           0 :           reschedule = 1;
     224             :         }
     225             :     }
     226             : 
     227           0 :   if (tx_interval)
     228             :     {
     229           0 :       if (tx_interval < LLDP_MIN_TX_INTERVAL ||
     230             :           tx_interval > LLDP_MAX_TX_INTERVAL)
     231             :         {
     232           0 :           return lldp_invalid_arg;
     233             :         }
     234           0 :       if (lm->msg_tx_interval != tx_interval)
     235             :         {
     236           0 :           reschedule = 1;
     237           0 :           lm->msg_tx_interval = tx_interval;
     238             :         }
     239             :     }
     240             : 
     241           0 :   if (reschedule)
     242             :     {
     243           0 :       vlib_process_signal_event (lm->vlib_main, lm->lldp_process_node_index,
     244             :                                  LLDP_EVENT_RESCHEDULE, 0);
     245             :     }
     246             : 
     247           0 :   return lldp_ok;
     248             : }
     249             : 
     250             : static clib_error_t *
     251           0 : lldp_cfg_cmd (vlib_main_t * vm, unformat_input_t * input,
     252             :               vlib_cli_command_t * cmd)
     253             : {
     254           0 :   int hold_time = 0;
     255           0 :   int tx_interval = 0;
     256           0 :   u8 *host = NULL;
     257           0 :   clib_error_t *ret = NULL;
     258             : 
     259           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     260             :     {
     261           0 :       if (unformat (input, "system-name %s", &host))
     262             :         {
     263             :         }
     264           0 :       else if (unformat (input, "tx-hold %d", &hold_time))
     265             :         {
     266           0 :           if (hold_time < LLDP_MIN_TX_HOLD || hold_time > LLDP_MAX_TX_HOLD)
     267             :             {
     268             :               ret =
     269           0 :                 clib_error_return (0,
     270             :                                    "invalid tx-hold `%d' (out of range <%d,%d>)",
     271             :                                    hold_time, LLDP_MIN_TX_HOLD,
     272             :                                    LLDP_MAX_TX_HOLD);
     273           0 :               goto out;
     274             :             }
     275             :         }
     276           0 :       else if (unformat (input, "tx-interval %d", &tx_interval))
     277             :         {
     278           0 :           if (tx_interval < LLDP_MIN_TX_INTERVAL ||
     279           0 :               tx_interval > LLDP_MAX_TX_INTERVAL)
     280             :             {
     281             :               ret =
     282           0 :                 clib_error_return (0,
     283             :                                    "invalid tx-interval `%d' (out of range <%d,%d>)",
     284             :                                    tx_interval, LLDP_MIN_TX_INTERVAL,
     285             :                                    LLDP_MAX_TX_INTERVAL);
     286           0 :               goto out;
     287             :             }
     288             :         }
     289             :       else
     290             :         {
     291           0 :           break;
     292             :         }
     293             :     }
     294             :   ret =
     295           0 :     lldp_cfg_err_to_clib_err (lldp_cfg_set (&host, hold_time, tx_interval));
     296           0 : out:
     297           0 :   vec_free (host);
     298           0 :   return ret;
     299             : }
     300             : 
     301             : /* *INDENT-OFF* */
     302      121687 : VLIB_CLI_COMMAND(set_interface_lldp_cmd, static) = {
     303             :   .path = "set interface lldp",
     304             :   .short_help = "set interface lldp <interface> | sw_if_index <idx>"
     305             :                 " [port-desc <string>] [mgmt-ip4 <string>]"
     306             :                 " [mgmt-ip6 <string>] [mgmt-oid <string>] [disable]",
     307             :   .function = lldp_intf_cmd,
     308             : };
     309             : 
     310      121687 : VLIB_CLI_COMMAND(set_lldp_cmd, static) = {
     311             :   .path = "set lldp",
     312             :   .short_help = "set lldp [system-name <string>] [tx-hold <value>] "
     313             :                 "[tx-interval <value>]",
     314             :   .function = lldp_cfg_cmd,
     315             : };
     316             : /* *INDENT-ON* */
     317             : 
     318             : static const char *
     319           0 : lldp_chassis_id_subtype_str (lldp_chassis_id_subtype_t t)
     320             : {
     321           0 :   switch (t)
     322             :     {
     323             : #define F(num, val, str) \
     324             :   case num:              \
     325             :     return str;
     326           0 :       foreach_chassis_id_subtype (F)
     327             : #undef F
     328             :     }
     329           0 :   return "unknown chassis subtype";
     330             : }
     331             : 
     332             : static const char *
     333           0 : lldp_port_id_subtype_str (lldp_port_id_subtype_t t)
     334             : {
     335           0 :   switch (t)
     336             :     {
     337             : #define F(num, val, str) \
     338             :   case num:              \
     339             :     return str;
     340           0 :       foreach_port_id_subtype (F)
     341             : #undef F
     342             :     }
     343           0 :   return "unknown port subtype";
     344             : }
     345             : 
     346             : /*
     347             :  * format port id subtype&value
     348             :  *
     349             :  * @param va - 1st argument - unsigned - port id subtype
     350             :  * @param va - 2nd argument - u8* - port id
     351             :  * @param va - 3rd argument - unsigned - port id length
     352             :  * @param va - 4th argument - int - 1 for detailed output, 0 for simple
     353             :  */
     354             : u8 *
     355           0 : format_lldp_port_id (u8 * s, va_list * va)
     356             : {
     357           0 :   const lldp_port_id_subtype_t subtype = va_arg (*va, unsigned);
     358           0 :   const u8 *id = va_arg (*va, u8 *);
     359           0 :   const unsigned len = va_arg (*va, unsigned);
     360           0 :   const int detail = va_arg (*va, int);
     361           0 :   if (!id)
     362             :     {
     363           0 :       return s;
     364             :     }
     365           0 :   switch (subtype)
     366             :     {
     367           0 :     case LLDP_PORT_ID_SUBTYPE_NAME (intf_alias):
     368             :       /* fallthrough */
     369             :     case LLDP_PORT_ID_SUBTYPE_NAME (port_comp):
     370             :       /* fallthrough */
     371             :     case LLDP_PORT_ID_SUBTYPE_NAME (local):
     372             :       /* fallthrough */
     373             :     case LLDP_PORT_ID_SUBTYPE_NAME (intf_name):
     374           0 :       if (detail)
     375             :         {
     376           0 :           s = format (s, "%U(%s)", format_ascii_bytes, id, len,
     377             :                       lldp_port_id_subtype_str (subtype));
     378             :         }
     379             :       else
     380             :         {
     381           0 :           s = format (s, "%U", format_ascii_bytes, id, len);
     382             :         }
     383           0 :       break;
     384           0 :     case LLDP_PORT_ID_SUBTYPE_NAME (mac_addr):
     385           0 :       if (ETHER_ADDR_LEN == len)
     386             :         {
     387           0 :           if (detail)
     388             :             {
     389           0 :               s = format (s, "%U(%s)", format_mac_address, id,
     390             :                           lldp_port_id_subtype_str (subtype));
     391             :             }
     392             :           else
     393             :             {
     394           0 :               s = format (s, "%U", format_mac_address, id);
     395             :             }
     396           0 :           break;
     397             :         }
     398             :       /* fallthrough */
     399             :     case LLDP_PORT_ID_SUBTYPE_NAME (net_addr):
     400             :       /* TODO */
     401             :       /* fallthrough */
     402             :     default:
     403           0 :       if (detail)
     404             :         {
     405           0 :           s = format (s, "%U(%s)", format_hex_bytes, id, len,
     406             :                       lldp_port_id_subtype_str (subtype));
     407             :         }
     408             :       else
     409             :         {
     410           0 :           s = format (s, "%U", format_hex_bytes, id, len);
     411             :         }
     412           0 :       break;
     413             :     }
     414           0 :   return s;
     415             : }
     416             : 
     417             : /*
     418             :  * format chassis id subtype&value
     419             :  *
     420             :  * @param s format string
     421             :  * @param va - 1st argument - unsigned - chassis id subtype
     422             :  * @param va - 2nd argument - u8* - chassis id
     423             :  * @param va - 3rd argument - unsigned - chassis id length
     424             :  * @param va - 4th argument - int - 1 for detailed output, 0 for simple
     425             :  */
     426             : u8 *
     427           0 : format_lldp_chassis_id (u8 * s, va_list * va)
     428             : {
     429           0 :   const lldp_chassis_id_subtype_t subtype =
     430             :     va_arg (*va, lldp_chassis_id_subtype_t);
     431           0 :   const u8 *id = va_arg (*va, u8 *);
     432           0 :   const unsigned len = va_arg (*va, unsigned);
     433           0 :   const int detail = va_arg (*va, int);
     434           0 :   if (!id)
     435             :     {
     436           0 :       return s;
     437             :     }
     438           0 :   switch (subtype)
     439             :     {
     440           0 :     case LLDP_CHASS_ID_SUBTYPE_NAME (chassis_comp):
     441             :       /* fallthrough */
     442             :     case LLDP_CHASS_ID_SUBTYPE_NAME (intf_alias):
     443             :       /* fallthrough */
     444             :     case LLDP_CHASS_ID_SUBTYPE_NAME (port_comp):
     445             :       /* fallthrough */
     446             :     case LLDP_PORT_ID_SUBTYPE_NAME (local):
     447             :       /* fallthrough */
     448             :     case LLDP_CHASS_ID_SUBTYPE_NAME (intf_name):
     449           0 :       if (detail)
     450             :         {
     451           0 :           s = format (s, "%U(%s)", format_ascii_bytes, id, len,
     452             :                       lldp_chassis_id_subtype_str (subtype));
     453             :         }
     454             :       else
     455             :         {
     456           0 :           s = format (s, "%U", format_ascii_bytes, id, len);
     457             :         }
     458           0 :       break;
     459           0 :     case LLDP_CHASS_ID_SUBTYPE_NAME (mac_addr):
     460           0 :       if (ETHER_ADDR_LEN == len)
     461             :         {
     462           0 :           if (detail)
     463             :             {
     464           0 :               s = format (s, "%U(%s)", format_mac_address, id,
     465             :                           lldp_chassis_id_subtype_str (subtype));
     466             :             }
     467             :           else
     468             :             {
     469           0 :               s = format (s, "%U", format_mac_address, id);
     470             :             }
     471           0 :           break;
     472             :         }
     473             :       /* fallthrough */
     474             :     case LLDP_CHASS_ID_SUBTYPE_NAME (net_addr):
     475             :       /* TODO */
     476             :     default:
     477           0 :       if (detail)
     478             :         {
     479           0 :           s = format (s, "%U(%s)", format_hex_bytes, id, len,
     480             :                       lldp_chassis_id_subtype_str (subtype));
     481             :         }
     482             :       else
     483             :         {
     484           0 :           s = format (s, "%U", format_hex_bytes, id, len);
     485             :         }
     486           0 :       break;
     487             :     }
     488           0 :   return s;
     489             : }
     490             : 
     491             : /*
     492             :  * convert a tlv code to human-readable string
     493             :  */
     494             : static const char *
     495           0 : lldp_tlv_code_str (lldp_tlv_code_t t)
     496             : {
     497           0 :   switch (t)
     498             :     {
     499             : #define F(n, t, s) \
     500             :   case n:          \
     501             :     return s;
     502           0 :       foreach_lldp_tlv_type (F)
     503             : #undef F
     504             :     }
     505           0 :   return "unknown lldp tlv";
     506             : }
     507             : 
     508             : /*
     509             :  * format a single LLDP TLV
     510             :  *
     511             :  * @param s format string
     512             :  * @param va variable list - pointer to lldp_tlv_t is expected
     513             :  */
     514             : u8 *
     515           0 : format_lldp_tlv (u8 * s, va_list * va)
     516             : {
     517           0 :   const lldp_tlv_t *tlv = va_arg (*va, lldp_tlv_t *);
     518           0 :   if (!tlv)
     519             :     {
     520           0 :       return s;
     521             :     }
     522           0 :   u16 l = lldp_tlv_get_length (tlv);
     523           0 :   switch (lldp_tlv_get_code (tlv))
     524             :     {
     525           0 :     case LLDP_TLV_NAME (chassis_id):
     526           0 :       s = format (s, "%U", format_lldp_chassis_id,
     527           0 :                   ((lldp_chassis_id_tlv_t *) tlv)->subtype,
     528           0 :                   ((lldp_chassis_id_tlv_t *) tlv)->id,
     529             :                   l - STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype), 1);
     530           0 :       break;
     531           0 :     case LLDP_TLV_NAME (port_id):
     532           0 :       s = format (s, "%U", format_lldp_port_id,
     533           0 :                   ((lldp_port_id_tlv_t *) tlv)->subtype,
     534           0 :                   ((lldp_port_id_tlv_t *) tlv)->id,
     535             :                   l - STRUCT_SIZE_OF (lldp_port_id_tlv_t, subtype), 1);
     536           0 :       break;
     537           0 :     case LLDP_TLV_NAME (ttl):
     538           0 :       s = format (s, "%d", ntohs (((lldp_ttl_tlv_t *) tlv)->ttl));
     539           0 :       break;
     540           0 :     case LLDP_TLV_NAME (sys_name):
     541             :       /* fallthrough */
     542             :     case LLDP_TLV_NAME (sys_desc):
     543           0 :       s = format (s, "%U", format_ascii_bytes, tlv->v, l);
     544           0 :       break;
     545           0 :     default:
     546           0 :       s = format (s, "%U", format_hex_bytes, tlv->v, l);
     547             :     }
     548             : 
     549           0 :   return s;
     550             : }
     551             : 
     552             : static u8 *
     553           0 : format_time_ago (u8 * s, va_list * va)
     554             : {
     555           0 :   f64 ago = va_arg (*va, double);
     556           0 :   f64 now = va_arg (*va, double);
     557           0 :   if (ago < 0.01)
     558             :     {
     559           0 :       return format (s, "never");
     560             :     }
     561           0 :   return format (s, "%.1fs ago", now - ago);
     562             : }
     563             : 
     564             : static u8 *
     565           0 : format_lldp_intfs_detail (u8 * s, vlib_main_t * vm, const lldp_main_t * lm)
     566             : {
     567           0 :   vnet_main_t *vnm = &vnet_main;
     568             :   const lldp_intf_t *n;
     569             :   const vnet_hw_interface_t *hw;
     570             :   const vnet_sw_interface_t *sw;
     571           0 :   s = format (s, "LLDP configuration:\n");
     572           0 :   if (lm->sys_name)
     573             :     {
     574           0 :       s = format (s, "Configured system name: %U\n", format_ascii_bytes,
     575           0 :                   lm->sys_name, vec_len (lm->sys_name));
     576             :     }
     577             : 
     578           0 :   s = format (s, "Configured tx-hold: %d\n", (int) lm->msg_tx_hold);
     579           0 :   s = format (s, "Configured tx-interval: %d\n", (int) lm->msg_tx_interval);
     580           0 :   s = format (s, "\nLLDP-enabled interface table:\n");
     581           0 :   f64 now = vlib_time_now (vm);
     582             : 
     583             :   /* *INDENT-OFF* */
     584           0 :   pool_foreach (
     585             :       n, lm->intfs)  {
     586           0 :         hw = vnet_get_hw_interface(vnm, n->hw_if_index);
     587           0 :         sw = vnet_get_sw_interface(lm->vnet_main, hw->sw_if_index);
     588             : 
     589           0 :         s = format(s, "\nLocal Interface name: %v\n"
     590             :                       "Local Port Description: %s\n",
     591             :                        hw->name, n->port_desc);
     592           0 :         if (n->mgmt_ip4)
     593             :           {
     594           0 :             s = format (s, "Local Management address: %U\n",
     595           0 :                         format_ip4_address, n->mgmt_ip4, vec_len (n->mgmt_ip4));
     596             :           }
     597             : 
     598           0 :         if (n->mgmt_ip6)
     599             :           {
     600           0 :             s = format (s, "Local Management address IPV6: %U\n",
     601           0 :                         format_ip6_address, n->mgmt_ip6, vec_len (n->mgmt_ip6));
     602             :           }
     603             : 
     604           0 :         if (n->mgmt_oid)
     605             :           {
     606           0 :             s = format (s, "Local Management address OID: %U\n",
     607           0 :                         format_ascii_bytes, n->mgmt_oid, vec_len (n->mgmt_oid));
     608             :           }
     609             : 
     610             :         /* Interface shutdown */
     611           0 :         if (!(sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
     612             :           {
     613           0 :             s = format(s, "Interface/peer state: interface down\n"
     614             :                        "Last packet sent: %U\n",
     615             :                        format_time_ago, n->last_sent, now);
     616             :           }
     617           0 :         else if (now < n->last_heard + n->ttl)
     618             :           {
     619           0 :             s = format(s,
     620             :                        "Interface/peer state: active\n"
     621             :                        "Peer chassis ID: %U\nRemote port ID: %U\n"
     622             :                        "Last packet sent: %U\nLast packet received: %U\n",
     623           0 :                        format_lldp_chassis_id, n->chassis_id_subtype,
     624           0 :                        n->chassis_id, vec_len(n->chassis_id), 1,
     625           0 :                        format_lldp_port_id, n->port_id_subtype, n->port_id,
     626           0 :                        vec_len(n->port_id), 1, format_time_ago, n->last_sent,
     627             :                        now, format_time_ago, n->last_heard, now);
     628             :           }
     629             :         else
     630             :           {
     631           0 :             s = format(s,
     632             :                        "Interface/peer state: inactive(timeout)\n"
     633             :                        "Last known peer chassis ID: %U\n"
     634             :                        "Last known peer port ID: %U\nLast packet sent: %U\n"
     635             :                        "Last packet received: %U\n",
     636           0 :                        format_lldp_chassis_id, n->chassis_id_subtype,
     637           0 :                        n->chassis_id, vec_len(n->chassis_id), 1,
     638           0 :                        format_lldp_port_id, n->port_id_subtype, n->port_id,
     639           0 :                        vec_len(n->port_id), 1, format_time_ago, n->last_sent,
     640             :                        now, format_time_ago, n->last_heard, now);
     641             :           }
     642             :       }
     643             :   /* *INDENT-ON* */
     644           0 :   return s;
     645             : }
     646             : 
     647             : static u8 *
     648           0 : format_lldp_intfs (u8 * s, va_list * va)
     649             : {
     650           0 :   vlib_main_t *vm = va_arg (*va, vlib_main_t *);
     651           0 :   const lldp_main_t *lm = va_arg (*va, lldp_main_t *);
     652           0 :   const int detail = va_arg (*va, int);
     653           0 :   vnet_main_t *vnm = &vnet_main;
     654             :   const lldp_intf_t *n;
     655             : 
     656           0 :   if (detail)
     657             :     {
     658           0 :       return format_lldp_intfs_detail (s, vm, lm);
     659             :     }
     660             : 
     661           0 :   f64 now = vlib_time_now (vm);
     662           0 :   s = format (s, "%-25s %-25s %-25s %=15s %=15s %=10s\n", "Local interface",
     663             :               "Peer chassis ID", "Remote port ID", "Last heard", "Last sent",
     664             :               "Status");
     665             : 
     666             :   /* *INDENT-OFF* */
     667           0 :   pool_foreach (
     668             :       n, lm->intfs)  {
     669             :         const vnet_hw_interface_t *hw =
     670           0 :             vnet_get_hw_interface(vnm, n->hw_if_index);
     671             :         const vnet_sw_interface_t *sw =
     672           0 :             vnet_get_sw_interface(lm->vnet_main, hw->sw_if_index);
     673             :         /* Interface shutdown */
     674           0 :         if (!(sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
     675           0 :           continue;
     676           0 :         if (now < n->last_heard + n->ttl)
     677             :           {
     678           0 :             s = format(s, "%-25v %-25U %-25U %=15U %=15U %=10s\n", hw->name,
     679           0 :                        format_lldp_chassis_id, n->chassis_id_subtype,
     680           0 :                        n->chassis_id, vec_len(n->chassis_id), 0,
     681           0 :                        format_lldp_port_id, n->port_id_subtype, n->port_id,
     682           0 :                        vec_len(n->port_id), 0, format_time_ago, n->last_heard,
     683             :                        now, format_time_ago, n->last_sent, now, "active");
     684             :           }
     685             :         else
     686             :           {
     687           0 :             s = format(s, "%-25v %-25s %-25s %=15U %=15U %=10s\n", hw->name,
     688             :                        "", "", format_time_ago, n->last_heard, now,
     689             :                        format_time_ago, n->last_sent, now, "inactive");
     690             :           }
     691             :       }
     692             :   /* *INDENT-ON* */
     693           0 :   return s;
     694             : }
     695             : 
     696             : static clib_error_t *
     697           0 : show_lldp (vlib_main_t * vm, unformat_input_t * input,
     698             :            CLIB_UNUSED (vlib_cli_command_t * lmd))
     699             : {
     700           0 :   lldp_main_t *lm = &lldp_main;
     701             : 
     702           0 :   if (unformat (input, "detail"))
     703             :     {
     704           0 :       vlib_cli_output (vm, "%U\n", format_lldp_intfs, vm, lm, 1);
     705             :     }
     706             :   else
     707             :     {
     708           0 :       vlib_cli_output (vm, "%U\n", format_lldp_intfs, vm, lm, 0);
     709             :     }
     710           0 :   return 0;
     711             : }
     712             : 
     713             : /* *INDENT-OFF* */
     714      121687 : VLIB_CLI_COMMAND(show_lldp_command, static) = {
     715             :   .path = "show lldp",
     716             :   .short_help = "show lldp [detail]",
     717             :   .function = show_lldp,
     718             : };
     719             : /* *INDENT-ON* */
     720             : 
     721             : /*
     722             :  * packet trace format function, very similar to
     723             :  * lldp_packet_scan except that we call the per TLV format
     724             :  * functions instead of the per TLV processing functions
     725             :  */
     726             : u8 *
     727           0 : lldp_input_format_trace (u8 * s, va_list * args)
     728             : {
     729           0 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
     730           0 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
     731           0 :   const lldp_input_trace_t *t = va_arg (*args, lldp_input_trace_t *);
     732             :   const u8 *cur;
     733             :   const lldp_tlv_t *tlv;
     734           0 :   cur = t->data;
     735           0 :   while (((cur + lldp_tlv_get_length ((lldp_tlv_t *) cur)) <
     736           0 :           t->data + t->len))
     737             :     {
     738           0 :       tlv = (lldp_tlv_t *) cur;
     739           0 :       if (cur == t->data)
     740             :         {
     741           0 :           s = format (s, "TLV #%d(%s): %U\n", lldp_tlv_get_code (tlv),
     742             :                       lldp_tlv_code_str (lldp_tlv_get_code (tlv)),
     743             :                       format_lldp_tlv, tlv);
     744             :         }
     745             :       else
     746             :         {
     747           0 :           s = format (s, "  TLV #%d(%s): %U\n", lldp_tlv_get_code (tlv),
     748             :                       lldp_tlv_code_str (lldp_tlv_get_code (tlv)),
     749             :                       format_lldp_tlv, tlv);
     750             :         }
     751           0 :       cur += STRUCT_SIZE_OF (lldp_tlv_t, head) + lldp_tlv_get_length (tlv);
     752             :     }
     753             : 
     754           0 :   return s;
     755             : }
     756             : 
     757             : /*
     758             :  * fd.io coding-style-patch-verification: ON
     759             :  *
     760             :  * Local Variables:
     761             :  * eval: (c-set-style "gnu")
     762             :  * End:
     763             :  */

Generated by: LCOV version 1.14