LCOV - code coverage report
Current view: top level - vnet - interface_cli.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 312 974 32.0 %
Date: 2023-07-05 22:20:52 Functions: 69 95 72.6 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 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             :  * interface_cli.c: interface CLI
      17             :  *
      18             :  * Copyright (c) 2008 Eliot Dresselhaus
      19             :  *
      20             :  * Permission is hereby granted, free of charge, to any person obtaining
      21             :  * a copy of this software and associated documentation files (the
      22             :  * "Software"), to deal in the Software without restriction, including
      23             :  * without limitation the rights to use, copy, modify, merge, publish,
      24             :  * distribute, sublicense, and/or sell copies of the Software, and to
      25             :  * permit persons to whom the Software is furnished to do so, subject to
      26             :  * the following conditions:
      27             :  *
      28             :  * The above copyright notice and this permission notice shall be
      29             :  * included in all copies or substantial portions of the Software.
      30             :  *
      31             :  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      32             :  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      33             :  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      34             :  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      35             :  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      36             :  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      37             :  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      38             :  */
      39             : /**
      40             :  * @file
      41             :  * @brief Interface CLI.
      42             :  *
      43             :  * Source code for several CLI interface commands.
      44             :  *
      45             :  */
      46             : #include <vnet/vnet.h>
      47             : #include <vnet/ip/ip.h>
      48             : #include <vppinfra/bitmap.h>
      49             : #include <vnet/fib/ip4_fib.h>
      50             : #include <vnet/fib/ip6_fib.h>
      51             : #include <vnet/l2/l2_output.h>
      52             : #include <vnet/l2/l2_input.h>
      53             : #include <vnet/classify/vnet_classify.h>
      54             : #include <vnet/interface/rx_queue_funcs.h>
      55             : #include <vnet/interface/tx_queue_funcs.h>
      56             : #include <vnet/hash/hash.h>
      57             : static int
      58       16553 : compare_interface_names (void *a1, void *a2)
      59             : {
      60       16553 :   u32 *hi1 = a1;
      61       16553 :   u32 *hi2 = a2;
      62             : 
      63       16553 :   return vnet_hw_interface_compare (vnet_get_main (), *hi1, *hi2);
      64             : }
      65             : 
      66             : static clib_error_t *
      67        1970 : show_or_clear_hw_interfaces (vlib_main_t * vm,
      68             :                              unformat_input_t * input,
      69             :                              vlib_cli_command_t * cmd, int is_show)
      70             : {
      71        1970 :   clib_error_t *error = 0;
      72        1970 :   unformat_input_t _line_input, *line_input = &_line_input;
      73        1970 :   vnet_main_t *vnm = vnet_get_main ();
      74        1970 :   vnet_interface_main_t *im = &vnm->interface_main;
      75             :   vnet_hw_interface_t *hi;
      76        1970 :   u32 hw_if_index, *hw_if_indices = 0;
      77        1970 :   int i, verbose = -1, show_bond = 0;
      78             : 
      79        1970 :   if (!unformat_user (input, unformat_line_input, line_input))
      80        1970 :     goto skip_unformat;
      81             : 
      82           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
      83             :     {
      84             :       /* See if user wants to show a specific interface. */
      85           0 :       if (unformat (line_input, "%U", unformat_vnet_hw_interface, vnm,
      86             :                     &hw_if_index))
      87           0 :         vec_add1 (hw_if_indices, hw_if_index);
      88             : 
      89             :       /* See if user wants to show an interface with a specific hw_if_index. */
      90           0 :       else if (unformat (line_input, "%u", &hw_if_index))
      91           0 :         vec_add1 (hw_if_indices, hw_if_index);
      92             : 
      93           0 :       else if (unformat (line_input, "verbose"))
      94           0 :         verbose = 1;            /* this is also the default */
      95             : 
      96           0 :       else if (unformat (line_input, "detail"))
      97           0 :         verbose = 2;
      98             : 
      99           0 :       else if (unformat (line_input, "brief"))
     100           0 :         verbose = 0;
     101             : 
     102           0 :       else if (unformat (line_input, "bond"))
     103             :         {
     104           0 :           show_bond = 1;
     105           0 :           if (verbose < 0)
     106           0 :             verbose = 0;        /* default to brief for link bonding */
     107             :         }
     108             : 
     109             :       else
     110             :         {
     111           0 :           error = clib_error_return (0, "unknown input `%U'",
     112             :                                      format_unformat_error, line_input);
     113           0 :           unformat_free (line_input);
     114           0 :           goto done;
     115             :         }
     116             :     }
     117             : 
     118           0 :   unformat_free (line_input);
     119             : 
     120        1970 : skip_unformat:
     121             :   /* Gather interfaces. */
     122        1970 :   if (vec_len (hw_if_indices) == 0)
     123       12802 :     pool_foreach (hi, im->hw_interfaces)
     124       10832 :       vec_add1 (hw_if_indices, hi - im->hw_interfaces);
     125             : 
     126        1970 :   if (verbose < 0)
     127        1970 :     verbose = 1;                /* default to verbose (except bond) */
     128             : 
     129        1970 :   if (is_show)
     130             :     {
     131             :       /* Sort by name. */
     132        1970 :       vec_sort_with_function (hw_if_indices, compare_interface_names);
     133             : 
     134        1970 :       vlib_cli_output (vm, "%U\n", format_vnet_hw_interface, vnm, 0, verbose);
     135       12802 :       for (i = 0; i < vec_len (hw_if_indices); i++)
     136             :         {
     137       10832 :           hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
     138       10832 :           if (show_bond == 0)   /* show all interfaces */
     139       10832 :             vlib_cli_output (vm, "%U\n", format_vnet_hw_interface, vnm,
     140             :                              hi, verbose);
     141           0 :           else if ((hi->bond_info) &&
     142           0 :                    (hi->bond_info != VNET_HW_INTERFACE_BOND_INFO_SLAVE))
     143             :             {                   /* show only bonded interface and all its slave interfaces */
     144             :               int hw_idx;
     145             :               vnet_hw_interface_t *shi;
     146           0 :               vlib_cli_output (vm, "%U\n", format_vnet_hw_interface, vnm,
     147             :                                hi, verbose);
     148             : 
     149             :               /* *INDENT-OFF* */
     150           0 :               clib_bitmap_foreach (hw_idx, hi->bond_info)
     151             :                {
     152           0 :                 shi = vnet_get_hw_interface(vnm, hw_idx);
     153           0 :                 vlib_cli_output (vm, "%U\n",
     154             :                                  format_vnet_hw_interface, vnm, shi, verbose);
     155             :               }
     156             :               /* *INDENT-ON* */
     157             :             }
     158             :         }
     159             :     }
     160             :   else
     161             :     {
     162           0 :       for (i = 0; i < vec_len (hw_if_indices); i++)
     163             :         {
     164             :           vnet_device_class_t *dc;
     165             : 
     166           0 :           hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
     167           0 :           dc = vec_elt_at_index (im->device_classes, hi->dev_class_index);
     168             : 
     169           0 :           if (dc->clear_counters)
     170           0 :             dc->clear_counters (hi->dev_instance);
     171             :         }
     172             :     }
     173             : 
     174           0 : done:
     175        1970 :   vec_free (hw_if_indices);
     176        1970 :   return error;
     177             : }
     178             : 
     179             : static clib_error_t *
     180        1970 : show_hw_interfaces (vlib_main_t * vm,
     181             :                     unformat_input_t * input, vlib_cli_command_t * cmd)
     182             : {
     183        1970 :   return show_or_clear_hw_interfaces (vm, input, cmd, 1 /* is_show */ );
     184             : }
     185             : 
     186             : static clib_error_t *
     187           0 : clear_hw_interfaces (vlib_main_t * vm,
     188             :                      unformat_input_t * input, vlib_cli_command_t * cmd)
     189             : {
     190           0 :   return show_or_clear_hw_interfaces (vm, input, cmd, 0 /* is_show */ );
     191             : }
     192             : 
     193             : 
     194             : /*?
     195             :  * Display more detailed information about all or a list of given interfaces.
     196             :  * The verboseness of the output can be controlled by the following optional
     197             :  * parameters:
     198             :  * - brief: Only show name, index and state (default for bonded interfaces).
     199             :  * - verbose: Also display additional attributes (default for all other interfaces).
     200             :  * - detail: Also display all remaining attributes and extended statistics.
     201             :  *
     202             :  * To limit the output of the command to bonded interfaces and their slave
     203             :  * interfaces, use the '<em>bond</em>' optional parameter.
     204             :  *
     205             :  * @cliexpar
     206             :  * Example of how to display default data for all interfaces:
     207             :  * @cliexstart{show hardware-interfaces}
     208             :  *               Name                Idx   Link  Hardware
     209             :  * GigabitEthernet7/0/0               1     up   GigabitEthernet7/0/0
     210             :  *   Ethernet address ec:f4:bb:c0:bc:fc
     211             :  *   Intel e1000
     212             :  *     carrier up full duplex speed 1000 mtu 9216
     213             :  *     rx queues 1, rx desc 1024, tx queues 3, tx desc 1024
     214             :  *     cpu socket 0
     215             :  * GigabitEthernet7/0/1               2     up   GigabitEthernet7/0/1
     216             :  *   Ethernet address ec:f4:bb:c0:bc:fd
     217             :  *   Intel e1000
     218             :  *     carrier up full duplex speed 1000 mtu 9216
     219             :  *     rx queues 1, rx desc 1024, tx queues 3, tx desc 1024
     220             :  *     cpu socket 0
     221             :  * VirtualEthernet0/0/0               3     up   VirtualEthernet0/0/0
     222             :  *   Ethernet address 02:fe:a5:a9:8b:8e
     223             :  * VirtualEthernet0/0/1               4     up   VirtualEthernet0/0/1
     224             :  *   Ethernet address 02:fe:c0:4e:3b:b0
     225             :  * VirtualEthernet0/0/2               5     up   VirtualEthernet0/0/2
     226             :  *   Ethernet address 02:fe:1f:73:92:81
     227             :  * VirtualEthernet0/0/3               6     up   VirtualEthernet0/0/3
     228             :  *   Ethernet address 02:fe:f2:25:c4:68
     229             :  * local0                             0    down  local0
     230             :  *   local
     231             :  * @cliexend
     232             :  * Example of how to display '<em>verbose</em>' data for an interface by name and
     233             :  * software index (where 2 is the software index):
     234             :  * @cliexstart{show hardware-interfaces GigabitEthernet7/0/0 2 verbose}
     235             :  *               Name                Idx   Link  Hardware
     236             :  * GigabitEthernet7/0/0               1     up   GigabitEthernet7/0/0
     237             :  *   Ethernet address ec:f4:bb:c0:bc:fc
     238             :  *   Intel e1000
     239             :  *     carrier up full duplex speed 1000 mtu 9216
     240             :  *     rx queues 1, rx desc 1024, tx queues 3, tx desc 1024
     241             :  *     cpu socket 0
     242             :  * GigabitEthernet7/0/1               2    down  GigabitEthernet7/0/1
     243             :  *   Ethernet address ec:f4:bb:c0:bc:fd
     244             :  *   Intel e1000
     245             :  *     carrier up full duplex speed 1000 mtu 9216
     246             :  *     rx queues 1, rx desc 1024, tx queues 3, tx desc 1024
     247             :  *     cpu socket 0
     248             :  * @cliexend
     249             :  ?*/
     250             : /* *INDENT-OFF* */
     251      272887 : VLIB_CLI_COMMAND (show_hw_interfaces_command, static) = {
     252             :   .path = "show hardware-interfaces",
     253             :   .short_help = "show hardware-interfaces [brief|verbose|detail] [bond] "
     254             :     "[<interface> [<interface> [..]]] [<sw_idx> [<sw_idx> [..]]]",
     255             :   .function = show_hw_interfaces,
     256             : };
     257             : /* *INDENT-ON* */
     258             : 
     259             : 
     260             : /*?
     261             :  * Clear the extended statistics for all or a list of given interfaces
     262             :  * (statistics associated with the '<em>show hardware-interfaces</em>' command).
     263             :  *
     264             :  * @cliexpar
     265             :  * Example of how to clear the extended statistics for all interfaces:
     266             :  * @cliexcmd{clear hardware-interfaces}
     267             :  * Example of how to clear the extended statistics for an interface by
     268             :  * name and software index (where 2 is the software index):
     269             :  * @cliexcmd{clear hardware-interfaces GigabitEthernet7/0/0 2}
     270             :  ?*/
     271             : /* *INDENT-OFF* */
     272      272887 : VLIB_CLI_COMMAND (clear_hw_interface_counters_command, static) = {
     273             :   .path = "clear hardware-interfaces",
     274             :   .short_help = "clear hardware-interfaces "
     275             :     "[<interface> [<interface> [..]]] [<sw_idx> [<sw_idx> [..]]]",
     276             :   .function = clear_hw_interfaces,
     277             : };
     278             : /* *INDENT-ON* */
     279             : 
     280             : static int
     281       31553 : sw_interface_name_compare (void *a1, void *a2)
     282             : {
     283       31553 :   vnet_sw_interface_t *si1 = a1;
     284       31553 :   vnet_sw_interface_t *si2 = a2;
     285             : 
     286       31553 :   return vnet_sw_interface_compare (vnet_get_main (),
     287       31553 :                                     si1->sw_if_index, si2->sw_if_index);
     288             : }
     289             : 
     290             : static clib_error_t *
     291        2523 : show_sw_interfaces (vlib_main_t * vm,
     292             :                     unformat_input_t * input, vlib_cli_command_t * cmd)
     293             : {
     294        2523 :   clib_error_t *error = 0;
     295        2523 :   vnet_main_t *vnm = vnet_get_main ();
     296        2523 :   unformat_input_t _linput, *linput = &_linput;
     297        2523 :   vnet_interface_main_t *im = &vnm->interface_main;
     298        2523 :   vnet_sw_interface_t *si, *sorted_sis = 0;
     299        2523 :   u32 sw_if_index = ~(u32) 0;
     300        2523 :   u8 show_addresses = 0;
     301        2523 :   u8 show_features = 0;
     302        2523 :   u8 show_tag = 0;
     303        2523 :   u8 show_vtr = 0;
     304        2523 :   int verbose = 0;
     305             : 
     306             :   /*
     307             :    * Get a line of input. Won't work if the user typed
     308             :    * "show interface" and nothing more.
     309             :    */
     310        2523 :   if (unformat_user (input, unformat_line_input, linput))
     311             :     {
     312        1794 :       while (unformat_check_input (linput) != UNFORMAT_END_OF_INPUT)
     313             :         {
     314             :           /* See if user wants to show specific interface */
     315         899 :           if (unformat
     316             :               (linput, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
     317             :             {
     318           8 :               si = pool_elt_at_index (im->sw_interfaces, sw_if_index);
     319           8 :               vec_add1 (sorted_sis, si[0]);
     320             :             }
     321         891 :           else if (unformat (linput, "address") || unformat (linput, "addr"))
     322         887 :             show_addresses = 1;
     323           4 :           else if (unformat (linput, "features") || unformat (linput, "feat"))
     324           3 :             show_features = 1;
     325           1 :           else if (unformat (linput, "tag"))
     326           0 :             show_tag = 1;
     327           1 :           else if (unformat (linput, "vtr"))
     328           0 :             show_vtr = 1;
     329           1 :           else if (unformat (linput, "verbose"))
     330           0 :             verbose = 1;
     331           1 :           else if (unformat (linput, "%d", &sw_if_index))
     332             :             {
     333           0 :               if (!pool_is_free_index (im->sw_interfaces, sw_if_index))
     334             :                 {
     335           0 :                   si = pool_elt_at_index (im->sw_interfaces, sw_if_index);
     336           0 :                   vec_add1 (sorted_sis, si[0]);
     337             :                 }
     338             :               else
     339             :                 {
     340           0 :                   vec_free (sorted_sis);
     341           0 :                   error = clib_error_return (0, "unknown interface index `%d'",
     342             :                                              sw_if_index);
     343           0 :                   goto done;
     344             :                 }
     345             :             }
     346             :           else
     347             :             {
     348           1 :               vec_free (sorted_sis);
     349           1 :               error = clib_error_return (0, "unknown input `%U'",
     350             :                                          format_unformat_error, linput);
     351           1 :               goto done;
     352             :             }
     353             :         }
     354         895 :       unformat_free (linput);
     355             :     }
     356        2522 :   if (show_features || show_tag || show_vtr)
     357             :     {
     358           3 :       if (sw_if_index == ~(u32) 0)
     359             :         {
     360           0 :           vec_free (sorted_sis);
     361           0 :           return clib_error_return (0, "Interface not specified...");
     362             :         }
     363             :     }
     364             : 
     365        2522 :   if (show_features)
     366             :     {
     367           3 :       vnet_interface_features_show (vm, sw_if_index, verbose);
     368           3 :       vlib_cli_output (vm, "%U", format_l2_input_features, sw_if_index, 1);
     369             : 
     370           3 :       l2_output_config_t *l2_output = l2output_intf_config (sw_if_index);
     371           3 :       vlib_cli_output (vm, "\nl2-output:");
     372           3 :       if (l2_output->out_vtr_flag)
     373           0 :         vlib_cli_output (vm, "%10s (%s)", "VTR", "--internal--");
     374           3 :       vlib_cli_output (vm, "%U", format_l2_output_features,
     375             :                        l2_output->feature_bitmap, 1);
     376           3 :       vec_free (sorted_sis);
     377           3 :       return 0;
     378             :     }
     379        2519 :   if (show_tag)
     380             :     {
     381             :       u8 *tag;
     382           0 :       tag = vnet_get_sw_interface_tag (vnm, sw_if_index);
     383           0 :       vlib_cli_output (vm, "%U: %s",
     384             :                        format_vnet_sw_if_index_name, vnm, sw_if_index,
     385             :                        tag ? (char *) tag : "(none)");
     386           0 :       vec_free (sorted_sis);
     387           0 :       return 0;
     388             :     }
     389             : 
     390             :   /*
     391             :    * Show vlan tag rewrite data for one interface.
     392             :    */
     393        2519 :   if (show_vtr)
     394             :     {
     395           0 :       u32 vtr_op = L2_VTR_DISABLED;
     396           0 :       u32 push_dot1q = 0, tag1 = 0, tag2 = 0;
     397             : 
     398           0 :       if (l2vtr_get (vm, vnm, sw_if_index,
     399             :                      &vtr_op, &push_dot1q, &tag1, &tag2) != 0)
     400             :         {
     401           0 :           vlib_cli_output (vm, "%U: Problem getting vlan tag-rewrite data",
     402             :                            format_vnet_sw_if_index_name, vnm, sw_if_index);
     403           0 :           return 0;
     404             :         }
     405           0 :       vlib_cli_output (vm, "%U:  VTR %0U",
     406             :                        format_vnet_sw_if_index_name, vnm, sw_if_index,
     407             :                        format_vtr, vtr_op, push_dot1q, tag1, tag2);
     408           0 :       return 0;
     409             :     }
     410             : 
     411        2519 :   if (!show_addresses)
     412        1632 :     vlib_cli_output (vm, "%U\n", format_vnet_sw_interface, vnm, 0);
     413             : 
     414        2519 :   if (vec_len (sorted_sis) == 0)        /* Get all interfaces */
     415             :     {
     416             :       /* Gather interfaces. */
     417        2514 :       sorted_sis =
     418        2514 :         vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
     419        2514 :       vec_set_len (sorted_sis, 0);
     420             :       /* *INDENT-OFF* */
     421       18315 :       pool_foreach (si, im->sw_interfaces)
     422             :        {
     423       15801 :         int visible = vnet_swif_is_api_visible (si);
     424       15801 :         if (visible)
     425       15479 :           vec_add1 (sorted_sis, si[0]);
     426             :         }
     427             :       /* *INDENT-ON* */
     428             :       /* Sort by name. */
     429        2514 :       vec_sort_with_function (sorted_sis, sw_interface_name_compare);
     430             :     }
     431             : 
     432        2519 :   if (show_addresses)
     433             :     {
     434        4782 :       vec_foreach (si, sorted_sis)
     435             :       {
     436        3895 :         ip4_main_t *im4 = &ip4_main;
     437        3895 :         ip6_main_t *im6 = &ip6_main;
     438        3895 :         ip_lookup_main_t *lm4 = &im4->lookup_main;
     439        3895 :         ip_lookup_main_t *lm6 = &im6->lookup_main;
     440        3895 :         ip_interface_address_t *ia = 0;
     441        3895 :         u32 fib_index4 = 0, fib_index6 = 0;
     442             : 
     443        3895 :         if (vec_len (im4->fib_index_by_sw_if_index) > si->sw_if_index)
     444        3895 :           fib_index4 = vec_elt (im4->fib_index_by_sw_if_index,
     445             :                                 si->sw_if_index);
     446             : 
     447        3895 :         if (vec_len (im6->fib_index_by_sw_if_index) > si->sw_if_index)
     448        3895 :           fib_index6 = vec_elt (im6->fib_index_by_sw_if_index,
     449             :                                 si->sw_if_index);
     450             : 
     451        3895 :         ip4_fib_t *fib4 = ip4_fib_get (fib_index4);
     452        3895 :         ip6_fib_t *fib6 = ip6_fib_get (fib_index6);
     453             : 
     454        3895 :         if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
     455           0 :           vlib_cli_output
     456             :             (vm, "%U (%s): \n  unnumbered, use %U",
     457             :              format_vnet_sw_if_index_name, vnm, si->sw_if_index,
     458           0 :              (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? "up" : "dn",
     459             :              format_vnet_sw_if_index_name, vnm, si->unnumbered_sw_if_index);
     460             :         else
     461        3895 :           vlib_cli_output
     462             :             (vm, "%U (%s):",
     463             :              format_vnet_sw_if_index_name, vnm, si->sw_if_index,
     464        3895 :              (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? "up" : "dn");
     465             : 
     466             :         /* Display any L2 info */
     467        3895 :         vlib_cli_output (vm, "%U", format_l2_input, si->sw_if_index);
     468             : 
     469             :         /* *INDENT-OFF* */
     470             :         /* Display any IP4 addressing info */
     471        6741 :         foreach_ip_interface_address (lm4, ia, si->sw_if_index,
     472             :                                       1 /* honor unnumbered */,
     473             :         ({
     474             :           ip4_address_t *r4 = ip_interface_address_get_address (lm4, ia);
     475             :           if (fib4->hash.table_id)
     476             :             vlib_cli_output (
     477             :               vm, "  L3 %U/%d ip4 table-id %d fib-idx %d", format_ip4_address,
     478             :               r4, ia->address_length, fib4->hash.table_id,
     479             :               ip4_fib_index_from_table_id (fib4->hash.table_id));
     480             :           else
     481             :             vlib_cli_output (vm, "  L3 %U/%d",
     482             :                              format_ip4_address, r4, ia->address_length);
     483             :         }));
     484             :         /* *INDENT-ON* */
     485             : 
     486             :         /* *INDENT-OFF* */
     487             :         /* Display any IP6 addressing info */
     488        6698 :         foreach_ip_interface_address (lm6, ia, si->sw_if_index,
     489             :                                       1 /* honor unnumbered */,
     490             :         ({
     491             :           ip6_address_t *r6 = ip_interface_address_get_address (lm6, ia);
     492             :           if (fib6->table_id)
     493             :             vlib_cli_output (vm, "  L3 %U/%d ip6 table-id %d fib-idx %d",
     494             :                              format_ip6_address, r6, ia->address_length,
     495             :                              fib6->table_id,
     496             :                              ip6_fib_index_from_table_id (fib6->table_id));
     497             :           else
     498             :             vlib_cli_output (vm, "  L3 %U/%d",
     499             :                              format_ip6_address, r6, ia->address_length);
     500             :         }));
     501             :         /* *INDENT-ON* */
     502             :       }
     503             :     }
     504             :   else
     505             :     {
     506       13221 :       vec_foreach (si, sorted_sis)
     507             :       {
     508       11589 :         vlib_cli_output (vm, "%U\n", format_vnet_sw_interface, vnm, si);
     509             :       }
     510             :     }
     511             : 
     512        1632 : done:
     513        2520 :   vec_free (sorted_sis);
     514        2520 :   return error;
     515             : }
     516             : 
     517             : /* *INDENT-OFF* */
     518      272887 : VLIB_CLI_COMMAND (show_sw_interfaces_command, static) = {
     519             :   .path = "show interface",
     520             :   .short_help = "show interface [address|addr|features|feat|vtr|tag] "
     521             :                 "[<interface> [<interface> [..]]] [verbose]",
     522             :   .function = show_sw_interfaces,
     523             :   .is_mp_safe = 1,
     524             : };
     525             : /* *INDENT-ON* */
     526             : 
     527             : /* Root of all interface commands. */
     528             : /* *INDENT-OFF* */
     529      272887 : VLIB_CLI_COMMAND (vnet_cli_interface_command, static) = {
     530             :   .path = "interface",
     531             :   .short_help = "Interface commands",
     532             : };
     533             : /* *INDENT-ON* */
     534             : 
     535             : /* *INDENT-OFF* */
     536      272887 : VLIB_CLI_COMMAND (vnet_cli_set_interface_command, static) = {
     537             :   .path = "set interface",
     538             :   .short_help = "Interface commands",
     539             : };
     540             : /* *INDENT-ON* */
     541             : 
     542             : static clib_error_t *
     543           3 : clear_interface_counters (vlib_main_t * vm,
     544             :                           unformat_input_t * input, vlib_cli_command_t * cmd)
     545             : {
     546           3 :   vnet_main_t *vnm = vnet_get_main ();
     547           3 :   vnet_interface_main_t *im = &vnm->interface_main;
     548             :   vlib_simple_counter_main_t *sm;
     549             :   vlib_combined_counter_main_t *cm;
     550             :   int j, n_counters;
     551             : 
     552           3 :   n_counters = vec_len (im->combined_sw_if_counters);
     553             : 
     554          27 :   for (j = 0; j < n_counters; j++)
     555             :     {
     556          24 :       im = &vnm->interface_main;
     557          24 :       cm = im->combined_sw_if_counters + j;
     558          24 :       vlib_clear_combined_counters (cm);
     559             :     }
     560             : 
     561           3 :   n_counters = vec_len (im->sw_if_counters);
     562             : 
     563          30 :   for (j = 0; j < n_counters; j++)
     564             :     {
     565          27 :       im = &vnm->interface_main;
     566          27 :       sm = im->sw_if_counters + j;
     567          27 :       vlib_clear_simple_counters (sm);
     568             :     }
     569             : 
     570           3 :   return 0;
     571             : }
     572             : 
     573             : /*?
     574             :  * Clear the statistics for all interfaces (statistics associated with the
     575             :  * '<em>show interface</em>' command).
     576             :  *
     577             :  * @cliexpar
     578             :  * Example of how to clear the statistics for all interfaces:
     579             :  * @cliexcmd{clear interfaces}
     580             :  ?*/
     581             : /* *INDENT-OFF* */
     582      272887 : VLIB_CLI_COMMAND (clear_interface_counters_command, static) = {
     583             :   .path = "clear interfaces",
     584             :   .short_help = "clear interfaces",
     585             :   .function = clear_interface_counters,
     586             : };
     587             : /* *INDENT-ON* */
     588             : 
     589             : /**
     590             :  * Parse subinterface names.
     591             :  *
     592             :  * The following subinterface syntax is supported. The first two are for
     593             :  * backwards compatability:
     594             :  *
     595             :  * <intf-name> <id>
     596             :  *     - a subinterface with the name <intf-name>.<id>. The subinterface
     597             :  *       is a single dot1q vlan with vlan id <id> and exact-match semantics.
     598             :  *
     599             :  * <intf-name> <min_id>-<max_id>
     600             :  *     - a set of the above subinterfaces, repeating for each id
     601             :  *       in the range <min_id> to <max_id>
     602             :  *
     603             :  * In the following, exact-match semantics (i.e. the number of vlan tags on the
     604             :  * packet must match the number of tags in the configuration) are used only if
     605             :  * the keyword exact-match is present. Non-exact match is the default.
     606             :  *
     607             :  * <intf-name> <id> dot1q <outer_id> [exact-match]
     608             :  *     - a subinterface with the name <intf-name>.<id>. The subinterface
     609             :  *       is a single dot1q vlan with vlan id <outer_id>.
     610             :  *
     611             :  * <intf-name> <id> dot1q any [exact-match]
     612             :  *     - a subinterface with the name <intf-name>.<id>. The subinterface
     613             :  *       is a single dot1q vlan with any vlan id.
     614             :  *
     615             :  * <intf-name> <id> dot1q <outer_id> inner-dot1q <inner_id> [exact-match]
     616             :  *     - a subinterface with the name <intf-name>.<id>. The subinterface
     617             :  *       is a double dot1q vlan with outer vlan id <outer_id> and inner vlan id
     618             :  *       <inner_id>.
     619             :  *
     620             :  * <intf-name> <id> dot1q <outer_id> inner-dot1q any [exact-match]
     621             :  *     - a subinterface with the name <intf-name>.<id>. The subinterface
     622             :  *       is a double dot1q vlan with outer vlan id <id> and any inner vlan id.
     623             :  *
     624             :  * <intf-name> <id> dot1q any inner-dot1q any [exact-match]
     625             :  *
     626             :  *     - a subinterface with the name <intf-name>.<id>. The subinterface
     627             :  *       is a double dot1q vlan with any outer vlan id and any inner vlan id.
     628             :  *
     629             :  * For each of the above CLI, there is a duplicate that uses the keyword
     630             :  * "dot1ad" in place of the first "dot1q". These interfaces use ethertype
     631             :  * 0x88ad in place of 0x8100 for the outer ethertype. Note that for double-
     632             :  * tagged packets the inner ethertype is always 0x8100. Also note that
     633             :  * the dot1q and dot1ad naming spaces are independent, so it is legal to
     634             :  * have both "Gig3/0/0.1 dot1q 100" and "Gig3/0/0.2 dot1ad 100". For example:
     635             :  *
     636             :  * <intf-name> <id> dot1ad <outer_id> inner-dot1q <inner_id> [exact-match]
     637             :  *     - a subinterface with the name <intf-name>.<id>. The subinterface
     638             :  *       is a double dot1ad vlan with outer vlan id <outer_id> and inner vlan
     639             :  *       id <inner_id>.
     640             :  *
     641             :  * <intf-name> <id> untagged
     642             :  *     - a subinterface with the name <intf-name>.<id>. The subinterface
     643             :  *       has no vlan tags. Only one can be specified per interface.
     644             :  *
     645             :  * <intf-name> <id> default
     646             :  *     - a subinterface with the name <intf-name>.<id>. This is associated
     647             :  *       with a packet that did not match any other configured subinterface
     648             :  *       on this interface. Only one can be specified per interface.
     649             :  */
     650             : 
     651             : static clib_error_t *
     652           0 : parse_vlan_sub_interfaces (unformat_input_t * input,
     653             :                            vnet_sw_interface_t * template)
     654             : {
     655           0 :   clib_error_t *error = 0;
     656             :   u32 inner_vlan, outer_vlan;
     657             : 
     658           0 :   if (unformat (input, "any inner-dot1q any"))
     659             :     {
     660           0 :       template->sub.eth.flags.two_tags = 1;
     661           0 :       template->sub.eth.flags.outer_vlan_id_any = 1;
     662           0 :       template->sub.eth.flags.inner_vlan_id_any = 1;
     663             :     }
     664           0 :   else if (unformat (input, "any"))
     665             :     {
     666           0 :       template->sub.eth.flags.one_tag = 1;
     667           0 :       template->sub.eth.flags.outer_vlan_id_any = 1;
     668             :     }
     669           0 :   else if (unformat (input, "%d inner-dot1q any", &outer_vlan))
     670             :     {
     671           0 :       template->sub.eth.flags.two_tags = 1;
     672           0 :       template->sub.eth.flags.inner_vlan_id_any = 1;
     673           0 :       template->sub.eth.outer_vlan_id = outer_vlan;
     674             :     }
     675           0 :   else if (unformat (input, "%d inner-dot1q %d", &outer_vlan, &inner_vlan))
     676             :     {
     677           0 :       template->sub.eth.flags.two_tags = 1;
     678           0 :       template->sub.eth.outer_vlan_id = outer_vlan;
     679           0 :       template->sub.eth.inner_vlan_id = inner_vlan;
     680             :     }
     681           0 :   else if (unformat (input, "%d", &outer_vlan))
     682             :     {
     683           0 :       template->sub.eth.flags.one_tag = 1;
     684           0 :       template->sub.eth.outer_vlan_id = outer_vlan;
     685             :     }
     686             :   else
     687             :     {
     688           0 :       error = clib_error_return (0, "expected dot1q config, got `%U'",
     689             :                                  format_unformat_error, input);
     690           0 :       goto done;
     691             :     }
     692             : 
     693           0 :   if (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     694             :     {
     695           0 :       if (unformat (input, "exact-match"))
     696             :         {
     697           0 :           template->sub.eth.flags.exact_match = 1;
     698             :         }
     699             :     }
     700             : 
     701           0 : done:
     702           0 :   return error;
     703             : }
     704             : 
     705             : static clib_error_t *
     706           0 : create_sub_interfaces (vlib_main_t * vm,
     707             :                        unformat_input_t * input, vlib_cli_command_t * cmd)
     708             : {
     709           0 :   vnet_main_t *vnm = vnet_get_main ();
     710           0 :   clib_error_t *error = 0;
     711             :   u32 hw_if_index, sw_if_index;
     712             :   vnet_hw_interface_t *hi;
     713             :   u32 id, id_min, id_max;
     714             :   vnet_sw_interface_t template;
     715             : 
     716           0 :   hw_if_index = ~0;
     717           0 :   if (!unformat_user (input, unformat_vnet_hw_interface, vnm, &hw_if_index))
     718             :     {
     719           0 :       error = clib_error_return (0, "unknown interface `%U'",
     720             :                                  format_unformat_error, input);
     721           0 :       goto done;
     722             :     }
     723             : 
     724           0 :   clib_memset (&template, 0, sizeof (template));
     725           0 :   template.sub.eth.raw_flags = 0;
     726             : 
     727           0 :   if (unformat (input, "%d default", &id_min))
     728             :     {
     729           0 :       id_max = id_min;
     730           0 :       template.sub.eth.flags.default_sub = 1;
     731             :     }
     732           0 :   else if (unformat (input, "%d untagged", &id_min))
     733             :     {
     734           0 :       id_max = id_min;
     735           0 :       template.sub.eth.flags.no_tags = 1;
     736           0 :       template.sub.eth.flags.exact_match = 1;
     737             :     }
     738           0 :   else if (unformat (input, "%d dot1q", &id_min))
     739             :     {
     740             :       /* parse dot1q config */
     741           0 :       id_max = id_min;
     742           0 :       error = parse_vlan_sub_interfaces (input, &template);
     743           0 :       if (error)
     744           0 :         goto done;
     745             :     }
     746           0 :   else if (unformat (input, "%d dot1ad", &id_min))
     747             :     {
     748             :       /* parse dot1ad config */
     749           0 :       id_max = id_min;
     750           0 :       template.sub.eth.flags.dot1ad = 1;
     751           0 :       error = parse_vlan_sub_interfaces (input, &template);
     752           0 :       if (error)
     753           0 :         goto done;
     754             :     }
     755           0 :   else if (unformat (input, "%d-%d", &id_min, &id_max))
     756             :     {
     757           0 :       template.sub.eth.flags.one_tag = 1;
     758           0 :       template.sub.eth.flags.exact_match = 1;
     759           0 :       if (id_min > id_max)
     760           0 :         goto id_error;
     761             :     }
     762           0 :   else if (unformat (input, "%d", &id_min))
     763             :     {
     764           0 :       id_max = id_min;
     765           0 :       template.sub.eth.flags.one_tag = 1;
     766           0 :       template.sub.eth.outer_vlan_id = id_min;
     767           0 :       template.sub.eth.flags.exact_match = 1;
     768             :     }
     769             :   else
     770             :     {
     771           0 :     id_error:
     772           0 :       error = clib_error_return (0, "expected ID or ID MIN-MAX, got `%U'",
     773             :                                  format_unformat_error, input);
     774           0 :       goto done;
     775             :     }
     776             : 
     777           0 :   hi = vnet_get_hw_interface (vnm, hw_if_index);
     778             : 
     779           0 :   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
     780             :     {
     781             :       error =
     782           0 :         clib_error_return (0,
     783             :                            "not allowed as %v belong to a BondEthernet interface",
     784             :                            hi->name);
     785           0 :       goto done;
     786             :     }
     787             : 
     788           0 :   for (id = id_min; id <= id_max; id++)
     789             :     {
     790             :       uword *p;
     791           0 :       vnet_interface_main_t *im = &vnm->interface_main;
     792           0 :       u64 sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
     793             :       u64 *kp;
     794             : 
     795           0 :       p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
     796           0 :       if (p)
     797             :         {
     798             :           if (CLIB_DEBUG > 0)
     799           0 :             clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
     800             :                           hi->sw_if_index, id);
     801           0 :           continue;
     802             :         }
     803             : 
     804           0 :       template.type = VNET_SW_INTERFACE_TYPE_SUB;
     805           0 :       template.flood_class = VNET_FLOOD_CLASS_NORMAL;
     806           0 :       template.sup_sw_if_index = hi->sw_if_index;
     807           0 :       template.sub.id = id;
     808           0 :       if (id_min < id_max)
     809           0 :         template.sub.eth.outer_vlan_id = id;
     810             : 
     811           0 :       error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
     812           0 :       if (error)
     813           0 :         goto done;
     814             : 
     815           0 :       kp = clib_mem_alloc (sizeof (*kp));
     816           0 :       *kp = sup_and_sub_key;
     817             : 
     818           0 :       hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
     819           0 :       hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
     820           0 :       vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name,
     821             :                        vnet_get_main (), sw_if_index);
     822             :     }
     823             : 
     824           0 : done:
     825           0 :   return error;
     826             : }
     827             : 
     828             : /*?
     829             :  * This command is used to add VLAN IDs to interfaces, also known as subinterfaces.
     830             :  * The primary input to this command is the '<em>interface</em>' and '<em>subId</em>'
     831             :  * (subinterface Id) parameters. If no additional VLAN ID is provide, the VLAN ID is
     832             :  * assumed to be the '<em>subId</em>'. The VLAN ID and '<em>subId</em>' can be different,
     833             :  * but this is not recommended.
     834             :  *
     835             :  * This command has several variations:
     836             :  * - <b>create sub-interfaces <interface> <subId></b> - Create a subinterface to
     837             :  * process packets with a given 802.1q VLAN ID (same value as the '<em>subId</em>').
     838             :  *
     839             :  * - <b>create sub-interfaces <interface> <subId> default</b> - Adding the
     840             :  * '<em>default</em>' parameter indicates that packets with VLAN IDs that do not
     841             :  * match any other subinterfaces should be sent to this subinterface.
     842             :  *
     843             :  * - <b>create sub-interfaces <interface> <subId> untagged</b> - Adding the
     844             :  * '<em>untagged</em>' parameter indicates that packets no VLAN IDs should be sent
     845             :  * to this subinterface.
     846             :  *
     847             :  * - <b>create sub-interfaces <interface> <subId>-<subId></b> - Create a range of
     848             :  * subinterfaces to handle a range of VLAN IDs.
     849             :  *
     850             :  * - <b>create sub-interfaces <interface> <subId> dot1q|dot1ad <vlanId>|any [exact-match]</b> -
     851             :  * Use this command to specify the outer VLAN ID, to either be explicit or to make the
     852             :  * VLAN ID different from the '<em>subId</em>'.
     853             :  *
     854             :  * - <b>create sub-interfaces <interface> <subId> dot1q|dot1ad <vlanId>|any inner-dot1q
     855             :  * <vlanId>|any [exact-match]</b> - Use this command to specify the outer VLAN ID and
     856             :  * the inner VLAN ID.
     857             :  *
     858             :  * When '<em>dot1q</em>' or '<em>dot1ad</em>' is explicitly entered, subinterfaces
     859             :  * can be configured as either exact-match or non-exact match. Non-exact match is the CLI
     860             :  * default. If '<em>exact-match</em>' is specified, packets must have the same number of
     861             :  * VLAN tags as the configuration. For non-exact-match, packets must at least that number
     862             :  * of tags. L3 (routed) interfaces must be configured as exact-match. L2 interfaces are
     863             :  * typically configured as non-exact-match. If '<em>dot1q</em>' or '<em>dot1ad</em>' is NOT
     864             :  * entered, then the default behavior is exact-match.
     865             :  *
     866             :  * Use the '<em>show interface</em>' command to display all subinterfaces.
     867             :  *
     868             :  * @cliexpar
     869             :  * @parblock
     870             :  * Example of how to create a VLAN subinterface 11 to process packets on 802.1q VLAN ID 11:
     871             :  * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11}
     872             :  *
     873             :  * The previous example is shorthand and is equivalent to:
     874             :  * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11 dot1q 11 exact-match}
     875             :  *
     876             :  *
     877             :  * Example of how to create a subinterface number that is different from the VLAN ID:
     878             :  * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11 dot1q 100}
     879             :  *
     880             :  *
     881             :  * Examples of how to create q-in-q and q-in-any subinterfaces:
     882             :  * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11 dot1q 100 inner-dot1q 200}
     883             :  * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 12 dot1q 100 inner-dot1q any}
     884             :  *
     885             :  * Examples of how to create dot1ad interfaces:
     886             :  * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11 dot1ad 11}
     887             :  * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 12 dot1ad 100 inner-dot1q 200}
     888             :  *
     889             :  *
     890             :  * Examples of '<em>exact-match</em>' versus non-exact match. A packet with
     891             :  * outer VLAN 100 and inner VLAN 200 would match this interface, because the default
     892             :  * is non-exact match:
     893             :  * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 5 dot1q 100}
     894             :  *
     895             :  * However, the same packet would NOT match this interface because '<em>exact-match</em>'
     896             :  * is specified and only one VLAN is configured, but packet contains two VLANs:
     897             :  * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 5 dot1q 100 exact-match}
     898             :  *
     899             :  *
     900             :  * Example of how to created a subinterface to process untagged packets:
     901             :  * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 5 untagged}
     902             :  *
     903             :  * Example of how to created a subinterface to process any packet with a VLAN ID that
     904             :  * does not match any other subinterface:
     905             :  * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 7 default}
     906             :  *
     907             :  * When subinterfaces are created, they are in the down state. Example of how to
     908             :  * enable a newly created subinterface:
     909             :  * @cliexcmd{set interface GigabitEthernet2/0/0.7 up}
     910             :  * @endparblock
     911             :  ?*/
     912             : /* *INDENT-OFF* */
     913      272887 : VLIB_CLI_COMMAND (create_sub_interfaces_command, static) = {
     914             :   .path = "create sub-interfaces",
     915             :   .short_help = "create sub-interfaces <interface> "
     916             :     "{<subId> [default|untagged]} | "
     917             :     "{<subId>-<subId>} | "
     918             :     "{<subId> dot1q|dot1ad <vlanId>|any [inner-dot1q <vlanId>|any] [exact-match]}",
     919             :   .function = create_sub_interfaces,
     920             : };
     921             : /* *INDENT-ON* */
     922             : 
     923             : static clib_error_t *
     924           5 : set_state (vlib_main_t * vm,
     925             :            unformat_input_t * input, vlib_cli_command_t * cmd)
     926             : {
     927           5 :   vnet_main_t *vnm = vnet_get_main ();
     928             :   clib_error_t *error;
     929             :   u32 sw_if_index, flags;
     930             : 
     931           5 :   sw_if_index = ~0;
     932           5 :   if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
     933             :     {
     934           0 :       error = clib_error_return (0, "unknown interface `%U'",
     935             :                                  format_unformat_error, input);
     936           0 :       goto done;
     937             :     }
     938             : 
     939           5 :   if (!unformat (input, "%U", unformat_vnet_sw_interface_flags, &flags))
     940             :     {
     941           0 :       error = clib_error_return (0, "unknown flags `%U'",
     942             :                                  format_unformat_error, input);
     943           0 :       goto done;
     944             :     }
     945             : 
     946           5 :   error = vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
     947           5 :   if (error)
     948           0 :     goto done;
     949             : 
     950           5 : done:
     951           5 :   return error;
     952             : }
     953             : 
     954             : /*?
     955             :  * This command is used to change the admin state (up/down) of an interface.
     956             :  *
     957             :  * If an interface is down, the optional '<em>punt</em>' flag can also be set.
     958             :  * The '<em>punt</em>' flag implies the interface is disabled for forwarding
     959             :  * but punt all traffic to slow-path. Use the '<em>enable</em>' flag to clear
     960             :  * '<em>punt</em>' flag (interface is still down).
     961             :  *
     962             :  * @cliexpar
     963             :  * Example of how to configure the admin state of an interface to
     964             :  '<em>up</em>':
     965             :  * @cliexcmd{set interface state GigabitEthernet2/0/0 up}
     966             :  * Example of how to configure the admin state of an interface to
     967             :  '<em>down</em>':
     968             :  * @cliexcmd{set interface state GigabitEthernet2/0/0 down}
     969             :  ?*/
     970             : /* *INDENT-OFF* */
     971      272887 : VLIB_CLI_COMMAND (set_state_command, static) = {
     972             :   .path = "set interface state",
     973             :   .short_help = "set interface state <interface> [up|down|punt|enable]",
     974             :   .function = set_state,
     975             : };
     976             : /* *INDENT-ON* */
     977             : 
     978             : static clib_error_t *
     979           0 : set_unnumbered (vlib_main_t * vm,
     980             :                 unformat_input_t * input, vlib_cli_command_t * cmd)
     981             : {
     982           0 :   vnet_main_t *vnm = vnet_get_main ();
     983           0 :   u32 unnumbered_sw_if_index = ~0;
     984           0 :   u32 inherit_from_sw_if_index = ~0;
     985           0 :   int enable = 1;
     986             : 
     987           0 :   if (unformat (input, "%U use %U",
     988             :                 unformat_vnet_sw_interface, vnm, &unnumbered_sw_if_index,
     989             :                 unformat_vnet_sw_interface, vnm, &inherit_from_sw_if_index))
     990           0 :     enable = 1;
     991           0 :   else if (unformat (input, "del %U",
     992             :                      unformat_vnet_sw_interface, vnm,
     993             :                      &unnumbered_sw_if_index))
     994           0 :     enable = 0;
     995             :   else
     996           0 :     return clib_error_return (0, "parse error '%U'",
     997             :                               format_unformat_error, input);
     998             : 
     999           0 :   if (~0 == unnumbered_sw_if_index)
    1000           0 :     return clib_error_return (0, "Specify the unnumbered interface");
    1001           0 :   if (enable && ~0 == inherit_from_sw_if_index)
    1002           0 :     return clib_error_return (0, "When enabling unnumbered specify the"
    1003             :                               " IP enabled interface that it uses");
    1004             : 
    1005           0 :   int rv = vnet_sw_interface_update_unnumbered (
    1006             :     unnumbered_sw_if_index, inherit_from_sw_if_index, enable);
    1007             : 
    1008           0 :   switch (rv)
    1009             :     {
    1010           0 :     case 0:
    1011           0 :       break;
    1012             : 
    1013           0 :     case VNET_API_ERROR_UNEXPECTED_INTF_STATE:
    1014           0 :       return clib_error_return (
    1015             :         0,
    1016             :         "When enabling unnumbered both interfaces must be in the same tables");
    1017             : 
    1018           0 :     default:
    1019           0 :       return clib_error_return (
    1020             :         0, "vnet_sw_interface_update_unnumbered returned %d", rv);
    1021             :     }
    1022             : 
    1023           0 :   return (NULL);
    1024             : }
    1025             : 
    1026             : /* *INDENT-OFF* */
    1027      272887 : VLIB_CLI_COMMAND (set_unnumbered_command, static) = {
    1028             :   .path = "set interface unnumbered",
    1029             :   .short_help = "set interface unnumbered [<interface> use <interface> | del <interface>]",
    1030             :   .function = set_unnumbered,
    1031             : };
    1032             : /* *INDENT-ON* */
    1033             : 
    1034             : 
    1035             : 
    1036             : static clib_error_t *
    1037           0 : set_hw_class (vlib_main_t * vm,
    1038             :               unformat_input_t * input, vlib_cli_command_t * cmd)
    1039             : {
    1040           0 :   vnet_main_t *vnm = vnet_get_main ();
    1041           0 :   vnet_interface_main_t *im = &vnm->interface_main;
    1042             :   clib_error_t *error;
    1043             :   u32 hw_if_index, hw_class_index;
    1044             : 
    1045           0 :   hw_if_index = ~0;
    1046           0 :   if (!unformat_user (input, unformat_vnet_hw_interface, vnm, &hw_if_index))
    1047             :     {
    1048           0 :       error = clib_error_return (0, "unknown hardware interface `%U'",
    1049             :                                  format_unformat_error, input);
    1050           0 :       goto done;
    1051             :     }
    1052             : 
    1053           0 :   if (!unformat_user (input, unformat_hash_string,
    1054             :                       im->hw_interface_class_by_name, &hw_class_index))
    1055             :     {
    1056           0 :       error = clib_error_return (0, "unknown hardware class `%U'",
    1057             :                                  format_unformat_error, input);
    1058           0 :       goto done;
    1059             :     }
    1060             : 
    1061           0 :   error = vnet_hw_interface_set_class (vnm, hw_if_index, hw_class_index);
    1062           0 :   if (error)
    1063           0 :     goto done;
    1064             : 
    1065           0 : done:
    1066           0 :   return error;
    1067             : }
    1068             : 
    1069             : /* *INDENT-OFF* */
    1070      272887 : VLIB_CLI_COMMAND (set_hw_class_command, static) = {
    1071             :   .path = "set interface hw-class",
    1072             :   .short_help = "Set interface hardware class",
    1073             :   .function = set_hw_class,
    1074             : };
    1075             : /* *INDENT-ON* */
    1076             : 
    1077             : static clib_error_t *
    1078         559 : vnet_interface_cli_init (vlib_main_t * vm)
    1079             : {
    1080         559 :   return 0;
    1081             : }
    1082             : 
    1083       10639 : VLIB_INIT_FUNCTION (vnet_interface_cli_init);
    1084             : 
    1085             : static clib_error_t *
    1086           0 : renumber_interface_command_fn (vlib_main_t * vm,
    1087             :                                unformat_input_t * input,
    1088             :                                vlib_cli_command_t * cmd)
    1089             : {
    1090             :   u32 hw_if_index;
    1091             :   u32 new_dev_instance;
    1092           0 :   vnet_main_t *vnm = vnet_get_main ();
    1093             :   int rv;
    1094             : 
    1095           0 :   if (!unformat_user (input, unformat_vnet_hw_interface, vnm, &hw_if_index))
    1096           0 :     return clib_error_return (0, "unknown hardware interface `%U'",
    1097             :                               format_unformat_error, input);
    1098             : 
    1099           0 :   if (!unformat (input, "%d", &new_dev_instance))
    1100           0 :     return clib_error_return (0, "new dev instance missing");
    1101             : 
    1102           0 :   rv = vnet_interface_name_renumber (hw_if_index, new_dev_instance);
    1103             : 
    1104           0 :   switch (rv)
    1105             :     {
    1106           0 :     case 0:
    1107           0 :       break;
    1108             : 
    1109           0 :     default:
    1110           0 :       return clib_error_return (0, "vnet_interface_name_renumber returned %d",
    1111             :                                 rv);
    1112             : 
    1113             :     }
    1114             : 
    1115           0 :   return 0;
    1116             : }
    1117             : 
    1118             : 
    1119             : /* *INDENT-OFF* */
    1120      272887 : VLIB_CLI_COMMAND (renumber_interface_command, static) = {
    1121             :   .path = "renumber interface",
    1122             :   .short_help = "renumber interface <interface> <new-dev-instance>",
    1123             :   .function = renumber_interface_command_fn,
    1124             : };
    1125             : /* *INDENT-ON* */
    1126             : 
    1127             : static clib_error_t *
    1128           0 : promiscuous_cmd (vlib_main_t * vm,
    1129             :                  unformat_input_t * input, vlib_cli_command_t * cmd)
    1130             : {
    1131           0 :   vnet_main_t *vnm = vnet_get_main ();
    1132             :   u32 hw_if_index;
    1133           0 :   u32 flags = ETHERNET_INTERFACE_FLAG_ACCEPT_ALL;
    1134           0 :   ethernet_main_t *em = &ethernet_main;
    1135             :   ethernet_interface_t *eif;
    1136             : 
    1137           0 :   if (unformat (input, "on %U",
    1138             :                 unformat_vnet_hw_interface, vnm, &hw_if_index))
    1139             :     ;
    1140           0 :   else if (unformat (input, "off %U",
    1141             :                      unformat_ethernet_interface, vnm, &hw_if_index))
    1142           0 :     flags = 0;
    1143             :   else
    1144           0 :     return clib_error_return (0, "unknown input `%U'",
    1145             :                               format_unformat_error, input);
    1146             : 
    1147           0 :   eif = ethernet_get_interface (em, hw_if_index);
    1148           0 :   if (!eif)
    1149           0 :     return clib_error_return (0, "not supported");
    1150             : 
    1151           0 :   ethernet_set_flags (vnm, hw_if_index, flags);
    1152           0 :   return 0;
    1153             : }
    1154             : 
    1155             : /* *INDENT-OFF* */
    1156      272887 : VLIB_CLI_COMMAND (set_interface_promiscuous_cmd, static) = {
    1157             :   .path = "set interface promiscuous",
    1158             :   .short_help = "set interface promiscuous [on|off] <interface>",
    1159             :   .function = promiscuous_cmd,
    1160             : };
    1161             : /* *INDENT-ON* */
    1162             : 
    1163             : static clib_error_t *
    1164           0 : mtu_cmd (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
    1165             : {
    1166           0 :   vnet_main_t *vnm = vnet_get_main ();
    1167             :   u32 hw_if_index, sw_if_index, mtu;
    1168           0 :   ethernet_main_t *em = &ethernet_main;
    1169           0 :   u32 mtus[VNET_N_MTU] = { 0, 0, 0, 0 };
    1170             :   clib_error_t *err;
    1171             : 
    1172           0 :   if (unformat (input, "%d %U", &mtu,
    1173             :                 unformat_vnet_hw_interface, vnm, &hw_if_index))
    1174             :     {
    1175             :       /*
    1176             :        * Change physical MTU on interface. Only supported for Ethernet
    1177             :        * interfaces
    1178             :        */
    1179           0 :       ethernet_interface_t *eif = ethernet_get_interface (em, hw_if_index);
    1180             : 
    1181           0 :       if (!eif)
    1182           0 :         return clib_error_return (0, "not supported");
    1183             : 
    1184           0 :       err = vnet_hw_interface_set_mtu (vnm, hw_if_index, mtu);
    1185           0 :       if (err)
    1186           0 :         return err;
    1187           0 :       goto done;
    1188             :     }
    1189           0 :   else if (unformat (input, "packet %d %U", &mtu,
    1190             :                      unformat_vnet_sw_interface, vnm, &sw_if_index))
    1191             :     /* Set default packet MTU (including L3 header */
    1192           0 :     mtus[VNET_MTU_L3] = mtu;
    1193           0 :   else if (unformat (input, "ip4 %d %U", &mtu,
    1194             :                      unformat_vnet_sw_interface, vnm, &sw_if_index))
    1195           0 :     mtus[VNET_MTU_IP4] = mtu;
    1196           0 :   else if (unformat (input, "ip6 %d %U", &mtu,
    1197             :                      unformat_vnet_sw_interface, vnm, &sw_if_index))
    1198           0 :     mtus[VNET_MTU_IP6] = mtu;
    1199           0 :   else if (unformat (input, "mpls %d %U", &mtu,
    1200             :                      unformat_vnet_sw_interface, vnm, &sw_if_index))
    1201           0 :     mtus[VNET_MTU_MPLS] = mtu;
    1202             :   else
    1203           0 :     return clib_error_return (0, "unknown input `%U'",
    1204             :                               format_unformat_error, input);
    1205             : 
    1206           0 :   vnet_sw_interface_set_protocol_mtu (vnm, sw_if_index, mtus);
    1207             : 
    1208           0 : done:
    1209           0 :   return 0;
    1210             : }
    1211             : 
    1212             : /* *INDENT-OFF* */
    1213      272887 : VLIB_CLI_COMMAND (set_interface_mtu_cmd, static) = {
    1214             :   .path = "set interface mtu",
    1215             :   .short_help = "set interface mtu [packet|ip4|ip6|mpls] <value> <interface>",
    1216             :   .function = mtu_cmd,
    1217             : };
    1218             : /* *INDENT-ON* */
    1219             : 
    1220             : static clib_error_t *
    1221           0 : show_interface_sec_mac_addr_fn (vlib_main_t * vm, unformat_input_t * input,
    1222             :                                 vlib_cli_command_t * cmd)
    1223             : {
    1224           0 :   vnet_main_t *vnm = vnet_get_main ();
    1225           0 :   vnet_interface_main_t *im = &vnm->interface_main;
    1226           0 :   ethernet_main_t *em = &ethernet_main;
    1227           0 :   u32 sw_if_index = ~0;
    1228           0 :   vnet_sw_interface_t *si, *sorted_sis = 0;
    1229             : 
    1230           0 :   if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
    1231             :     {
    1232           0 :       si = pool_elt_at_index (im->sw_interfaces, sw_if_index);
    1233           0 :       vec_add1 (sorted_sis, si[0]);
    1234             :     }
    1235             : 
    1236             :   /* if an interface name was not passed, get all interfaces */
    1237           0 :   if (vec_len (sorted_sis) == 0)
    1238             :     {
    1239           0 :       sorted_sis =
    1240           0 :         vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
    1241           0 :       vec_set_len (sorted_sis, 0);
    1242             :       /* *INDENT-OFF* */
    1243           0 :       pool_foreach (si, im->sw_interfaces)
    1244             :        {
    1245           0 :         int visible = vnet_swif_is_api_visible (si);
    1246           0 :         if (visible)
    1247           0 :           vec_add1 (sorted_sis, si[0]);
    1248             :         }
    1249             :       /* *INDENT-ON* */
    1250             :       /* Sort by name. */
    1251           0 :       vec_sort_with_function (sorted_sis, sw_interface_name_compare);
    1252             :     }
    1253             : 
    1254           0 :   vec_foreach (si, sorted_sis)
    1255             :   {
    1256             :     vnet_sw_interface_t *sup_si;
    1257             :     ethernet_interface_t *ei;
    1258             : 
    1259           0 :     sup_si = vnet_get_sup_sw_interface (vnm, si->sw_if_index);
    1260           0 :     ei = ethernet_get_interface (em, sup_si->hw_if_index);
    1261             : 
    1262           0 :     vlib_cli_output (vm, "%U (%s):",
    1263             :                      format_vnet_sw_if_index_name, vnm, si->sw_if_index,
    1264           0 :                      (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
    1265             :                      "up" : "dn");
    1266             : 
    1267           0 :     if (ei && ei->secondary_addrs)
    1268             :       {
    1269             :         ethernet_interface_address_t *sec_addr;
    1270             : 
    1271           0 :         vec_foreach (sec_addr, ei->secondary_addrs)
    1272             :         {
    1273           0 :           vlib_cli_output (vm, "  %U", format_mac_address_t, &sec_addr->mac);
    1274             :         }
    1275             :       }
    1276             :   }
    1277             : 
    1278           0 :   vec_free (sorted_sis);
    1279           0 :   return 0;
    1280             : }
    1281             : 
    1282             : /*?
    1283             :  * This command is used to display interface secondary mac addresses.
    1284             :  *
    1285             :  * @cliexpar
    1286             :  * Example of how to display interface secondary mac addresses:
    1287             :  * @cliexstart{show interface secondary-mac-address}
    1288             :  * @cliexend
    1289             : ?*/
    1290             : /* *INDENT-OFF* */
    1291      272887 : VLIB_CLI_COMMAND (show_interface_sec_mac_addr, static) = {
    1292             :   .path = "show interface secondary-mac-address",
    1293             :   .short_help = "show interface secondary-mac-address [<interface>]",
    1294             :   .function = show_interface_sec_mac_addr_fn,
    1295             : };
    1296             : /* *INDENT-ON* */
    1297             : 
    1298             : static clib_error_t *
    1299           0 : interface_add_del_mac_address (vlib_main_t * vm, unformat_input_t * input,
    1300             :                                vlib_cli_command_t * cmd)
    1301             : {
    1302           0 :   vnet_main_t *vnm = vnet_get_main ();
    1303           0 :   vnet_sw_interface_t *si = NULL;
    1304           0 :   clib_error_t *error = 0;
    1305           0 :   u32 sw_if_index = ~0;
    1306           0 :   u8 mac[6] = { 0 };
    1307             :   u8 is_add, is_del;
    1308             : 
    1309           0 :   is_add = is_del = 0;
    1310             : 
    1311           0 :   if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
    1312             :     {
    1313           0 :       error = clib_error_return (0, "unknown interface `%U'",
    1314             :                                  format_unformat_error, input);
    1315           0 :       goto done;
    1316             :     }
    1317           0 :   if (!unformat_user (input, unformat_ethernet_address, mac))
    1318             :     {
    1319           0 :       error = clib_error_return (0, "expected mac address `%U'",
    1320             :                                  format_unformat_error, input);
    1321           0 :       goto done;
    1322             :     }
    1323             : 
    1324           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1325             :     {
    1326           0 :       if (unformat (input, "add"))
    1327           0 :         is_add = 1;
    1328           0 :       else if (unformat (input, "del"))
    1329           0 :         is_del = 1;
    1330             :       else
    1331           0 :         break;
    1332             :     }
    1333             : 
    1334           0 :   if (is_add == is_del)
    1335             :     {
    1336           0 :       error = clib_error_return (0, "must choose one of add or del");
    1337           0 :       goto done;
    1338             :     }
    1339             : 
    1340           0 :   si = vnet_get_sw_interface (vnm, sw_if_index);
    1341             :   error =
    1342           0 :     vnet_hw_interface_add_del_mac_address (vnm, si->hw_if_index, mac, is_add);
    1343             : 
    1344           0 : done:
    1345           0 :   return error;
    1346             : }
    1347             : 
    1348             : /*?
    1349             :  * The '<em>set interface secondary-mac-address </em>' command allows adding
    1350             :  * or deleting extra MAC addresses on a given interface without changing the
    1351             :  * default MAC address. This could allow packets sent to these MAC addresses
    1352             :  * to be received without setting the interface to promiscuous mode.
    1353             :  * Not all interfaces support this operation. The ones that do are mostly
    1354             :  * hardware NICs, though virtio does also.
    1355             :  *
    1356             :  * @cliexpar
    1357             :  * @parblock
    1358             :  * Example of how to add a secondary MAC Address on an interface:
    1359             :  * @cliexcmd{set interface secondary-mac-address GigabitEthernet0/8/0 aa:bb:cc:dd:ee:01 add}
    1360             :  * Example of how to delete a secondary MAC address from an interface:
    1361             :  * @cliexcmd{set interface secondary-mac-address GigabitEthernet0/8/0 aa:bb:cc:dd:ee:01 del}
    1362             :  * @endparblock
    1363             : ?*/
    1364             : /* *INDENT-OFF* */
    1365      272887 : VLIB_CLI_COMMAND (interface_add_del_mac_address_cmd, static) = {
    1366             :   .path = "set interface secondary-mac-address",
    1367             :   .short_help = "set interface secondary-mac-address <interface> <mac-address> [(add|del)]",
    1368             :   .function = interface_add_del_mac_address,
    1369             : };
    1370             : /* *INDENT-ON* */
    1371             : 
    1372             : static clib_error_t *
    1373           0 : set_interface_mac_address (vlib_main_t * vm, unformat_input_t * input,
    1374             :                            vlib_cli_command_t * cmd)
    1375             : {
    1376           0 :   vnet_main_t *vnm = vnet_get_main ();
    1377           0 :   vnet_sw_interface_t *si = NULL;
    1378           0 :   clib_error_t *error = 0;
    1379           0 :   u32 sw_if_index = ~0;
    1380           0 :   u8 mac[6] = { 0 };
    1381             : 
    1382           0 :   if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
    1383             :     {
    1384           0 :       error = clib_error_return (0, "unknown interface `%U'",
    1385             :                                  format_unformat_error, input);
    1386           0 :       goto done;
    1387             :     }
    1388           0 :   if (!unformat_user (input, unformat_ethernet_address, mac))
    1389             :     {
    1390           0 :       error = clib_error_return (0, "expected mac address `%U'",
    1391             :                                  format_unformat_error, input);
    1392           0 :       goto done;
    1393             :     }
    1394           0 :   si = vnet_get_sw_interface (vnm, sw_if_index);
    1395           0 :   error = vnet_hw_interface_change_mac_address (vnm, si->hw_if_index, mac);
    1396           0 : done:
    1397           0 :   return error;
    1398             : }
    1399             : 
    1400             : /*?
    1401             :  * The '<em>set interface mac address </em>' command allows to set MAC address of given interface.
    1402             :  * In case of NIC interfaces the one has to support MAC address change. A side effect of MAC address
    1403             :  * change are changes of MAC addresses in FIB tables (ipv4 and ipv6).
    1404             :  *
    1405             :  * @cliexpar
    1406             :  * @parblock
    1407             :  * Example of how to change MAC Address of interface:
    1408             :  * @cliexcmd{set interface mac address GigabitEthernet0/8/0 aa:bb:cc:dd:ee:01}
    1409             :  * @cliexcmd{set interface mac address host-vpp0 aa:bb:cc:dd:ee:02}
    1410             :  * @cliexcmd{set interface mac address tap-0 aa:bb:cc:dd:ee:03}
    1411             :  * @cliexcmd{set interface mac address pg0 aa:bb:cc:dd:ee:04}
    1412             :  * @endparblock
    1413             : ?*/
    1414             : /* *INDENT-OFF* */
    1415      272887 : VLIB_CLI_COMMAND (set_interface_mac_address_cmd, static) = {
    1416             :   .path = "set interface mac address",
    1417             :   .short_help = "set interface mac address <interface> <mac-address>",
    1418             :   .function = set_interface_mac_address,
    1419             : };
    1420             : /* *INDENT-ON* */
    1421             : 
    1422             : static clib_error_t *
    1423           0 : set_tag (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
    1424             : {
    1425           0 :   vnet_main_t *vnm = vnet_get_main ();
    1426           0 :   u32 sw_if_index = ~0;
    1427           0 :   u8 *tag = 0;
    1428             : 
    1429           0 :   if (!unformat (input, "%U %s", unformat_vnet_sw_interface,
    1430             :                  vnm, &sw_if_index, &tag))
    1431           0 :     return clib_error_return (0, "unknown input `%U'",
    1432             :                               format_unformat_error, input);
    1433             : 
    1434           0 :   vnet_set_sw_interface_tag (vnm, tag, sw_if_index);
    1435             : 
    1436           0 :   return 0;
    1437             : }
    1438             : 
    1439             : /* *INDENT-OFF* */
    1440      272887 : VLIB_CLI_COMMAND (set_tag_command, static) = {
    1441             :   .path = "set interface tag",
    1442             :   .short_help = "set interface tag <interface> <tag>",
    1443             :   .function = set_tag,
    1444             : };
    1445             : /* *INDENT-ON* */
    1446             : 
    1447             : static clib_error_t *
    1448           0 : clear_tag (vlib_main_t * vm, unformat_input_t * input,
    1449             :            vlib_cli_command_t * cmd)
    1450             : {
    1451           0 :   vnet_main_t *vnm = vnet_get_main ();
    1452           0 :   u32 sw_if_index = ~0;
    1453             : 
    1454           0 :   if (!unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
    1455           0 :     return clib_error_return (0, "unknown input `%U'",
    1456             :                               format_unformat_error, input);
    1457             : 
    1458           0 :   vnet_clear_sw_interface_tag (vnm, sw_if_index);
    1459             : 
    1460           0 :   return 0;
    1461             : }
    1462             : 
    1463             : /* *INDENT-OFF* */
    1464      272887 : VLIB_CLI_COMMAND (clear_tag_command, static) = {
    1465             :   .path = "clear interface tag",
    1466             :   .short_help = "clear interface tag <interface>",
    1467             :   .function = clear_tag,
    1468             : };
    1469             : /* *INDENT-ON* */
    1470             : 
    1471             : static clib_error_t *
    1472           0 : set_ip_directed_broadcast (vlib_main_t * vm,
    1473             :                            unformat_input_t * input, vlib_cli_command_t * cmd)
    1474             : {
    1475           0 :   vnet_main_t *vnm = vnet_get_main ();
    1476           0 :   u32 sw_if_index = ~0;
    1477           0 :   u8 enable = 0;
    1478             : 
    1479           0 :   if (!unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index));
    1480           0 :   else if (unformat (input, "enable"))
    1481           0 :     enable = 1;
    1482           0 :   else if (unformat (input, "disable"))
    1483           0 :     enable = 0;
    1484             :   else
    1485           0 :     return clib_error_return (0, "unknown input: `%U'",
    1486             :                               format_unformat_error, input);
    1487             : 
    1488           0 :   if (~0 == sw_if_index)
    1489           0 :     return clib_error_return (0, "specify an interface: `%U'",
    1490             :                               format_unformat_error, input);
    1491             : 
    1492           0 :   vnet_sw_interface_ip_directed_broadcast (vnm, sw_if_index, enable);
    1493             : 
    1494           0 :   return 0;
    1495             : }
    1496             : 
    1497             : /*?
    1498             :  * This command is used to enable/disable IP directed broadcast
    1499             :  * If directed broadcast is enabled a packet sent to the interface's
    1500             :  * subnet broadcast address will be sent L2 broadcast on the interface,
    1501             :  * otherwise it is dropped.
    1502             :  ?*/
    1503             : /* *INDENT-OFF* */
    1504      272887 : VLIB_CLI_COMMAND (set_ip_directed_broadcast_command, static) = {
    1505             :   .path = "set interface ip directed-broadcast",
    1506             :   .short_help = "set interface enable <interface> <enable|disable>",
    1507             :   .function = set_ip_directed_broadcast,
    1508             : };
    1509             : /* *INDENT-ON* */
    1510             : 
    1511             : clib_error_t *
    1512           0 : set_hw_interface_change_rx_mode (vnet_main_t * vnm, u32 hw_if_index,
    1513             :                                  u8 queue_id_valid, u32 queue_id,
    1514             :                                  vnet_hw_if_rx_mode mode)
    1515             : {
    1516           0 :   clib_error_t *error = 0;
    1517             :   vnet_hw_interface_t *hw;
    1518           0 :   u32 *queue_indices = 0;
    1519             : 
    1520           0 :   hw = vnet_get_hw_interface (vnm, hw_if_index);
    1521             : 
    1522           0 :   if (queue_id_valid)
    1523             :     {
    1524             :       u32 queue_index;
    1525             :       queue_index =
    1526           0 :         vnet_hw_if_get_rx_queue_index_by_id (vnm, hw_if_index, queue_id);
    1527           0 :       if (queue_index == ~0)
    1528           0 :         return clib_error_return (0, "unknown queue %u on interface %s",
    1529             :                                   queue_id, hw->name);
    1530           0 :       vec_add1 (queue_indices, queue_index);
    1531             :     }
    1532             :   else
    1533           0 :     queue_indices = hw->rx_queue_indices;
    1534             : 
    1535           0 :   for (int i = 0; i < vec_len (queue_indices); i++)
    1536             :     {
    1537           0 :       int rv = vnet_hw_if_set_rx_queue_mode (vnm, queue_indices[i], mode);
    1538           0 :       if (rv)
    1539             :         {
    1540           0 :           error = clib_error_return (
    1541             :             0, "unable to set rx-mode on interface %v queue-id %u.\n",
    1542             :             hw->name, queue_id);
    1543           0 :           goto done;
    1544             :         }
    1545             :     }
    1546             : 
    1547           0 : done:
    1548           0 :   if (queue_indices != hw->rx_queue_indices)
    1549           0 :     vec_free (queue_indices);
    1550           0 :   vnet_hw_if_update_runtime_data (vnm, hw_if_index);
    1551           0 :   return error;
    1552             : }
    1553             : 
    1554             : static clib_error_t *
    1555           0 : set_interface_rx_mode (vlib_main_t * vm, unformat_input_t * input,
    1556             :                        vlib_cli_command_t * cmd)
    1557             : {
    1558           0 :   clib_error_t *error = 0;
    1559           0 :   unformat_input_t _line_input, *line_input = &_line_input;
    1560           0 :   vnet_main_t *vnm = vnet_get_main ();
    1561           0 :   u32 hw_if_index = (u32) ~ 0;
    1562           0 :   u32 queue_id = (u32) ~ 0;
    1563           0 :   vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
    1564           0 :   u8 queue_id_valid = 0;
    1565             : 
    1566           0 :   if (!unformat_user (input, unformat_line_input, line_input))
    1567           0 :     return 0;
    1568             : 
    1569           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    1570             :     {
    1571           0 :       if (unformat
    1572             :           (line_input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
    1573             :         ;
    1574           0 :       else if (unformat (line_input, "queue %d", &queue_id))
    1575           0 :         queue_id_valid = 1;
    1576           0 :       else if (unformat (line_input, "polling"))
    1577           0 :         mode = VNET_HW_IF_RX_MODE_POLLING;
    1578           0 :       else if (unformat (line_input, "interrupt"))
    1579           0 :         mode = VNET_HW_IF_RX_MODE_INTERRUPT;
    1580           0 :       else if (unformat (line_input, "adaptive"))
    1581           0 :         mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
    1582             :       else
    1583             :         {
    1584           0 :           error = clib_error_return (0, "parse error: '%U'",
    1585             :                                      format_unformat_error, line_input);
    1586           0 :           unformat_free (line_input);
    1587           0 :           return error;
    1588             :         }
    1589             :     }
    1590             : 
    1591           0 :   unformat_free (line_input);
    1592             : 
    1593           0 :   if (hw_if_index == (u32) ~ 0)
    1594           0 :     return clib_error_return (0, "please specify valid interface name");
    1595             : 
    1596           0 :   if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
    1597           0 :     return clib_error_return (0, "please specify valid rx-mode");
    1598             : 
    1599           0 :   error = set_hw_interface_change_rx_mode (vnm, hw_if_index, queue_id_valid,
    1600             :                                            queue_id, mode);
    1601             : 
    1602           0 :   return (error);
    1603             : }
    1604             : 
    1605             : /*?
    1606             :  * This command is used to assign the RX packet processing mode (polling,
    1607             :  * interrupt, adaptive) of the a given interface, and optionally a
    1608             :  * given queue. If the '<em>queue</em>' is not provided, the '<em>mode</em>'
    1609             :  * is applied to all queues of the interface. Not all interfaces support
    1610             :  * all modes. To display the current rx-mode use the command
    1611             :  * '<em>show interface rx-placement</em>'.
    1612             :  *
    1613             :  * @cliexpar
    1614             :  * Example of how to assign rx-mode to all queues on an interface:
    1615             :  * @cliexcmd{set interface rx-mode VirtualEthernet0/0/12 polling}
    1616             :  * Example of how to assign rx-mode to one queue of an interface:
    1617             :  * @cliexcmd{set interface rx-mode VirtualEthernet0/0/12 queue 0 interrupt}
    1618             :  * Example of how to display the rx-mode of all interfaces:
    1619             :  * @cliexstart{show interface rx-placement}
    1620             :  * Thread 1 (vpp_wk_0):
    1621             :  *   node dpdk-input:
    1622             :  *     GigabitEthernet7/0/0 queue 0 (polling)
    1623             :  *   node vhost-user-input:
    1624             :  *     VirtualEthernet0/0/12 queue 0 (interrupt)
    1625             :  *     VirtualEthernet0/0/12 queue 2 (polling)
    1626             :  *     VirtualEthernet0/0/13 queue 0 (polling)
    1627             :  *     VirtualEthernet0/0/13 queue 2 (polling)
    1628             :  * Thread 2 (vpp_wk_1):
    1629             :  *   node dpdk-input:
    1630             :  *     GigabitEthernet7/0/1 queue 0 (polling)
    1631             :  *   node vhost-user-input:
    1632             :  *     VirtualEthernet0/0/12 queue 1 (polling)
    1633             :  *     VirtualEthernet0/0/12 queue 3 (polling)
    1634             :  *     VirtualEthernet0/0/13 queue 1 (polling)
    1635             :  *     VirtualEthernet0/0/13 queue 3 (polling)
    1636             :  * @cliexend
    1637             : ?*/
    1638             : /* *INDENT-OFF* */
    1639      272887 : VLIB_CLI_COMMAND (cmd_set_if_rx_mode,static) = {
    1640             :     .path = "set interface rx-mode",
    1641             :     .short_help = "set interface rx-mode <interface> [queue <n>] [polling | interrupt | adaptive]",
    1642             :     .function = set_interface_rx_mode,
    1643             : };
    1644             : /* *INDENT-ON* */
    1645             : 
    1646             : static clib_error_t *
    1647           0 : show_interface_rx_placement_fn (vlib_main_t * vm, unformat_input_t * input,
    1648             :                                 vlib_cli_command_t * cmd)
    1649             : {
    1650           0 :   u8 *s = 0;
    1651           0 :   vnet_main_t *vnm = vnet_get_main ();
    1652           0 :   vnet_hw_if_rx_queue_t **all_queues = 0;
    1653             :   vnet_hw_if_rx_queue_t **qptr;
    1654             :   vnet_hw_if_rx_queue_t *q;
    1655           0 :   pool_foreach (q, vnm->interface_main.hw_if_rx_queues)
    1656           0 :     vec_add1 (all_queues, q);
    1657           0 :   vec_sort_with_function (all_queues, vnet_hw_if_rxq_cmp_cli_api);
    1658           0 :   u32 prev_node = ~0;
    1659             : 
    1660           0 :   vec_foreach (qptr, all_queues)
    1661             :     {
    1662           0 :       u32 current_thread = qptr[0]->thread_index;
    1663           0 :       u32 hw_if_index = qptr[0]->hw_if_index;
    1664           0 :       vnet_hw_interface_t *hw_if = vnet_get_hw_interface (vnm, hw_if_index);
    1665           0 :       u32 current_node = hw_if->input_node_index;
    1666           0 :       if (current_node != prev_node)
    1667           0 :         s = format (s, " node %U:\n", format_vlib_node_name, vm, current_node);
    1668           0 :       s = format (s, "    %U queue %u (%U)\n", format_vnet_sw_if_index_name,
    1669           0 :                   vnm, hw_if->sw_if_index, qptr[0]->queue_id,
    1670           0 :                   format_vnet_hw_if_rx_mode, qptr[0]->mode);
    1671           0 :       if (qptr == all_queues + vec_len (all_queues) - 1 ||
    1672           0 :           current_thread != qptr[1]->thread_index)
    1673             :         {
    1674           0 :           vlib_cli_output (vm, "Thread %u (%s):\n%v", current_thread,
    1675           0 :                            vlib_worker_threads[current_thread].name, s);
    1676           0 :           vec_reset_length (s);
    1677             :         }
    1678           0 :       prev_node = current_node;
    1679             :     }
    1680           0 :   vec_free (s);
    1681           0 :   vec_free (all_queues);
    1682           0 :   return 0;
    1683             : }
    1684             : 
    1685             : /*?
    1686             :  * This command is used to display the interface and queue worker
    1687             :  * thread placement.
    1688             :  *
    1689             :  * @cliexpar
    1690             :  * Example of how to display the interface placement:
    1691             :  * @cliexstart{show interface rx-placement}
    1692             :  * Thread 1 (vpp_wk_0):
    1693             :  *   node dpdk-input:
    1694             :  *     GigabitEthernet7/0/0 queue 0 (polling)
    1695             :  *   node vhost-user-input:
    1696             :  *     VirtualEthernet0/0/12 queue 0 (polling)
    1697             :  *     VirtualEthernet0/0/12 queue 2 (polling)
    1698             :  *     VirtualEthernet0/0/13 queue 0 (polling)
    1699             :  *     VirtualEthernet0/0/13 queue 2 (polling)
    1700             :  * Thread 2 (vpp_wk_1):
    1701             :  *   node dpdk-input:
    1702             :  *     GigabitEthernet7/0/1 queue 0 (polling)
    1703             :  *   node vhost-user-input:
    1704             :  *     VirtualEthernet0/0/12 queue 1 (polling)
    1705             :  *     VirtualEthernet0/0/12 queue 3 (polling)
    1706             :  *     VirtualEthernet0/0/13 queue 1 (polling)
    1707             :  *     VirtualEthernet0/0/13 queue 3 (polling)
    1708             :  * @cliexend
    1709             : ?*/
    1710             : /* *INDENT-OFF* */
    1711      272887 : VLIB_CLI_COMMAND (show_interface_rx_placement, static) = {
    1712             :   .path = "show interface rx-placement",
    1713             :   .short_help = "show interface rx-placement",
    1714             :   .function = show_interface_rx_placement_fn,
    1715             : };
    1716             : /* *INDENT-ON* */
    1717             : clib_error_t *
    1718           0 : set_hw_interface_rx_placement (u32 hw_if_index, u32 queue_id,
    1719             :                                u32 thread_index, u8 is_main)
    1720             : {
    1721           0 :   vnet_main_t *vnm = vnet_get_main ();
    1722           0 :   vnet_device_main_t *vdm = &vnet_device_main;
    1723             :   vnet_hw_interface_t *hw;
    1724             :   u32 queue_index;
    1725             : 
    1726           0 :   if (is_main)
    1727           0 :     thread_index = 0;
    1728             :   else
    1729           0 :     thread_index += vdm->first_worker_thread_index;
    1730             : 
    1731           0 :   if (thread_index > vdm->last_worker_thread_index)
    1732           0 :     return clib_error_return (0,
    1733             :                               "please specify valid worker thread or main");
    1734             : 
    1735           0 :   hw = vnet_get_hw_interface (vnm, hw_if_index);
    1736             : 
    1737             :   queue_index =
    1738           0 :     vnet_hw_if_get_rx_queue_index_by_id (vnm, hw_if_index, queue_id);
    1739           0 :   if (queue_index == ~0)
    1740           0 :     return clib_error_return (0, "unknown queue %u on interface %s", queue_id,
    1741             :                               hw->name);
    1742           0 :   vnet_hw_if_set_rx_queue_thread_index (vnm, queue_index, thread_index);
    1743           0 :   vnet_hw_if_update_runtime_data (vnm, hw_if_index);
    1744           0 :   return 0;
    1745             : }
    1746             : 
    1747             : static clib_error_t *
    1748           0 : set_interface_rx_placement (vlib_main_t *vm, unformat_input_t *input,
    1749             :                             vlib_cli_command_t *cmd)
    1750             : {
    1751           0 :   clib_error_t *error = 0;
    1752           0 :   unformat_input_t _line_input, *line_input = &_line_input;
    1753           0 :   vnet_main_t *vnm = vnet_get_main ();
    1754           0 :   u32 hw_if_index = (u32) ~ 0;
    1755           0 :   u32 queue_id = (u32) 0;
    1756           0 :   u32 thread_index = (u32) ~ 0;
    1757           0 :   u8 is_main = 0;
    1758             : 
    1759           0 :   if (!unformat_user (input, unformat_line_input, line_input))
    1760           0 :     return 0;
    1761             : 
    1762           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    1763             :     {
    1764           0 :       if (unformat
    1765             :           (line_input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
    1766             :         ;
    1767           0 :       else if (unformat (line_input, "queue %d", &queue_id))
    1768             :         ;
    1769           0 :       else if (unformat (line_input, "main", &thread_index))
    1770           0 :         is_main = 1;
    1771           0 :       else if (unformat (line_input, "worker %d", &thread_index))
    1772             :         ;
    1773             :       else
    1774             :         {
    1775           0 :           error = clib_error_return (0, "parse error: '%U'",
    1776             :                                      format_unformat_error, line_input);
    1777           0 :           unformat_free (line_input);
    1778           0 :           return error;
    1779             :         }
    1780             :     }
    1781             : 
    1782           0 :   unformat_free (line_input);
    1783             : 
    1784           0 :   if (hw_if_index == (u32) ~ 0)
    1785           0 :     return clib_error_return (0, "please specify valid interface name");
    1786             : 
    1787           0 :   error = set_hw_interface_rx_placement (hw_if_index, queue_id, thread_index,
    1788             :                                          is_main);
    1789             : 
    1790           0 :   return (error);
    1791             : }
    1792             : 
    1793             : /*?
    1794             :  * This command is used to assign a given interface, and optionally a
    1795             :  * given queue, to a different thread. If the '<em>queue</em>' is not provided,
    1796             :  * it defaults to 0. The '<em>worker</em>' parameter is zero based and the index
    1797             :  * in the thread name, for example, 0 in the thread name '<em>vpp_wk_0</em>'.
    1798             :  *
    1799             :  * @cliexpar
    1800             :  * Example of how to display the interface placement:
    1801             :  * @cliexstart{show interface rx-placement}
    1802             :  * Thread 1 (vpp_wk_0):
    1803             :  *   node dpdk-input:
    1804             :  *     GigabitEthernet7/0/0 queue 0 (polling)
    1805             :  *   node vhost-user-input:
    1806             :  *     VirtualEthernet0/0/12 queue 0 (polling)
    1807             :  *     VirtualEthernet0/0/12 queue 2 (polling)
    1808             :  *     VirtualEthernet0/0/13 queue 0 (polling)
    1809             :  *     VirtualEthernet0/0/13 queue 2 (polling)
    1810             :  * Thread 2 (vpp_wk_1):
    1811             :  *   node dpdk-input:
    1812             :  *     GigabitEthernet7/0/1 queue 0 (polling)
    1813             :  *   node vhost-user-input:
    1814             :  *     VirtualEthernet0/0/12 queue 1 (polling)
    1815             :  *     VirtualEthernet0/0/12 queue 3 (polling)
    1816             :  *     VirtualEthernet0/0/13 queue 1 (polling)
    1817             :  *     VirtualEthernet0/0/13 queue 3 (polling)
    1818             :  * @cliexend
    1819             :  * Example of how to assign a interface and queue to a worker thread:
    1820             :  * @cliexcmd{set interface rx-placement VirtualEthernet0/0/12 queue 1 worker 0}
    1821             :  * Example of how to display the interface placement:
    1822             :  * @cliexstart{show interface rx-placement}
    1823             :  * Thread 1 (vpp_wk_0):
    1824             :  *   node dpdk-input:
    1825             :  *     GigabitEthernet7/0/0 queue 0 (polling)
    1826             :  *   node vhost-user-input:
    1827             :  *     VirtualEthernet0/0/12 queue 0 (polling)
    1828             :  *     VirtualEthernet0/0/12 queue 1 (polling)
    1829             :  *     VirtualEthernet0/0/12 queue 2 (polling)
    1830             :  *     VirtualEthernet0/0/13 queue 0 (polling)
    1831             :  *     VirtualEthernet0/0/13 queue 2 (polling)
    1832             :  * Thread 2 (vpp_wk_1):
    1833             :  *   node dpdk-input:
    1834             :  *     GigabitEthernet7/0/1 queue 0 (polling)
    1835             :  *   node vhost-user-input:
    1836             :  *     VirtualEthernet0/0/12 queue 3 (polling)
    1837             :  *     VirtualEthernet0/0/13 queue 1 (polling)
    1838             :  *     VirtualEthernet0/0/13 queue 3 (polling)
    1839             :  * @cliexend
    1840             : ?*/
    1841             : /* *INDENT-OFF* */
    1842      272887 : VLIB_CLI_COMMAND (cmd_set_if_rx_placement,static) = {
    1843             :     .path = "set interface rx-placement",
    1844             :     .short_help = "set interface rx-placement <interface> [queue <n>] "
    1845             :       "[worker <n> | main]",
    1846             :     .function = set_interface_rx_placement,
    1847             :     .is_mp_safe = 1,
    1848             : };
    1849             : /* *INDENT-ON* */
    1850             : 
    1851             : int
    1852           0 : set_hw_interface_tx_queue (u32 hw_if_index, u32 queue_id, uword *bitmap)
    1853             : {
    1854           0 :   vnet_main_t *vnm = vnet_get_main ();
    1855           0 :   vlib_thread_main_t *vtm = vlib_get_thread_main ();
    1856             :   vnet_hw_if_tx_queue_t *txq;
    1857             :   u32 queue_index;
    1858             :   u32 thread_index;
    1859             : 
    1860             :   /* highest set bit in bitmap should not exceed last worker thread index */
    1861           0 :   thread_index = clib_bitmap_last_set (bitmap);
    1862           0 :   if ((thread_index != ~0) && (thread_index >= vtm->n_vlib_mains))
    1863           0 :     return VNET_API_ERROR_INVALID_VALUE;
    1864             : 
    1865             :   queue_index =
    1866           0 :     vnet_hw_if_get_tx_queue_index_by_id (vnm, hw_if_index, queue_id);
    1867           0 :   if (queue_index == ~0)
    1868           0 :     return VNET_API_ERROR_INVALID_QUEUE;
    1869             : 
    1870           0 :   txq = vnet_hw_if_get_tx_queue (vnm, queue_index);
    1871             : 
    1872             :   // free the existing bitmap
    1873           0 :   if (clib_bitmap_count_set_bits (txq->threads))
    1874             :     {
    1875           0 :       txq->shared_queue = 0;
    1876           0 :       clib_bitmap_free (txq->threads);
    1877             :     }
    1878             : 
    1879           0 :   clib_bitmap_foreach (thread_index, bitmap)
    1880           0 :     vnet_hw_if_tx_queue_assign_thread (vnm, queue_index, thread_index);
    1881             : 
    1882           0 :   vnet_hw_if_update_runtime_data (vnm, hw_if_index);
    1883           0 :   return 0;
    1884             : }
    1885             : 
    1886             : static clib_error_t *
    1887           0 : set_interface_tx_queue (vlib_main_t *vm, unformat_input_t *input,
    1888             :                         vlib_cli_command_t *cmd)
    1889             : {
    1890           0 :   clib_error_t *error = 0;
    1891           0 :   unformat_input_t _line_input, *line_input = &_line_input;
    1892           0 :   vnet_main_t *vnm = vnet_get_main ();
    1893           0 :   u32 hw_if_index = (u32) ~0;
    1894           0 :   u32 queue_id = (u32) 0;
    1895           0 :   uword *bitmap = 0;
    1896           0 :   int rv = 0;
    1897             : 
    1898           0 :   if (!unformat_user (input, unformat_line_input, line_input))
    1899           0 :     return 0;
    1900             : 
    1901           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    1902             :     {
    1903           0 :       if (unformat (line_input, "%U", unformat_vnet_hw_interface, vnm,
    1904             :                     &hw_if_index))
    1905             :         ;
    1906           0 :       else if (unformat (line_input, "queue %d", &queue_id))
    1907             :         ;
    1908           0 :       else if (unformat (line_input, "threads %U", unformat_bitmap_list,
    1909             :                          &bitmap))
    1910             :         ;
    1911             :       else
    1912             :         {
    1913           0 :           error = clib_error_return (0, "parse error: '%U'",
    1914             :                                      format_unformat_error, line_input);
    1915           0 :           unformat_free (line_input);
    1916           0 :           return error;
    1917             :         }
    1918             :     }
    1919             : 
    1920           0 :   unformat_free (line_input);
    1921             : 
    1922           0 :   if (hw_if_index == (u32) ~0)
    1923             :     {
    1924           0 :       error = clib_error_return (0, "please specify valid interface name");
    1925           0 :       goto error;
    1926             :     }
    1927             : 
    1928           0 :   rv = set_hw_interface_tx_queue (hw_if_index, queue_id, bitmap);
    1929             : 
    1930           0 :   switch (rv)
    1931             :     {
    1932           0 :     case VNET_API_ERROR_INVALID_VALUE:
    1933           0 :       error = clib_error_return (
    1934             :         0, "please specify valid thread(s) - last thread index %u",
    1935             :         clib_bitmap_last_set (bitmap));
    1936           0 :       break;
    1937           0 :     case VNET_API_ERROR_INVALID_QUEUE:
    1938           0 :       error = clib_error_return (
    1939             :         0, "unknown queue %u on interface %s", queue_id,
    1940             :         vnet_get_hw_interface (vnet_get_main (), hw_if_index)->name);
    1941           0 :       break;
    1942           0 :     default:
    1943           0 :       break;
    1944             :     }
    1945             : 
    1946           0 : error:
    1947           0 :   clib_bitmap_free (bitmap);
    1948           0 :   return (error);
    1949             : }
    1950             : 
    1951      272887 : VLIB_CLI_COMMAND (cmd_set_if_tx_queue, static) = {
    1952             :   .path = "set interface tx-queue",
    1953             :   .short_help = "set interface tx-queue <interface> queue <n> "
    1954             :                 "[threads <list>]",
    1955             :   .function = set_interface_tx_queue,
    1956             :   .is_mp_safe = 1,
    1957             : };
    1958             : 
    1959             : clib_error_t *
    1960           0 : set_interface_rss_queues (vlib_main_t * vm, u32 hw_if_index,
    1961             :                           clib_bitmap_t * bitmap)
    1962             : {
    1963           0 :   vnet_main_t *vnm = vnet_get_main ();
    1964           0 :   vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
    1965             : 
    1966           0 :   return vnet_hw_interface_set_rss_queues (vnm, hi, bitmap);
    1967             : }
    1968             : 
    1969             : static clib_error_t *
    1970           0 : set_interface_rss_queues_fn (vlib_main_t * vm,
    1971             :                              unformat_input_t * input,
    1972             :                              vlib_cli_command_t * cmd)
    1973             : {
    1974           0 :   clib_error_t *error = 0;
    1975           0 :   unformat_input_t _line_input, *line_input = &_line_input;
    1976           0 :   vnet_main_t *vnm = vnet_get_main ();
    1977           0 :   u32 hw_if_index = (u32) ~ 0;
    1978           0 :   clib_bitmap_t *bitmap = NULL;
    1979             : 
    1980           0 :   if (!unformat_user (input, unformat_line_input, line_input))
    1981           0 :     return 0;
    1982             : 
    1983           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    1984             :     {
    1985           0 :       if (unformat
    1986             :           (line_input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
    1987             :         ;
    1988             :       else
    1989           0 :         if (unformat (line_input, "list %U", unformat_bitmap_list, &bitmap))
    1990             :         ;
    1991             :       else
    1992             :         {
    1993           0 :           error = clib_error_return (0, "parse error: '%U'",
    1994             :                                      format_unformat_error, line_input);
    1995           0 :           unformat_free (line_input);
    1996           0 :           goto done;
    1997             :         }
    1998             :     }
    1999             : 
    2000           0 :   unformat_free (line_input);
    2001             : 
    2002           0 :   if (hw_if_index == (u32) ~ 0)
    2003             :     {
    2004           0 :       error = clib_error_return (0, "please specify valid interface name");
    2005           0 :       goto done;
    2006             :     }
    2007             : 
    2008           0 :   if (bitmap == NULL)
    2009             :     {
    2010           0 :       error = clib_error_return (0, "please specify the valid rss queues");
    2011           0 :       goto done;
    2012             :     }
    2013             : 
    2014           0 :   error = set_interface_rss_queues (vm, hw_if_index, bitmap);
    2015             : 
    2016           0 : done:
    2017           0 :   if (bitmap)
    2018           0 :     clib_bitmap_free (bitmap);
    2019             : 
    2020           0 :   return (error);
    2021             : }
    2022             : 
    2023             : /*?
    2024             :  * This command is used to set the rss queues of a given interface
    2025             :  * Not all the interfaces support this operation.
    2026             :  * To display the current rss queues, use the command
    2027             :  * '<em>show hardware-interfaces</em>'.
    2028             :  *
    2029             :  * @cliexpar
    2030             :  * Example of how to set the rss queues to 0,2-5,7 of an interface:
    2031             :  * @cliexstart{set interface rss queues VirtualFunctionEthernet18/1/0 list 0,2-5,7}
    2032             :  * @cliexend
    2033             : ?*/
    2034             : /* *INDENT-OFF* */
    2035      272887 : VLIB_CLI_COMMAND (cmd_set_interface_rss_queues,static) = {
    2036             :     .path = "set interface rss queues",
    2037             :     .short_help = "set interface rss queues <interface> <list <queue-list>>",
    2038             :     .function = set_interface_rss_queues_fn,
    2039             : };
    2040             : /* *INDENT-ON* */
    2041             : 
    2042             : static u8 *
    2043           1 : format_vnet_pcap (u8 * s, va_list * args)
    2044             : {
    2045           1 :   vnet_pcap_t *pp = va_arg (*args, vnet_pcap_t *);
    2046           1 :   int type = va_arg (*args, int);
    2047           1 :   int printed = 0;
    2048             : 
    2049           1 :   if (type == 0)
    2050             :     {
    2051           1 :       if (pp->pcap_rx_enable)
    2052             :         {
    2053           1 :           s = format (s, "rx");
    2054           1 :           printed = 1;
    2055             :         }
    2056           1 :       if (pp->pcap_tx_enable)
    2057             :         {
    2058           1 :           if (printed)
    2059           1 :             s = format (s, " and ");
    2060           1 :           s = format (s, "tx");
    2061           1 :           printed = 1;
    2062             :         }
    2063           1 :       if (pp->pcap_drop_enable)
    2064             :         {
    2065           0 :           if (printed)
    2066           0 :             s = format (s, " and ");
    2067           0 :           s = format (s, "drop");
    2068           0 :           printed = 1;
    2069             :         }
    2070           1 :       return s;
    2071             :     }
    2072           0 :   s = format (s, "unknown type %d!", type);
    2073           0 :   return s;
    2074             : }
    2075             : 
    2076             : 
    2077             : int
    2078          15 : vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a)
    2079             : {
    2080          15 :   vlib_main_t *vm = vlib_get_main ();
    2081          15 :   vnet_main_t *vnm = vnet_get_main ();
    2082          15 :   vnet_pcap_t *pp = &vnm->pcap;
    2083          15 :   pcap_main_t *pm = &pp->pcap_main;
    2084          15 :   vnet_classify_main_t *cm = &vnet_classify_main;
    2085             : 
    2086          15 :   if (a->status)
    2087             :     {
    2088           1 :       if (pp->pcap_rx_enable || pp->pcap_tx_enable || pp->pcap_drop_enable)
    2089             :         {
    2090           1 :           vlib_cli_output
    2091             :             (vm, "pcap %U dispatch capture enabled: %d of %d pkts...",
    2092             :              format_vnet_pcap, pp, 0 /* print type */ ,
    2093             :              pm->n_packets_captured, pm->n_packets_to_capture);
    2094           1 :           vlib_cli_output (vm, "capture to file %s", pm->file_name);
    2095             :         }
    2096             :       else
    2097           0 :         vlib_cli_output (vm, "pcap dispatch capture disabled");
    2098             : 
    2099           1 :       return 0;
    2100             :     }
    2101             : 
    2102             :   /* Consistency checks */
    2103             : 
    2104             :   /* Enable w/ capture already enabled not allowed */
    2105          14 :   if ((pp->pcap_rx_enable + pp->pcap_tx_enable + pp->pcap_drop_enable)
    2106           7 :       && (a->rx_enable + a->tx_enable + a->drop_enable))
    2107           0 :     return VNET_API_ERROR_INVALID_VALUE;
    2108             : 
    2109             :   /* Disable capture with capture already disabled, not interesting */
    2110          14 :   if (((pp->pcap_rx_enable + pp->pcap_tx_enable + pp->pcap_drop_enable) ==
    2111           7 :        0) &&
    2112           7 :       ((a->rx_enable + a->tx_enable + a->drop_enable == 0)))
    2113           0 :     return VNET_API_ERROR_VALUE_EXIST;
    2114             : 
    2115             :   /* Change number of packets to capture while capturing */
    2116          14 :   if ((pp->pcap_rx_enable + pp->pcap_tx_enable + pp->pcap_drop_enable)
    2117           7 :       && (a->rx_enable + a->tx_enable + a->drop_enable)
    2118           0 :       && (pm->n_packets_to_capture != a->packets_to_capture))
    2119           0 :     return VNET_API_ERROR_INVALID_VALUE_2;
    2120             : 
    2121             :   /* Classify filter specified, but no classify filter configured */
    2122          14 :   if ((a->rx_enable + a->tx_enable + a->drop_enable) && a->filter &&
    2123           3 :       (!cm->classify_table_index_by_sw_if_index ||
    2124           3 :        cm->classify_table_index_by_sw_if_index[0] == ~0))
    2125           0 :     return VNET_API_ERROR_NO_SUCH_LABEL;
    2126             : 
    2127          14 :   if (a->rx_enable + a->tx_enable + a->drop_enable)
    2128             :     {
    2129             :       void *save_pcap_data;
    2130             : 
    2131             :       /* Sanity check max bytes per pkt */
    2132           7 :       if (a->max_bytes_per_pkt < 32 || a->max_bytes_per_pkt > 9000)
    2133           0 :         return VNET_API_ERROR_INVALID_MEMORY_SIZE;
    2134             : 
    2135             :       /* Clean up from previous run, if any */
    2136           7 :       vec_reset_length (pm->pcap_data);
    2137             : 
    2138             :       /* Throw away the data buffer? */
    2139           7 :       if (a->free_data)
    2140           0 :         vec_free (pm->pcap_data);
    2141             : 
    2142           7 :       save_pcap_data = pm->pcap_data;
    2143             : 
    2144           7 :       memset (pm, 0, sizeof (*pm));
    2145             : 
    2146           7 :       pm->pcap_data = save_pcap_data;
    2147             : 
    2148           7 :       vec_validate_aligned (vnet_trace_placeholder, 2048,
    2149             :                             CLIB_CACHE_LINE_BYTES);
    2150           7 :       if (pm->lock == 0)
    2151           7 :         clib_spinlock_init (&(pm->lock));
    2152             : 
    2153           7 :       if (a->filename == 0)
    2154             :         {
    2155           1 :           u8 *stem = 0;
    2156             : 
    2157           1 :           if (a->rx_enable)
    2158           1 :             stem = format (stem, "rx");
    2159           1 :           if (a->tx_enable)
    2160           1 :             stem = format (stem, "tx");
    2161           1 :           if (a->drop_enable)
    2162           0 :             stem = format (stem, "drop");
    2163           1 :           a->filename = format (0, "/tmp/%v.pcap%c", stem, 0);
    2164           1 :           vec_free (stem);
    2165             :         }
    2166             : 
    2167           7 :       pm->file_name = (char *) a->filename;
    2168           7 :       pm->n_packets_captured = 0;
    2169           7 :       pm->packet_type = PCAP_PACKET_TYPE_ethernet;
    2170             :       /* Preallocate the data vector? */
    2171           7 :       if (a->preallocate_data)
    2172             :         {
    2173           0 :           vec_validate
    2174             :             (pm->pcap_data, a->packets_to_capture
    2175             :              * ((sizeof (pcap_packet_header_t) + a->max_bytes_per_pkt)));
    2176           0 :           vec_reset_length (pm->pcap_data);
    2177             :         }
    2178           7 :       pm->n_packets_to_capture = a->packets_to_capture;
    2179           7 :       pp->pcap_sw_if_index = a->sw_if_index;
    2180           7 :       if (a->filter)
    2181           3 :         pp->filter_classify_table_index =
    2182           3 :           cm->classify_table_index_by_sw_if_index[0];
    2183             :       else
    2184           4 :         pp->filter_classify_table_index = ~0;
    2185           7 :       pp->pcap_error_index = a->drop_err;
    2186           7 :       pp->pcap_rx_enable = a->rx_enable;
    2187           7 :       pp->pcap_tx_enable = a->tx_enable;
    2188           7 :       pp->pcap_drop_enable = a->drop_enable;
    2189           7 :       pp->max_bytes_per_pkt = a->max_bytes_per_pkt;
    2190             :     }
    2191             :   else
    2192             :     {
    2193           7 :       pp->pcap_rx_enable = 0;
    2194           7 :       pp->pcap_tx_enable = 0;
    2195           7 :       pp->pcap_drop_enable = 0;
    2196           7 :       pp->filter_classify_table_index = ~0;
    2197           7 :       pp->pcap_error_index = ~0;
    2198           7 :       if (pm->n_packets_captured)
    2199             :         {
    2200             :           clib_error_t *error;
    2201           7 :           pm->n_packets_to_capture = pm->n_packets_captured;
    2202           7 :           vlib_cli_output (vm, "Write %d packets to %s, and stop capture...",
    2203             :                            pm->n_packets_captured, pm->file_name);
    2204           7 :           error = pcap_write (pm);
    2205           7 :           if (pm->flags & PCAP_MAIN_INIT_DONE)
    2206           7 :             pcap_close (pm);
    2207             :           /* Report I/O errors... */
    2208           7 :           if (error)
    2209             :             {
    2210           0 :               clib_error_report (error);
    2211           0 :               return VNET_API_ERROR_SYSCALL_ERROR_1;
    2212             :             }
    2213           7 :           vec_free (pm->file_name);
    2214           7 :           if (a->free_data)
    2215           0 :             vec_free (pm->pcap_data);
    2216           7 :           return 0;
    2217             :         }
    2218             :       else
    2219           0 :         return VNET_API_ERROR_NO_SUCH_ENTRY;
    2220             :     }
    2221             : 
    2222           7 :   return 0;
    2223             : }
    2224             : 
    2225             : static clib_error_t *
    2226           9 : pcap_trace_command_fn (vlib_main_t * vm,
    2227             :                        unformat_input_t * input, vlib_cli_command_t * cmd)
    2228             : {
    2229           9 :   unformat_input_t _line_input, *line_input = &_line_input;
    2230           9 :   vnet_pcap_dispatch_trace_args_t _a, *a = &_a;
    2231           9 :   vnet_main_t *vnm = vnet_get_main ();
    2232           9 :   u8 *filename = 0;
    2233           9 :   u32 max = 1000;
    2234           9 :   u32 max_bytes_per_pkt = 512;
    2235             :   int rv;
    2236           9 :   int rx_enable = 0;
    2237           9 :   int tx_enable = 0;
    2238           9 :   int preallocate_data = 0;
    2239           9 :   int drop_enable = 0;
    2240           9 :   int status = 0;
    2241           9 :   int filter = 0;
    2242           9 :   int free_data = 0;
    2243           9 :   u32 sw_if_index = 0;          /* default: any interface */
    2244           9 :   vlib_error_t drop_err = ~0;   /* default: any error */
    2245             : 
    2246             :   /* Get a line of input. */
    2247           9 :   if (!unformat_user (input, unformat_line_input, line_input))
    2248           0 :     return 0;
    2249             : 
    2250          41 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    2251             :     {
    2252          32 :       if (unformat (line_input, "rx"))
    2253           6 :         rx_enable = 1;
    2254          26 :       else if (unformat (line_input, "tx"))
    2255           6 :         tx_enable = 1;
    2256          20 :       else if (unformat (line_input, "drop"))
    2257           2 :         drop_enable = 1;
    2258          18 :       else if (unformat (line_input, "off"))
    2259           4 :         rx_enable = tx_enable = drop_enable = 0;
    2260          14 :       else if (unformat (line_input, "max-bytes-per-pkt %u",
    2261             :                          &max_bytes_per_pkt))
    2262             :         ;
    2263          14 :       else if (unformat (line_input, "max %d", &max))
    2264             :         ;
    2265          10 :       else if (unformat (line_input, "packets-to-capture %d", &max))
    2266             :         ;
    2267          10 :       else if (unformat (line_input, "file %U", unformat_vlib_tmpfile,
    2268             :                          &filename))
    2269             :         ;
    2270           7 :       else if (unformat (line_input, "status %=", &status, 1))
    2271             :         ;
    2272           6 :       else if (unformat (line_input, "intfc %U",
    2273             :                          unformat_vnet_sw_interface, vnm, &sw_if_index))
    2274             :         ;
    2275           5 :       else if (unformat (line_input, "interface %U",
    2276             :                          unformat_vnet_sw_interface, vnm, &sw_if_index))
    2277             :         ;
    2278           5 :       else if (unformat (line_input, "error %U", unformat_vlib_error, vm,
    2279             :                          &drop_err))
    2280             :         ;
    2281           4 :       else if (unformat (line_input, "preallocate-data %=",
    2282             :                          &preallocate_data, 1))
    2283             :         ;
    2284           4 :       else if (unformat (line_input, "free-data %=", &free_data, 1))
    2285             :         ;
    2286           4 :       else if (unformat (line_input, "intfc any")
    2287           2 :                || unformat (line_input, "interface any"))
    2288           2 :         sw_if_index = 0;
    2289           2 :       else if (unformat (line_input, "filter"))
    2290           2 :         filter = 1;
    2291             :       else
    2292             :         {
    2293           0 :           return clib_error_return (0, "unknown input `%U'",
    2294             :                                     format_unformat_error, line_input);
    2295             :         }
    2296             :     }
    2297             : 
    2298           9 :   unformat_free (line_input);
    2299             : 
    2300             :   /* no need for memset (a, 0, sizeof (*a)), set all fields here. */
    2301           9 :   a->filename = filename;
    2302           9 :   a->rx_enable = rx_enable;
    2303           9 :   a->tx_enable = tx_enable;
    2304           9 :   a->preallocate_data = preallocate_data;
    2305           9 :   a->free_data = free_data;
    2306           9 :   a->drop_enable = drop_enable;
    2307           9 :   a->status = status;
    2308           9 :   a->packets_to_capture = max;
    2309           9 :   a->sw_if_index = sw_if_index;
    2310           9 :   a->filter = filter;
    2311           9 :   a->max_bytes_per_pkt = max_bytes_per_pkt;
    2312           9 :   a->drop_err = drop_err;
    2313             : 
    2314           9 :   rv = vnet_pcap_dispatch_trace_configure (a);
    2315             : 
    2316           9 :   switch (rv)
    2317             :     {
    2318           9 :     case 0:
    2319           9 :       break;
    2320             : 
    2321           0 :     case VNET_API_ERROR_INVALID_VALUE:
    2322           0 :       return clib_error_return (0, "dispatch trace already enabled...");
    2323             : 
    2324           0 :     case VNET_API_ERROR_VALUE_EXIST:
    2325           0 :       return clib_error_return (0, "dispatch trace already disabled...");
    2326             : 
    2327           0 :     case VNET_API_ERROR_INVALID_VALUE_2:
    2328           0 :       return clib_error_return
    2329             :         (0, "can't change number of records to capture while tracing...");
    2330             : 
    2331           0 :     case VNET_API_ERROR_SYSCALL_ERROR_1:
    2332           0 :       return clib_error_return (0, "I/O writing trace capture...");
    2333             : 
    2334           0 :     case VNET_API_ERROR_NO_SUCH_ENTRY:
    2335           0 :       return clib_error_return (0, "No packets captured...");
    2336             : 
    2337           0 :     case VNET_API_ERROR_INVALID_MEMORY_SIZE:
    2338           0 :       return clib_error_return (0,
    2339             :                                 "Max bytes per pkt must be > 32, < 9000...");
    2340             : 
    2341           0 :     case VNET_API_ERROR_NO_SUCH_LABEL:
    2342           0 :       return clib_error_return
    2343             :         (0, "No classify filter configured, see 'classify filter...'");
    2344             : 
    2345           0 :     default:
    2346           0 :       vlib_cli_output (vm, "WARNING: trace configure returned %d", rv);
    2347           0 :       break;
    2348             :     }
    2349           9 :   return 0;
    2350             : }
    2351             : 
    2352             : /*?
    2353             :  * This command is used to start or stop a packet capture, or show
    2354             :  * the status of packet capture.
    2355             :  *
    2356             :  * This command has the following optional parameters:
    2357             :  *
    2358             :  *
    2359             :  * - <b>rx</b> - Capture received packets
    2360             :  *
    2361             :  * - <b>tx</b> - Capture transmitted packets
    2362             :  *
    2363             :  * - <b>drop</b> - Capture dropped packets
    2364             :  *
    2365             :  * - <b>off</b> - Stop capturing packets, write results to the specified file
    2366             :  *
    2367             :  * - <b>max <nn></b> - Depth of local buffer. Once '<em>nn</em>' number
    2368             :  *   of packets have been received, buffer is flushed to file. Once another
    2369             :  *   '<em>nn</em>' number of packets have been received, buffer is flushed
    2370             :  *   to file, overwriting previous write. If not entered, value defaults
    2371             :  *   to 100. Can only be updated if packet capture is off.
    2372             :  *
    2373             :  * - <b>max-bytes-per-pkt <nnnn></b> - Maximum number of bytes to capture
    2374             :  *   for each packet. Must be >= 32, <= 9000.
    2375             :  *
    2376             :  * - <b>preallocate-data</b> - Preallocate the data buffer, to avoid
    2377             :  *   vector expansion delays during pcap capture
    2378             :  *
    2379             :  * - <b>free-data</b> - Free the data buffer. Ordinarily it's a feature
    2380             :  *   to retain the data buffer so this option is seldom used.
    2381             :  *
    2382             :  * - <b>intfc <interface-name>|any</b> - Used to specify a given interface,
    2383             :  *   or use '<em>any</em>' to run packet capture on all interfaces.
    2384             :  *   '<em>any</em>' is the default if not provided. Settings from a previous
    2385             :  *   packet capture are preserved, so '<em>any</em>' can be used to reset
    2386             :  *   the interface setting.
    2387             :  *
    2388             :  * - <b>filter</b> - Use the pcap trace rx / tx / drop filter, which
    2389             :  *   must be configured. Use <b>classify filter pcap...</b> to configure the
    2390             :  *   filter. The filter will only be executed if the per-interface or
    2391             :  *   any-interface tests fail.
    2392             :  *
    2393             :  * - <b>error <node>.<error></b> - filter packets based on a specific error.
    2394             :  *   For example: error {ip4-udp-lookup}.{no_listener}
    2395             :  *
    2396             :  * - <b>file <name></b> - Used to specify the output filename. The file will
    2397             :  *   be placed in the '<em>/tmp</em>' directory, so only the filename is
    2398             :  *   supported. Directory should not be entered. If file already exists, file
    2399             :  *   will be overwritten. If no filename is provided, the file will be
    2400             :  *   named "/tmp/rx.pcap", "/tmp/tx.pcap", "/tmp/rxandtx.pcap", etc.
    2401             :  *   Can only be updated if packet capture is off.
    2402             :  *
    2403             :  * - <b>status</b> - Displays the current status and configured attributes
    2404             :  *   associated with a packet capture. If packet capture is in progress,
    2405             :  *   '<em>status</em>' also will return the number of packets currently in
    2406             :  *   the local buffer. All additional attributes entered on command line
    2407             :  *   with '<em>status</em>' will be ignored and not applied.
    2408             :  *
    2409             :  * @cliexpar
    2410             :  * Example of how to display the status of a tx packet capture when off:
    2411             :  * @cliexstart{pcap trace status}
    2412             :  * max is 100, for any interface to file /tmp/vpe.pcap
    2413             :  * pcap tx capture is off...
    2414             :  * @cliexend
    2415             :  * Example of how to start a tx packet capture:
    2416             :  * @cliexstart{pcap trace tx max 35 intfc GigabitEthernet0/8/0 file
    2417             :  * vppTest.pcap}
    2418             :  * @cliexend
    2419             :  * Example of how to display the status of a tx packet capture in progress:
    2420             :  * @cliexstart{pcap trace status}
    2421             :  * max is 35, for interface GigabitEthernet0/8/0 to file /tmp/vppTest.pcap
    2422             :  * pcap tx capture is on: 20 of 35 pkts...
    2423             :  * @cliexend
    2424             :  * Example of how to stop a tx packet capture:
    2425             :  * @cliexstart{pcap trace off}
    2426             :  * captured 21 pkts...
    2427             :  * saved to /tmp/vppTest.pcap...
    2428             :  * @cliexend
    2429             : ?*/
    2430             : /* *INDENT-OFF* */
    2431             : 
    2432      272887 : VLIB_CLI_COMMAND (pcap_tx_trace_command, static) = {
    2433             :     .path = "pcap trace",
    2434             :     .short_help =
    2435             :     "pcap trace [rx] [tx] [drop] [off] [max <nn>] [intfc <interface>|any]\n"
    2436             :     "           [file <name>] [status] [max-bytes-per-pkt <nnnn>][filter]\n"
    2437             :     "           [preallocate-data][free-data]",
    2438             :     .function = pcap_trace_command_fn,
    2439             : };
    2440             : /* *INDENT-ON* */
    2441             : 
    2442             : static clib_error_t *
    2443           0 : set_interface_name (vlib_main_t *vm, unformat_input_t *input,
    2444             :                     vlib_cli_command_t *cmd)
    2445             : {
    2446           0 :   clib_error_t *error = 0;
    2447           0 :   unformat_input_t _line_input, *line_input = &_line_input;
    2448           0 :   vnet_main_t *vnm = vnet_get_main ();
    2449           0 :   u32 hw_if_index = ~0;
    2450           0 :   char *name = 0;
    2451             : 
    2452           0 :   if (!unformat_user (input, unformat_line_input, line_input))
    2453           0 :     return 0;
    2454             : 
    2455           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    2456             :     {
    2457           0 :       if (unformat (line_input, "%U %s", unformat_vnet_hw_interface, vnm,
    2458             :                     &hw_if_index, &name))
    2459             :         ;
    2460             :       else
    2461             :         {
    2462           0 :           error = clib_error_return (0, "parse error: '%U'",
    2463             :                                      format_unformat_error, line_input);
    2464           0 :           unformat_free (line_input);
    2465           0 :           vec_free (name);
    2466           0 :           return error;
    2467             :         }
    2468             :     }
    2469             : 
    2470           0 :   unformat_free (line_input);
    2471             : 
    2472           0 :   if (hw_if_index == (u32) ~0 || name == 0)
    2473             :     {
    2474           0 :       vec_free (name);
    2475           0 :       error = clib_error_return (0, "please specify valid interface name");
    2476           0 :       return error;
    2477             :     }
    2478             : 
    2479           0 :   error = vnet_rename_interface (vnm, hw_if_index, name);
    2480           0 :   vec_free (name);
    2481             : 
    2482           0 :   return (error);
    2483             : }
    2484             : 
    2485      272887 : VLIB_CLI_COMMAND (cmd_set_if_name, static) = {
    2486             :   .path = "set interface name",
    2487             :   .short_help = "set interface name <interface-name> <new-interface-name>",
    2488             :   .function = set_interface_name,
    2489             :   .is_mp_safe = 1,
    2490             : };
    2491             : 
    2492             : static clib_error_t *
    2493           0 : set_interface_tx_hash_cmd (vlib_main_t *vm, unformat_input_t *input,
    2494             :                            vlib_cli_command_t *cmd)
    2495             : {
    2496           0 :   clib_error_t *error = 0;
    2497           0 :   unformat_input_t _line_input, *line_input = &_line_input;
    2498           0 :   vnet_main_t *vnm = vnet_get_main ();
    2499             :   vnet_hw_interface_t *hi;
    2500           0 :   u8 *hash_name = 0;
    2501           0 :   u32 hw_if_index = (u32) ~0;
    2502             :   vnet_hash_fn_t hf;
    2503             :   vnet_hash_fn_type_t ftype;
    2504             : 
    2505           0 :   if (!unformat_user (input, unformat_line_input, line_input))
    2506           0 :     return 0;
    2507             : 
    2508           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    2509             :     {
    2510           0 :       if (unformat (line_input, "%U", unformat_vnet_hw_interface, vnm,
    2511             :                     &hw_if_index))
    2512             :         ;
    2513           0 :       else if (unformat (line_input, "hash-name %s", &hash_name))
    2514             :         ;
    2515             :       else
    2516             :         {
    2517           0 :           error = clib_error_return (0, "parse error: '%U'",
    2518             :                                      format_unformat_error, line_input);
    2519           0 :           unformat_free (line_input);
    2520           0 :           return error;
    2521             :         }
    2522             :     }
    2523             : 
    2524           0 :   unformat_free (line_input);
    2525             : 
    2526           0 :   if (hw_if_index == (u32) ~0)
    2527             :     {
    2528           0 :       error = clib_error_return (0, "please specify valid interface name");
    2529           0 :       goto error;
    2530             :     }
    2531             : 
    2532           0 :   if (hash_name == 0)
    2533             :     {
    2534           0 :       error = clib_error_return (0, "hash-name is required");
    2535           0 :       goto error;
    2536             :     }
    2537             : 
    2538           0 :   hi = vnet_get_hw_interface (vnm, hw_if_index);
    2539           0 :   ftype =
    2540           0 :     vnet_get_hw_interface_class (vnm, hi->hw_class_index)->tx_hash_fn_type;
    2541           0 :   hf = vnet_hash_function_from_name ((const char *) hash_name, ftype);
    2542             : 
    2543           0 :   if (!hf)
    2544             :     {
    2545           0 :       error = clib_error_return (0, "please specify valid hash name");
    2546           0 :       goto error;
    2547             :     }
    2548             : 
    2549           0 :   hi->hf = hf;
    2550           0 : error:
    2551           0 :   vec_free (hash_name);
    2552           0 :   return (error);
    2553             : }
    2554             : 
    2555      272887 : VLIB_CLI_COMMAND (cmd_set_if_tx_hash, static) = {
    2556             :   .path = "set interface tx-hash",
    2557             :   .short_help = "set interface tx-hash <interface> hash-name <hash-name>",
    2558             :   .function = set_interface_tx_hash_cmd,
    2559             : };
    2560             : 
    2561             : static clib_error_t *
    2562           0 : show_tx_hash (vlib_main_t *vm, unformat_input_t *input,
    2563             :               vlib_cli_command_t *cmd)
    2564             : {
    2565           0 :   clib_error_t *error = 0;
    2566           0 :   unformat_input_t _line_input, *line_input = &_line_input;
    2567           0 :   vnet_main_t *vnm = vnet_get_main ();
    2568             :   vnet_hw_interface_t *hi;
    2569             :   vnet_hash_function_registration_t *hash;
    2570           0 :   u32 hw_if_index = (u32) ~0;
    2571             :   vnet_hash_fn_type_t ftype;
    2572             : 
    2573           0 :   if (!unformat_user (input, unformat_line_input, line_input))
    2574           0 :     return 0;
    2575             : 
    2576           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    2577             :     {
    2578           0 :       if (unformat (line_input, "%U", unformat_vnet_hw_interface, vnm,
    2579             :                     &hw_if_index))
    2580             :         ;
    2581             :       else
    2582             :         {
    2583           0 :           error = clib_error_return (0, "parse error: '%U'",
    2584             :                                      format_unformat_error, line_input);
    2585           0 :           unformat_free (line_input);
    2586           0 :           goto error;
    2587             :         }
    2588             :     }
    2589             : 
    2590           0 :   unformat_free (line_input);
    2591             : 
    2592           0 :   if (hw_if_index == (u32) ~0)
    2593             :     {
    2594           0 :       error = clib_error_return (0, "please specify valid interface name");
    2595           0 :       goto error;
    2596             :     }
    2597             : 
    2598           0 :   hi = vnet_get_hw_interface (vnm, hw_if_index);
    2599           0 :   ftype =
    2600           0 :     vnet_get_hw_interface_class (vnm, hi->hw_class_index)->tx_hash_fn_type;
    2601             : 
    2602           0 :   if (hi->hf)
    2603             :     {
    2604           0 :       hash = vnet_hash_function_from_func (hi->hf, ftype);
    2605           0 :       if (hash)
    2606           0 :         vlib_cli_output (vm, "%U", format_vnet_hash, hash);
    2607             :       else
    2608           0 :         vlib_cli_output (vm, "no matching hash function found");
    2609             :     }
    2610             :   else
    2611           0 :     vlib_cli_output (vm, "no hashing function set");
    2612             : 
    2613           0 : error:
    2614           0 :   return (error);
    2615             : }
    2616             : 
    2617      272887 : VLIB_CLI_COMMAND (cmd_show_tx_hash, static) = {
    2618             :   .path = "show interface tx-hash",
    2619             :   .short_help = "show interface tx-hash [interface]",
    2620             :   .function = show_tx_hash,
    2621             : };
    2622             : 
    2623             : /*
    2624             :  * fd.io coding-style-patch-verification: ON
    2625             :  *
    2626             :  * Local Variables:
    2627             :  * eval: (c-set-style "gnu")
    2628             :  * End:
    2629             :  */

Generated by: LCOV version 1.14