LCOV - code coverage report
Current view: top level - plugins/nsh - nsh_cli.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 4 321 1.2 %
Date: 2023-10-26 01:39:38 Functions: 8 20 40.0 %

          Line data    Source code
       1             : /*
       2             :  * nsh_cli.c - nsh cli functions
       3             :  *
       4             :  * Copyright (c) 2019 Cisco and/or its affiliates.
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #include <vnet/vnet.h>
      19             : #include <vnet/plugin/plugin.h>
      20             : #include <nsh/nsh.h>
      21             : #include <vnet/adj/adj.h>
      22             : 
      23             : /* format from network order */
      24             : u8 *
      25           0 : format_nsh_pop_header (u8 * s, va_list * args)
      26             : {
      27           0 :   return format_nsh_header (s, args);
      28             : }
      29             : 
      30             : u8 *
      31           0 : format_nsh_pop_node_map_trace (u8 * s, va_list * args)
      32             : {
      33           0 :   return format_nsh_node_map_trace (s, args);
      34             : }
      35             : 
      36             : static uword
      37           0 : unformat_nsh_action (unformat_input_t * input, va_list * args)
      38             : {
      39           0 :   u32 *result = va_arg (*args, u32 *);
      40             :   u32 tmp;
      41             : 
      42           0 :   if (unformat (input, "swap"))
      43           0 :     *result = NSH_ACTION_SWAP;
      44           0 :   else if (unformat (input, "push"))
      45           0 :     *result = NSH_ACTION_PUSH;
      46           0 :   else if (unformat (input, "pop"))
      47           0 :     *result = NSH_ACTION_POP;
      48           0 :   else if (unformat (input, "%d", &tmp))
      49           0 :     *result = tmp;
      50             :   else
      51           0 :     return 0;
      52             : 
      53           0 :   return 1;
      54             : }
      55             : 
      56             : static u8 *
      57           0 : format_nsh_action (u8 * s, va_list * args)
      58             : {
      59           0 :   u32 nsh_action = va_arg (*args, u32);
      60             : 
      61           0 :   switch (nsh_action)
      62             :     {
      63           0 :     case NSH_ACTION_SWAP:
      64           0 :       return format (s, "swap");
      65           0 :     case NSH_ACTION_PUSH:
      66           0 :       return format (s, "push");
      67           0 :     case NSH_ACTION_POP:
      68           0 :       return format (s, "pop");
      69           0 :     default:
      70           0 :       return format (s, "unknown %d", nsh_action);
      71             :     }
      72             :   return s;
      73             : }
      74             : 
      75             : u8 *
      76           0 : format_nsh_map (u8 * s, va_list * args)
      77             : {
      78           0 :   nsh_map_t *map = va_arg (*args, nsh_map_t *);
      79             : 
      80           0 :   s = format (s, "nsh entry nsp: %d nsi: %d ",
      81           0 :               (map->nsp_nsi >> NSH_NSP_SHIFT) & NSH_NSP_MASK,
      82           0 :               map->nsp_nsi & NSH_NSI_MASK);
      83           0 :   s = format (s, "maps to nsp: %d nsi: %d ",
      84           0 :               (map->mapped_nsp_nsi >> NSH_NSP_SHIFT) & NSH_NSP_MASK,
      85           0 :               map->mapped_nsp_nsi & NSH_NSI_MASK);
      86             : 
      87           0 :   s = format (s, " nsh_action %U\n", format_nsh_action, map->nsh_action);
      88             : 
      89           0 :   switch (map->next_node)
      90             :     {
      91           0 :     case NSH_NODE_NEXT_ENCAP_GRE4:
      92             :       {
      93           0 :         s = format (s, "encapped by GRE4 intf: %d", map->sw_if_index);
      94           0 :         break;
      95             :       }
      96           0 :     case NSH_NODE_NEXT_ENCAP_GRE6:
      97             :       {
      98           0 :         s = format (s, "encapped by GRE6 intf: %d", map->sw_if_index);
      99           0 :         break;
     100             :       }
     101           0 :     case NSH_NODE_NEXT_ENCAP_VXLANGPE:
     102             :       {
     103           0 :         s = format (s, "encapped by VXLAN GPE intf: %d", map->sw_if_index);
     104           0 :         break;
     105             :       }
     106           0 :     case NSH_NODE_NEXT_ENCAP_VXLAN4:
     107             :       {
     108           0 :         s = format (s, "encapped by VXLAN4 intf: %d", map->sw_if_index);
     109           0 :         break;
     110             :       }
     111           0 :     case NSH_NODE_NEXT_ENCAP_VXLAN6:
     112             :       {
     113           0 :         s = format (s, "encapped by VXLAN6 intf: %d", map->sw_if_index);
     114           0 :         break;
     115             :       }
     116           0 :     case NSH_NODE_NEXT_DECAP_ETH_INPUT:
     117             :       {
     118           0 :         s = format (s, "encap-none");
     119           0 :         break;
     120             :       }
     121           0 :     case NSH_NODE_NEXT_ENCAP_LISP_GPE:
     122             :       {
     123           0 :         s = format (s, "encapped by LISP GPE intf: %d", map->sw_if_index);
     124           0 :         break;
     125             :       }
     126           0 :     case NSH_NODE_NEXT_ENCAP_ETHERNET:
     127             :       {
     128           0 :         s = format (s, "encapped by Ethernet intf: %d", map->sw_if_index);
     129           0 :         break;
     130             :       }
     131           0 :     default:
     132           0 :       s = format (s, "only GRE and VXLANGPE support in this rev");
     133             :     }
     134             : 
     135           0 :   return s;
     136             : }
     137             : 
     138             : static adj_index_t
     139           0 : nsh_get_adj_by_sw_if_index (u32 sw_if_index)
     140             : {
     141           0 :   adj_index_t ai = ~0;
     142             : 
     143             :   /* *INDENT-OFF* */
     144           0 :   pool_foreach_index (ai, adj_pool)
     145             :    {
     146           0 :       if (sw_if_index == adj_get_sw_if_index(ai))
     147             :       {
     148           0 :         return ai;
     149             :       }
     150             :   }
     151             :   /* *INDENT-ON* */
     152             : 
     153           0 :   return ~0;
     154             : }
     155             : 
     156             : 
     157             : /**
     158             :  * CLI command for NSH map
     159             :  */
     160             : static clib_error_t *
     161           0 : nsh_add_del_map_command_fn (vlib_main_t * vm,
     162             :                             unformat_input_t * input,
     163             :                             vlib_cli_command_t * cmd)
     164             : {
     165           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     166           0 :   u8 is_add = 1;
     167             :   u32 nsp, nsi, mapped_nsp, mapped_nsi, nsh_action;
     168           0 :   int nsp_set = 0, nsi_set = 0, mapped_nsp_set = 0, mapped_nsi_set = 0;
     169           0 :   int nsh_action_set = 0;
     170           0 :   u32 next_node = ~0;
     171           0 :   u32 adj_index = ~0;
     172           0 :   u32 sw_if_index = ~0;         // temporary requirement to get this moved over to NSHSFC
     173           0 :   u32 rx_sw_if_index = ~0;      // temporary requirement to get this moved over to NSHSFC
     174           0 :   nsh_add_del_map_args_t _a, *a = &_a;
     175             :   u32 map_index;
     176             :   int rv;
     177             : 
     178             :   /* Get a line of input. */
     179           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     180           0 :     return 0;
     181             : 
     182           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     183             :     {
     184           0 :       if (unformat (line_input, "del"))
     185           0 :         is_add = 0;
     186           0 :       else if (unformat (line_input, "nsp %d", &nsp))
     187           0 :         nsp_set = 1;
     188           0 :       else if (unformat (line_input, "nsi %d", &nsi))
     189           0 :         nsi_set = 1;
     190           0 :       else if (unformat (line_input, "mapped-nsp %d", &mapped_nsp))
     191           0 :         mapped_nsp_set = 1;
     192           0 :       else if (unformat (line_input, "mapped-nsi %d", &mapped_nsi))
     193           0 :         mapped_nsi_set = 1;
     194           0 :       else if (unformat (line_input, "nsh_action %U", unformat_nsh_action,
     195             :                          &nsh_action))
     196           0 :         nsh_action_set = 1;
     197           0 :       else if (unformat (line_input, "encap-gre4-intf %d", &sw_if_index))
     198           0 :         next_node = NSH_NODE_NEXT_ENCAP_GRE4;
     199           0 :       else if (unformat (line_input, "encap-gre6-intf %d", &sw_if_index))
     200           0 :         next_node = NSH_NODE_NEXT_ENCAP_GRE6;
     201           0 :       else if (unformat (line_input, "encap-vxlan-gpe-intf %d", &sw_if_index))
     202           0 :         next_node = NSH_NODE_NEXT_ENCAP_VXLANGPE;
     203           0 :       else if (unformat (line_input, "encap-lisp-gpe-intf %d", &sw_if_index))
     204           0 :         next_node = NSH_NODE_NEXT_ENCAP_LISP_GPE;
     205           0 :       else if (unformat (line_input, "encap-vxlan4-intf %d", &sw_if_index))
     206           0 :         next_node = NSH_NODE_NEXT_ENCAP_VXLAN4;
     207           0 :       else if (unformat (line_input, "encap-vxlan6-intf %d", &sw_if_index))
     208           0 :         next_node = NSH_NODE_NEXT_ENCAP_VXLAN6;
     209           0 :       else if (unformat (line_input, "encap-eth-intf %d", &sw_if_index))
     210             :         {
     211           0 :           next_node = NSH_NODE_NEXT_ENCAP_ETHERNET;
     212           0 :           adj_index = nsh_get_adj_by_sw_if_index (sw_if_index);
     213             :         }
     214             :       else
     215           0 :         if (unformat
     216             :             (line_input, "encap-none %d %d", &sw_if_index, &rx_sw_if_index))
     217           0 :         next_node = NSH_NODE_NEXT_DECAP_ETH_INPUT;
     218             :       else
     219           0 :         return clib_error_return (0, "parse error: '%U'",
     220             :                                   format_unformat_error, line_input);
     221             :     }
     222             : 
     223           0 :   unformat_free (line_input);
     224             : 
     225           0 :   if (nsp_set == 0 || nsi_set == 0)
     226           0 :     return clib_error_return (0, "nsp nsi pair required. Key: for NSH entry");
     227             : 
     228           0 :   if (mapped_nsp_set == 0 || mapped_nsi_set == 0)
     229           0 :     return clib_error_return (0,
     230             :                               "mapped-nsp mapped-nsi pair required. Key: for NSH entry");
     231             : 
     232           0 :   if (nsh_action_set == 0)
     233           0 :     return clib_error_return (0, "nsh_action required: swap|push|pop.");
     234             : 
     235           0 :   if (next_node == ~0)
     236           0 :     return clib_error_return (0,
     237             :                               "must specific action: [encap-gre-intf <nn> | encap-vxlan-gpe-intf <nn> | encap-lisp-gpe-intf <nn> | encap-none <tx_sw_if_index> <rx_sw_if_index>]");
     238             : 
     239           0 :   clib_memset (a, 0, sizeof (*a));
     240             : 
     241             :   /* set args structure */
     242           0 :   a->is_add = is_add;
     243           0 :   a->map.nsp_nsi = (nsp << NSH_NSP_SHIFT) | nsi;
     244           0 :   a->map.mapped_nsp_nsi = (mapped_nsp << NSH_NSP_SHIFT) | mapped_nsi;
     245           0 :   a->map.nsh_action = nsh_action;
     246           0 :   a->map.sw_if_index = sw_if_index;
     247           0 :   a->map.rx_sw_if_index = rx_sw_if_index;
     248           0 :   a->map.next_node = next_node;
     249           0 :   a->map.adj_index = adj_index;
     250             : 
     251           0 :   rv = nsh_add_del_map (a, &map_index);
     252             : 
     253           0 :   switch (rv)
     254             :     {
     255           0 :     case 0:
     256           0 :       break;
     257           0 :     case -1:                    //TODO API_ERROR_INVALID_VALUE:
     258           0 :       return clib_error_return (0,
     259             :                                 "mapping already exists. Remove it first.");
     260             : 
     261           0 :     case -2:                    // TODO API_ERROR_NO_SUCH_ENTRY:
     262           0 :       return clib_error_return (0, "mapping does not exist.");
     263             : 
     264           0 :     default:
     265           0 :       return clib_error_return (0, "nsh_add_del_map returned %d", rv);
     266             :     }
     267             : 
     268           0 :   if ((a->map.next_node == NSH_NODE_NEXT_ENCAP_VXLAN4)
     269           0 :       | (a->map.next_node == NSH_NODE_NEXT_ENCAP_VXLAN6))
     270             :     {
     271           0 :       rv = nsh_add_del_proxy_session (a);
     272             : 
     273           0 :       switch (rv)
     274             :         {
     275           0 :         case 0:
     276           0 :           break;
     277           0 :         case -1:                //TODO API_ERROR_INVALID_VALUE:
     278           0 :           return clib_error_return (0,
     279             :                                     "nsh-proxy-session already exists. Remove it first.");
     280             : 
     281           0 :         case -2:                // TODO API_ERROR_NO_SUCH_ENTRY:
     282           0 :           return clib_error_return (0, "nsh-proxy-session does not exist.");
     283             : 
     284           0 :         default:
     285           0 :           return clib_error_return
     286             :             (0, "nsh_add_del_proxy_session() returned %d", rv);
     287             :         }
     288           0 :     }
     289             : 
     290           0 :   return 0;
     291             : }
     292             : 
     293             : /* *INDENT-OFF* */
     294       58901 : VLIB_CLI_COMMAND (create_nsh_map_command, static) = {
     295             :   .path = "create nsh map",
     296             :   .short_help =
     297             :     "create nsh map nsp <nn> nsi <nn> [del] mapped-nsp <nn> mapped-nsi <nn> nsh_action [swap|push|pop] "
     298             :     "[encap-gre4-intf <nn> | encap-gre4-intf <nn> | encap-vxlan-gpe-intf <nn> | encap-lisp-gpe-intf <nn> "
     299             :     " encap-vxlan4-intf <nn> | encap-vxlan6-intf <nn>| encap-eth-intf <nn> | encap-none]\n",
     300             :   .function = nsh_add_del_map_command_fn,
     301             : };
     302             : /* *INDENT-ON* */
     303             : 
     304             : /**
     305             :  * CLI command for showing the mapping between NSH entries
     306             :  */
     307             : static clib_error_t *
     308           0 : show_nsh_map_command_fn (vlib_main_t * vm,
     309             :                          unformat_input_t * input, vlib_cli_command_t * cmd)
     310             : {
     311           0 :   nsh_main_t *nm = &nsh_main;
     312             :   nsh_map_t *map;
     313             : 
     314           0 :   if (pool_elts (nm->nsh_mappings) == 0)
     315           0 :     vlib_cli_output (vm, "No nsh maps configured.");
     316             : 
     317           0 :   pool_foreach (map, nm->nsh_mappings)
     318             :   {
     319           0 :     vlib_cli_output (vm, "%U", format_nsh_map, map);
     320             :   }
     321             : 
     322           0 :   return 0;
     323             : }
     324             : 
     325             : /* *INDENT-OFF* */
     326       58901 : VLIB_CLI_COMMAND (show_nsh_map_command, static) = {
     327             :   .path = "show nsh map",
     328             :   .function = show_nsh_map_command_fn,
     329             : };
     330             : /* *INDENT-ON* */
     331             : 
     332             : /**
     333             :  * CLI command for adding NSH entry
     334             :  */
     335             : static clib_error_t *
     336           0 : nsh_add_del_entry_command_fn (vlib_main_t * vm,
     337             :                               unformat_input_t * input,
     338             :                               vlib_cli_command_t * cmd)
     339             : {
     340           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     341           0 :   u8 is_add = 1;
     342           0 :   u8 ver_o_c = 0;
     343           0 :   u8 ttl = 63;
     344           0 :   u8 length = 0;
     345           0 :   u8 md_type = 0;
     346           0 :   u8 next_protocol = 1;         /* default: ip4 */
     347             :   u32 nsp;
     348           0 :   u8 nsp_set = 0;
     349             :   u32 nsi;
     350           0 :   u8 nsi_set = 0;
     351             :   u32 nsp_nsi;
     352           0 :   u32 c1 = 0;
     353           0 :   u32 c2 = 0;
     354           0 :   u32 c3 = 0;
     355           0 :   u32 c4 = 0;
     356           0 :   u8 *data = 0;
     357             :   nsh_tlv_header_t tlv_header;
     358           0 :   u8 cur_len = 0, tlvs_len = 0;
     359             :   u8 *current;
     360           0 :   nsh_main_t *nm = &nsh_main;
     361           0 :   nsh_option_map_t _nsh_option, *nsh_option = &_nsh_option;
     362           0 :   u8 option_size = 0;
     363             :   u32 tmp;
     364             :   int rv;
     365             :   u32 entry_index;
     366           0 :   nsh_add_del_entry_args_t _a, *a = &_a;
     367           0 :   u8 has_ioam_trace_option = 0;
     368             : 
     369             :   /* Get a line of input. */
     370           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     371           0 :     return 0;
     372             : 
     373           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     374             :     {
     375           0 :       if (unformat (line_input, "del"))
     376           0 :         is_add = 0;
     377           0 :       else if (unformat (line_input, "version %d", &tmp))
     378           0 :         ver_o_c |= (tmp & 3) << 6;
     379           0 :       else if (unformat (line_input, "o-bit %d", &tmp))
     380           0 :         ver_o_c |= (tmp & 1) << 5;
     381           0 :       else if (unformat (line_input, "c-bit %d", &tmp))
     382           0 :         ver_o_c |= (tmp & 1) << 4;
     383           0 :       else if (unformat (line_input, "ttl %d", &ttl))
     384           0 :         ver_o_c |= (ttl & NSH_LEN_MASK) >> 2;
     385           0 :       else if (unformat (line_input, "md-type %d", &tmp))
     386           0 :         md_type = tmp;
     387           0 :       else if (unformat (line_input, "next-ip4"))
     388           0 :         next_protocol = 1;
     389           0 :       else if (unformat (line_input, "next-ip6"))
     390           0 :         next_protocol = 2;
     391           0 :       else if (unformat (line_input, "next-ethernet"))
     392           0 :         next_protocol = 3;
     393           0 :       else if (unformat (line_input, "c1 %d", &c1))
     394             :         ;
     395           0 :       else if (unformat (line_input, "c2 %d", &c2))
     396             :         ;
     397           0 :       else if (unformat (line_input, "c3 %d", &c3))
     398             :         ;
     399           0 :       else if (unformat (line_input, "c4 %d", &c4))
     400             :         ;
     401           0 :       else if (unformat (line_input, "nsp %d", &nsp))
     402           0 :         nsp_set = 1;
     403           0 :       else if (unformat (line_input, "nsi %d", &nsi))
     404           0 :         nsi_set = 1;
     405           0 :       else if (unformat (line_input, "tlv-ioam-trace"))
     406           0 :         has_ioam_trace_option = 1;
     407             :       else
     408           0 :         return clib_error_return (0, "parse error: '%U'",
     409             :                                   format_unformat_error, line_input);
     410             :     }
     411             : 
     412           0 :   unformat_free (line_input);
     413             : 
     414           0 :   if (nsp_set == 0)
     415           0 :     return clib_error_return (0, "nsp not specified");
     416             : 
     417           0 :   if (nsi_set == 0)
     418           0 :     return clib_error_return (0, "nsi not specified");
     419             : 
     420           0 :   if (md_type == 1 && has_ioam_trace_option == 1)
     421           0 :     return clib_error_return (0, "Invalid MD Type");
     422             : 
     423           0 :   nsp_nsi = (nsp << 8) | nsi;
     424             : 
     425           0 :   clib_memset (a, 0, sizeof (*a));
     426           0 :   a->is_add = is_add;
     427             : 
     428           0 :   if (md_type == 1)
     429             :     {
     430           0 :       a->nsh_entry.md.md1_data.c1 = c1;
     431           0 :       a->nsh_entry.md.md1_data.c2 = c2;
     432           0 :       a->nsh_entry.md.md1_data.c3 = c3;
     433           0 :       a->nsh_entry.md.md1_data.c4 = c4;
     434           0 :       length = (sizeof (nsh_base_header_t) + sizeof (nsh_md1_data_t)) >> 2;
     435             :     }
     436           0 :   else if (md_type == 2)
     437             :     {
     438           0 :       length = sizeof (nsh_base_header_t) >> 2;
     439             : 
     440           0 :       vec_free (a->nsh_entry.tlvs_data);
     441           0 :       tlvs_len = (MAX_METADATA_LEN << 2);
     442           0 :       vec_validate_aligned (data, tlvs_len - 1, CLIB_CACHE_LINE_BYTES);
     443           0 :       a->nsh_entry.tlvs_data = data;
     444           0 :       current = data;
     445             : 
     446           0 :       if (has_ioam_trace_option)
     447             :         {
     448           0 :           tlv_header.class = clib_host_to_net_u16 (NSH_MD2_IOAM_CLASS);
     449           0 :           tlv_header.type = NSH_MD2_IOAM_OPTION_TYPE_TRACE;
     450             :           /* Uses network order's class and type to lookup */
     451             :           nsh_option =
     452           0 :             nsh_md2_lookup_option (tlv_header.class, tlv_header.type);
     453           0 :           if (nsh_option == NULL)
     454           0 :             return clib_error_return (0, "iOAM Trace not registered");
     455             : 
     456           0 :           if (nm->add_options[nsh_option->option_id] != NULL)
     457             :             {
     458           0 :               if (0 != nm->add_options[nsh_option->option_id] ((u8 *) current,
     459             :                                                                &option_size))
     460             :                 {
     461           0 :                   return clib_error_return (0, "Invalid MD Type");
     462             :                 }
     463             :             }
     464             : 
     465           0 :           nm->options_size[nsh_option->option_id] = option_size;
     466             :           /* round to 4-byte */
     467           0 :           option_size = (((option_size + 3) >> 2) << 2);
     468             : 
     469           0 :           cur_len += option_size;
     470           0 :           current = data + option_size;
     471             :         }
     472             : 
     473             :       /* Add more options' parsing */
     474             : 
     475           0 :       a->nsh_entry.tlvs_len = cur_len;
     476           0 :       length += (cur_len >> 2);
     477             :     }
     478           0 :   length = (length & NSH_LEN_MASK) | ((ttl & 0x3) << 6);
     479             : 
     480             : #define _(x) a->nsh_entry.nsh_base.x = x;
     481           0 :   foreach_copy_nsh_base_hdr_field;
     482             : #undef _
     483             : 
     484           0 :   rv = nsh_add_del_entry (a, &entry_index);
     485             : 
     486           0 :   switch (rv)
     487             :     {
     488           0 :     case 0:
     489           0 :       break;
     490           0 :     default:
     491           0 :       return clib_error_return (0, "nsh_add_del_entry returned %d", rv);
     492             :     }
     493             : 
     494           0 :   return 0;
     495             : }
     496             : 
     497             : /* *INDENT-OFF* */
     498       58901 : VLIB_CLI_COMMAND (create_nsh_entry_command, static) = {
     499             :   .path = "create nsh entry",
     500             :   .short_help =
     501             :     "create nsh entry {nsp <nn> nsi <nn>} [ttl <nn>] [md-type <nn>]"
     502             :     "  [c1 <nn> c2 <nn> c3 <nn> c4 <nn>] [tlv-ioam-trace] [del]\n",
     503             :   .function = nsh_add_del_entry_command_fn,
     504             : };
     505             : /* *INDENT-ON* */
     506             : 
     507             : /* format from network order */
     508             : u8 *
     509           0 : format_nsh_header (u8 * s, va_list * args)
     510             : {
     511           0 :   nsh_main_t *nm = &nsh_main;
     512             :   nsh_md2_data_t *opt0;
     513             :   nsh_md2_data_t *limit0;
     514             :   nsh_option_map_t *nsh_option;
     515           0 :   u8 option_len = 0;
     516             : 
     517           0 :   u8 *header = va_arg (*args, u8 *);
     518           0 :   nsh_base_header_t *nsh_base = (nsh_base_header_t *) header;
     519           0 :   nsh_md1_data_t *nsh_md1 = (nsh_md1_data_t *) (nsh_base + 1);
     520           0 :   nsh_md2_data_t *nsh_md2 = (nsh_md2_data_t *) (nsh_base + 1);
     521           0 :   opt0 = (nsh_md2_data_t *) nsh_md2;
     522           0 :   limit0 = (nsh_md2_data_t *) ((u8 *) nsh_md2 +
     523           0 :                                ((nsh_base->length & NSH_LEN_MASK) * 4
     524             :                                 - sizeof (nsh_base_header_t)));
     525             : 
     526           0 :   s = format (s, "nsh ver %d ", (nsh_base->ver_o_c >> 6));
     527           0 :   if (nsh_base->ver_o_c & NSH_O_BIT)
     528           0 :     s = format (s, "O-set ");
     529             : 
     530           0 :   if (nsh_base->ver_o_c & NSH_C_BIT)
     531           0 :     s = format (s, "C-set ");
     532             : 
     533           0 :   s = format (s, "ttl %d ", (nsh_base->ver_o_c & NSH_TTL_H4_MASK) << 2 |
     534           0 :               (nsh_base->length & NSH_TTL_L2_MASK) >> 6);
     535             : 
     536           0 :   s = format (s, "len %d (%d bytes) md_type %d next_protocol %d\n",
     537           0 :               (nsh_base->length & NSH_LEN_MASK),
     538           0 :               (nsh_base->length & NSH_LEN_MASK) * 4,
     539           0 :               nsh_base->md_type, nsh_base->next_protocol);
     540             : 
     541           0 :   s = format (s, "  service path %d service index %d\n",
     542           0 :               (clib_net_to_host_u32 (nsh_base->nsp_nsi) >> NSH_NSP_SHIFT) &
     543             :               NSH_NSP_MASK,
     544           0 :               clib_net_to_host_u32 (nsh_base->nsp_nsi) & NSH_NSI_MASK);
     545             : 
     546           0 :   if (nsh_base->md_type == 1)
     547             :     {
     548           0 :       s = format (s, "  c1 %d c2 %d c3 %d c4 %d\n",
     549             :                   clib_net_to_host_u32 (nsh_md1->c1),
     550             :                   clib_net_to_host_u32 (nsh_md1->c2),
     551             :                   clib_net_to_host_u32 (nsh_md1->c3),
     552             :                   clib_net_to_host_u32 (nsh_md1->c4));
     553             :     }
     554           0 :   else if (nsh_base->md_type == 2)
     555             :     {
     556           0 :       s = format (s, "  Supported TLVs: \n");
     557             : 
     558             :       /* Scan the set of variable metadata, network order */
     559           0 :       while (opt0 < limit0)
     560             :         {
     561           0 :           nsh_option = nsh_md2_lookup_option (opt0->class, opt0->type);
     562           0 :           if (nsh_option != NULL)
     563             :             {
     564           0 :               if (nm->trace[nsh_option->option_id] != NULL)
     565             :                 {
     566           0 :                   s = (*nm->trace[nsh_option->option_id]) (s, opt0);
     567             :                 }
     568             :               else
     569             :                 {
     570             :                   s =
     571           0 :                     format (s, "\n    untraced option %d length %d",
     572           0 :                             opt0->type, opt0->length);
     573             :                 }
     574             :             }
     575             :           else
     576             :             {
     577             :               s =
     578           0 :                 format (s, "\n    unrecognized option %d length %d",
     579           0 :                         opt0->type, opt0->length);
     580             :             }
     581             : 
     582             :           /* round to 4-byte */
     583           0 :           option_len = ((opt0->length + 3) >> 2) << 2;
     584           0 :           opt0 =
     585           0 :             (nsh_md2_data_t *) (((u8 *) opt0) + sizeof (nsh_md2_data_t) +
     586             :                                 option_len);
     587             :         }
     588             :     }
     589             : 
     590           0 :   return s;
     591             : }
     592             : 
     593             : u8 *
     594           0 : format_nsh_node_map_trace (u8 * s, va_list * args)
     595             : {
     596           0 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
     597           0 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
     598           0 :   nsh_input_trace_t *t = va_arg (*args, nsh_input_trace_t *);
     599             : 
     600           0 :   s = format (s, "\n  %U", format_nsh_header, &(t->trace_data));
     601             : 
     602           0 :   return s;
     603             : }
     604             : 
     605             : static clib_error_t *
     606           0 : show_nsh_entry_command_fn (vlib_main_t * vm,
     607             :                            unformat_input_t * input, vlib_cli_command_t * cmd)
     608             : {
     609           0 :   nsh_main_t *nm = &nsh_main;
     610             :   nsh_entry_t *nsh_entry;
     611             : 
     612           0 :   if (pool_elts (nm->nsh_entries) == 0)
     613           0 :     vlib_cli_output (vm, "No nsh entries configured.");
     614             : 
     615           0 :   pool_foreach (nsh_entry, nm->nsh_entries)
     616             :   {
     617           0 :     vlib_cli_output (vm, "%U", format_nsh_header, nsh_entry->rewrite);
     618           0 :     vlib_cli_output (vm, "  rewrite_size: %d bytes", nsh_entry->rewrite_size);
     619             :   }
     620             : 
     621           0 :   return 0;
     622             : }
     623             : 
     624             : /* *INDENT-OFF* */
     625       58901 : VLIB_CLI_COMMAND (show_nsh_entry_command, static) = {
     626             :   .path = "show nsh entry",
     627             :   .function = show_nsh_entry_command_fn,
     628             : };
     629             : /* *INDENT-ON* */
     630             : 
     631             : /*
     632             :  * fd.io coding-style-patch-verification: ON
     633             :  *
     634             :  * Local Variables:
     635             :  * eval: (c-set-style "gnu")
     636             :  * End:
     637             :  */

Generated by: LCOV version 1.14