LCOV - code coverage report
Current view: top level - vnet/ip - lookup.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 155 347 44.7 %
Date: 2023-07-05 22:20:52 Functions: 38 43 88.4 %

          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             :  * ip/ip_lookup.c: ip4/6 adjacency and lookup table management
      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             : #include <vnet/ip/ip.h>
      41             : #include <vnet/adj/adj.h>
      42             : #include <vnet/fib/fib_table.h>
      43             : #include <vnet/fib/ip4_fib.h>
      44             : #include <vnet/fib/ip6_fib.h>
      45             : #include <vnet/mpls/mpls.h>
      46             : #include <vnet/mfib/mfib_table.h>
      47             : #include <vnet/dpo/drop_dpo.h>
      48             : #include <vnet/dpo/classify_dpo.h>
      49             : #include <vnet/dpo/punt_dpo.h>
      50             : #include <vnet/dpo/receive_dpo.h>
      51             : #include <vnet/dpo/ip_null_dpo.h>
      52             : 
      53             : /**
      54             :  * @file
      55             :  * @brief IPv4 and IPv6 adjacency and lookup table management.
      56             :  *
      57             :  */
      58             : 
      59             : static clib_error_t *
      60       11597 : ip_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
      61             : {
      62       15494 :   vec_validate_init_empty (ip4_main.
      63             :                            lookup_main.if_address_pool_index_by_sw_if_index,
      64             :                            sw_if_index, ~0);
      65       15494 :   vec_validate_init_empty (ip6_main.
      66             :                            lookup_main.if_address_pool_index_by_sw_if_index,
      67             :                            sw_if_index, ~0);
      68             : 
      69       11597 :   return (NULL);
      70             : }
      71             : 
      72        3363 : VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ip_sw_interface_add_del);
      73             : 
      74             : void
      75        1118 : ip_lookup_init (ip_lookup_main_t * lm, u32 is_ip6)
      76             : {
      77        1118 :   if (!lm->fib_result_n_bytes)
      78        1118 :     lm->fib_result_n_bytes = sizeof (uword);
      79             : 
      80        1118 :   lm->is_ip6 = is_ip6;
      81        1118 :   mhash_init (&lm->prefix_to_if_prefix_index, sizeof (uword),
      82             :               sizeof (ip_interface_prefix_key_t));
      83        1118 :   if (is_ip6)
      84             :     {
      85         559 :       lm->format_address_and_length = format_ip6_address_and_length;
      86         559 :       mhash_init (&lm->address_to_if_address_index, sizeof (uword),
      87             :                   sizeof (ip6_address_fib_t));
      88             :     }
      89             :   else
      90             :     {
      91         559 :       lm->format_address_and_length = format_ip4_address_and_length;
      92         559 :       mhash_init (&lm->address_to_if_address_index, sizeof (uword),
      93             :                   sizeof (ip4_address_fib_t));
      94             :     }
      95             : 
      96             :   {
      97             :     int i;
      98             : 
      99             :     /* Setup all IP protocols to be punted and builtin-unknown. */
     100      287326 :     for (i = 0; i < 256; i++)
     101             :       {
     102      286208 :         lm->local_next_by_ip_protocol[i] = IP_LOCAL_NEXT_PUNT;
     103      286208 :         lm->builtin_protocol_by_ip_protocol[i] = IP_BUILTIN_PROTOCOL_UNKNOWN;
     104             :       }
     105             : 
     106        1118 :     lm->local_next_by_ip_protocol[IP_PROTOCOL_UDP] = IP_LOCAL_NEXT_UDP_LOOKUP;
     107        1118 :     lm->local_next_by_ip_protocol[is_ip6 ? IP_PROTOCOL_ICMP6 :
     108        1118 :                                   IP_PROTOCOL_ICMP] = IP_LOCAL_NEXT_ICMP;
     109        1118 :     lm->builtin_protocol_by_ip_protocol[IP_PROTOCOL_UDP] =
     110             :       IP_BUILTIN_PROTOCOL_UDP;
     111        1118 :     lm->builtin_protocol_by_ip_protocol[is_ip6 ? IP_PROTOCOL_ICMP6 :
     112        1118 :                                         IP_PROTOCOL_ICMP] =
     113             :       IP_BUILTIN_PROTOCOL_ICMP;
     114             :   }
     115        1118 : }
     116             : 
     117             : u8 *
     118         572 : format_ip_flow_hash_config (u8 * s, va_list * args)
     119             : {
     120         572 :   flow_hash_config_t flow_hash_config = va_arg (*args, u32);
     121             : 
     122             : #define _(n, b, v)                                                            \
     123             :   if (flow_hash_config & v)                                                   \
     124             :     s = format (s, "%s ", #n);
     125         572 :   foreach_flow_hash_bit;
     126             : #undef _
     127             : 
     128         572 :   return s;
     129             : }
     130             : 
     131             : uword
     132           0 : unformat_ip_flow_hash_config (unformat_input_t *input, va_list *args)
     133             : {
     134           0 :   flow_hash_config_t *flow_hash_config = va_arg (*args, flow_hash_config_t *);
     135           0 :   uword start_index = unformat_check_input (input);
     136           0 :   int matched_once = 0;
     137             : 
     138           0 :   if (unformat (input, "default"))
     139             :     {
     140           0 :       *flow_hash_config = IP_FLOW_HASH_DEFAULT;
     141           0 :       return 1;
     142             :     }
     143           0 :   while (!unformat_is_eof (input) &&
     144           0 :          !is_white_space (unformat_peek_input (input)))
     145             :     {
     146           0 :       if (unformat (input, "%_,"))
     147             :         ;
     148             : #define _(a, b, c)                                                            \
     149             :   else if (unformat (input, "%_" #a))                                         \
     150             :   {                                                                           \
     151             :     *flow_hash_config |= c;                                                   \
     152             :     matched_once = 1;                                                         \
     153             :   }
     154           0 :       foreach_flow_hash_bit
     155             : #undef _
     156             :         else
     157             :       {
     158             :         /* Roll back to our start */
     159           0 :         input->index = start_index;
     160           0 :         return 0;
     161             :       }
     162             :     }
     163             : 
     164           0 :   return matched_once;
     165             : }
     166             : 
     167             : u8 *
     168      306113 : format_ip_adjacency_packet_data (u8 * s, va_list * args)
     169             : {
     170      306113 :   u8 *packet_data = va_arg (*args, u8 *);
     171      306113 :   u32 n_packet_data_bytes = va_arg (*args, u32);
     172             : 
     173      306113 :   s = format (s, "%U", format_hex_bytes, packet_data, n_packet_data_bytes);
     174             : 
     175      306113 :   return s;
     176             : }
     177             : 
     178             : static uword
     179           2 : unformat_dpo (unformat_input_t * input, va_list * args)
     180             : {
     181           2 :   dpo_id_t *dpo = va_arg (*args, dpo_id_t *);
     182           2 :   fib_protocol_t fp = va_arg (*args, int);
     183             :   dpo_proto_t proto;
     184             : 
     185           2 :   proto = fib_proto_to_dpo (fp);
     186             : 
     187           2 :   if (unformat (input, "drop"))
     188           2 :     dpo_copy (dpo, drop_dpo_get (proto));
     189           0 :   else if (unformat (input, "punt"))
     190           0 :     dpo_copy (dpo, punt_dpo_get (proto));
     191           0 :   else if (unformat (input, "local"))
     192           0 :     receive_dpo_add_or_lock (proto, ~0, NULL, dpo);
     193           0 :   else if (unformat (input, "null-send-unreach"))
     194           0 :     ip_null_dpo_add_and_lock (proto, IP_NULL_ACTION_SEND_ICMP_UNREACH, dpo);
     195           0 :   else if (unformat (input, "null-send-prohibit"))
     196           0 :     ip_null_dpo_add_and_lock (proto, IP_NULL_ACTION_SEND_ICMP_PROHIBIT, dpo);
     197           0 :   else if (unformat (input, "null"))
     198           0 :     ip_null_dpo_add_and_lock (proto, IP_NULL_ACTION_NONE, dpo);
     199           0 :   else if (unformat (input, "classify"))
     200             :     {
     201             :       u32 classify_table_index;
     202             : 
     203           0 :       if (!unformat (input, "%d", &classify_table_index))
     204             :         {
     205           0 :           clib_warning ("classify adj must specify table index");
     206           0 :           return 0;
     207             :         }
     208             : 
     209           0 :       dpo_set (dpo, DPO_CLASSIFY, proto,
     210             :                classify_dpo_create (proto, classify_table_index));
     211             :     }
     212             :   else
     213           0 :     return 0;
     214             : 
     215           2 :   return 1;
     216             : }
     217             : 
     218             : const ip46_address_t zero_addr = {
     219             :   .as_u64 = {
     220             :              0, 0},
     221             : };
     222             : 
     223             : static clib_error_t *
     224          11 : vnet_ip_route_cmd (vlib_main_t * vm,
     225             :                    unformat_input_t * main_input, vlib_cli_command_t * cmd)
     226             : {
     227          11 :   unformat_input_t _line_input, *line_input = &_line_input;
     228             :   u32 table_id, is_del, fib_index, payload_proto;
     229          11 :   dpo_id_t dpo = DPO_INVALID, *dpos = NULL;
     230          11 :   fib_route_path_t *rpaths = NULL, rpath;
     231          11 :   fib_prefix_t *prefixs = NULL, pfx;
     232          11 :   clib_error_t *error = NULL;
     233             :   f64 count;
     234             :   int i;
     235             : 
     236          11 :   is_del = 0;
     237          11 :   table_id = 0;
     238          11 :   count = 1;
     239          11 :   clib_memset (&pfx, 0, sizeof (pfx));
     240             : 
     241             :   /* Get a line of input. */
     242          11 :   if (!unformat_user (main_input, unformat_line_input, line_input))
     243           0 :     return 0;
     244             : 
     245          46 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     246             :     {
     247          35 :       clib_memset (&rpath, 0, sizeof (rpath));
     248             : 
     249          35 :       if (unformat (line_input, "table %d", &table_id))
     250             :         ;
     251          33 :       else if (unformat (line_input, "count %f", &count))
     252             :         ;
     253             : 
     254          33 :       else if (unformat (line_input, "%U/%d",
     255             :                          unformat_ip4_address, &pfx.fp_addr.ip4, &pfx.fp_len))
     256             :         {
     257           2 :           payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP4;
     258           2 :           vec_add1 (prefixs, pfx);
     259             :         }
     260          31 :       else if (unformat (line_input, "%U/%d",
     261             :                          unformat_ip6_address, &pfx.fp_addr.ip6, &pfx.fp_len))
     262             :         {
     263           9 :           payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP6;
     264           9 :           vec_add1 (prefixs, pfx);
     265             :         }
     266          22 :       else if (unformat (line_input, "via %U",
     267             :                          unformat_fib_route_path, &rpath, &payload_proto))
     268             :         {
     269           9 :           vec_add1 (rpaths, rpath);
     270             :         }
     271          15 :       else if (vec_len (prefixs) > 0 &&
     272           2 :                unformat (line_input, "via %U",
     273           2 :                          unformat_dpo, &dpo, prefixs[0].fp_proto))
     274             :         {
     275           2 :           vec_add1 (dpos, dpo);
     276             :         }
     277          11 :       else if (unformat (line_input, "del"))
     278           0 :         is_del = 1;
     279          11 :       else if (unformat (line_input, "add"))
     280          11 :         is_del = 0;
     281             :       else
     282             :         {
     283           0 :           error = unformat_parse_error (line_input);
     284           0 :           goto done;
     285             :         }
     286             :     }
     287             : 
     288          11 :   if (vec_len (prefixs) == 0)
     289             :     {
     290             :       error =
     291           0 :         clib_error_return (0, "expected ip4/ip6 destination address/length.");
     292           0 :       goto done;
     293             :     }
     294             : 
     295          11 :   if (!is_del && vec_len (rpaths) + vec_len (dpos) == 0)
     296             :     {
     297           0 :       error = clib_error_return (0, "expected paths.");
     298           0 :       goto done;
     299             :     }
     300             : 
     301          11 :   if (~0 == table_id)
     302             :     {
     303             :       /*
     304             :        * if no table_id is passed we will manipulate the default
     305             :        */
     306           0 :       fib_index = 0;
     307             :     }
     308             :   else
     309             :     {
     310          11 :       fib_index = fib_table_find (prefixs[0].fp_proto, table_id);
     311             : 
     312          11 :       if (~0 == fib_index)
     313             :         {
     314           0 :           error = clib_error_return (0, "Nonexistent table id %d", table_id);
     315           0 :           goto done;
     316             :         }
     317             :     }
     318             : 
     319          22 :   for (i = 0; i < vec_len (prefixs); i++)
     320             :     {
     321          11 :       if (is_del && 0 == vec_len (rpaths))
     322             :         {
     323           0 :           fib_table_entry_delete (fib_index, &prefixs[i], FIB_SOURCE_CLI);
     324             :         }
     325          11 :       else if (!is_del && 1 == vec_len (dpos))
     326             :         {
     327           2 :           fib_table_entry_special_dpo_add (fib_index,
     328           2 :                                            &prefixs[i],
     329             :                                            FIB_SOURCE_CLI,
     330             :                                            FIB_ENTRY_FLAG_EXCLUSIVE,
     331             :                                            &dpos[0]);
     332           2 :           dpo_reset (&dpos[0]);
     333             :         }
     334           9 :       else if (vec_len (dpos) > 0)
     335             :         {
     336             :           error =
     337           0 :             clib_error_return (0,
     338             :                                "Load-balancing over multiple special adjacencies is unsupported");
     339           0 :           goto done;
     340             :         }
     341           9 :       else if (0 < vec_len (rpaths))
     342           9 :         {
     343             :           u32 k, n;
     344             :           f64 t[2];
     345           9 :           n = count;
     346           9 :           t[0] = vlib_time_now (vm);
     347             : 
     348          18 :           for (k = 0; k < n; k++)
     349             :             {
     350           9 :               fib_prefix_t rpfx = {
     351           9 :                 .fp_len = prefixs[i].fp_len,
     352           9 :                 .fp_proto = prefixs[i].fp_proto,
     353           9 :                 .fp_addr = prefixs[i].fp_addr,
     354             :               };
     355             : 
     356           9 :               if (is_del)
     357           0 :                 fib_table_entry_path_remove2 (fib_index,
     358             :                                               &rpfx, FIB_SOURCE_CLI, rpaths);
     359             :               else
     360           9 :                 fib_table_entry_path_add2 (fib_index,
     361             :                                            &rpfx,
     362             :                                            FIB_SOURCE_CLI,
     363             :                                            FIB_ENTRY_FLAG_NONE, rpaths);
     364             : 
     365           9 :               fib_prefix_increment (&prefixs[i]);
     366             :             }
     367             : 
     368           9 :           t[1] = vlib_time_now (vm);
     369           9 :           if (count > 1)
     370           0 :             vlib_cli_output (vm, "%.6e routes/sec", count / (t[1] - t[0]));
     371             :         }
     372             :       else
     373             :         {
     374           0 :           error = clib_error_return (0, "Don't understand what you want...");
     375           0 :           goto done;
     376             :         }
     377             :     }
     378             : 
     379          11 : done:
     380          11 :   vec_free (dpos);
     381          11 :   vec_free (prefixs);
     382          11 :   vec_free (rpaths);
     383          11 :   unformat_free (line_input);
     384          11 :   return error;
     385             : }
     386             : 
     387             : clib_error_t *
     388           3 : vnet_ip_table_cmd (vlib_main_t * vm,
     389             :                    unformat_input_t * main_input,
     390             :                    vlib_cli_command_t * cmd, fib_protocol_t fproto)
     391             : {
     392           3 :   unformat_input_t _line_input, *line_input = &_line_input;
     393           3 :   clib_error_t *error = NULL;
     394             :   u32 table_id, is_add;
     395           3 :   u8 *name = NULL;
     396             : 
     397           3 :   is_add = 1;
     398           3 :   table_id = ~0;
     399             : 
     400             :   /* Get a line of input. */
     401           3 :   if (!unformat_user (main_input, unformat_line_input, line_input))
     402           0 :     return 0;
     403             : 
     404           7 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     405             :     {
     406           4 :       if (unformat (line_input, "%d", &table_id))
     407             :         ;
     408           1 :       else if (unformat (line_input, "del"))
     409           0 :         is_add = 0;
     410           1 :       else if (unformat (line_input, "add"))
     411           1 :         is_add = 1;
     412           0 :       else if (unformat (line_input, "name %s", &name))
     413             :         ;
     414             :       else
     415             :         {
     416           0 :           error = unformat_parse_error (line_input);
     417           0 :           goto done;
     418             :         }
     419             :     }
     420             : 
     421           3 :   if (0 == table_id)
     422             :     {
     423           0 :       error = clib_error_return (0, "Can't change the default table");
     424           0 :       goto done;
     425             :     }
     426             :   else
     427             :         {
     428           3 :           if (is_add)
     429             :             {
     430           3 :               if (~0 == table_id)
     431             :                 {
     432           0 :                   table_id = ip_table_get_unused_id (fproto);
     433           0 :                   vlib_cli_output (vm, "%u\n", table_id);
     434             :                 }
     435           3 :               ip_table_create (fproto, table_id, 0, name);
     436             :             }
     437             :           else
     438             :             {
     439           0 :               if (~0 == table_id)
     440             :                 {
     441           0 :                   error = clib_error_return (0, "No table id");
     442           0 :                   goto done;
     443             :                 }
     444           0 :               ip_table_delete (fproto, table_id, 0);
     445             :             }
     446             :         }
     447             : 
     448           3 : done:
     449           3 :   vec_free (name);
     450           3 :   unformat_free (line_input);
     451           3 :   return error;
     452             : }
     453             : 
     454             : clib_error_t *
     455           2 : vnet_ip4_table_cmd (vlib_main_t * vm,
     456             :                     unformat_input_t * main_input, vlib_cli_command_t * cmd)
     457             : {
     458           2 :   return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP4));
     459             : }
     460             : 
     461             : clib_error_t *
     462           1 : vnet_ip6_table_cmd (vlib_main_t * vm,
     463             :                     unformat_input_t * main_input, vlib_cli_command_t * cmd)
     464             : {
     465           1 :   return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP6));
     466             : }
     467             : 
     468             : clib_error_t *
     469           0 : vnet_show_ip_table_cmd (vlib_main_t *vm, unformat_input_t *main_input,
     470             :                         vlib_cli_command_t *cmd, fib_protocol_t fproto)
     471             : {
     472           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     473             :   fib_table_t *fib, *fibs;
     474           0 :   clib_error_t *error = NULL;
     475           0 :   u32 table_id = ~0, fib_index;
     476             :   /* Get a line of input. */
     477           0 :   if (unformat_user (main_input, unformat_line_input, line_input))
     478             :     {
     479           0 :       while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     480             :         {
     481           0 :           if (unformat (line_input, "%d", &table_id))
     482             :             ;
     483             :           else
     484             :             {
     485           0 :               error = unformat_parse_error (line_input);
     486           0 :               goto done;
     487             :             }
     488             :         }
     489           0 :       unformat_free (line_input);
     490             :     }
     491             : 
     492           0 :   fibs = (fproto == FIB_PROTOCOL_IP4) ? ip4_main.fibs : ip6_main.fibs;
     493             : 
     494           0 :   if (table_id != (u32) ~0)
     495             :     {
     496           0 :       fib_index = fib_table_find (fproto, table_id);
     497           0 :       if (fib_index == (u32) ~0)
     498             :         {
     499           0 :           error = clib_error_return (0, "Couldn't find table with table_id %u",
     500             :                                      table_id);
     501           0 :           goto done;
     502             :         }
     503             : 
     504           0 :       fib = fib_table_get (fib_index, fproto);
     505           0 :       vlib_cli_output (vm, "[%u] table_id:%u %v", fib->ft_index,
     506             :                        fib->ft_table_id, fib->ft_desc);
     507             :     }
     508             :   else
     509             :     {
     510           0 :       pool_foreach (fib, fibs)
     511           0 :         vlib_cli_output (vm, "[%u] table_id:%u %v", fib->ft_index,
     512             :                          fib->ft_table_id, fib->ft_desc);
     513             :     }
     514             : 
     515           0 : done:
     516           0 :   return error;
     517             : }
     518             : 
     519             : clib_error_t *
     520           0 : vnet_show_ip4_table_cmd (vlib_main_t *vm, unformat_input_t *main_input,
     521             :                          vlib_cli_command_t *cmd)
     522             : {
     523           0 :   return (vnet_show_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP4));
     524             : }
     525             : 
     526             : clib_error_t *
     527           0 : vnet_show_ip6_table_cmd (vlib_main_t *vm, unformat_input_t *main_input,
     528             :                          vlib_cli_command_t *cmd)
     529             : {
     530           0 :   return (vnet_show_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP6));
     531             : }
     532             : 
     533             : /* *INDENT-OFF* */
     534      272887 : VLIB_CLI_COMMAND (vlib_cli_ip_command, static) = {
     535             :   .path = "ip",
     536             :   .short_help = "Internet protocol (IP) commands",
     537             : };
     538             : /* *INDENT-ON* */
     539             : 
     540             : /* *INDENT-OFF* */
     541      272887 : VLIB_CLI_COMMAND (vlib_cli_ip6_command, static) = {
     542             :   .path = "ip6",
     543             :   .short_help = "Internet protocol version 6 (IPv6) commands",
     544             : };
     545             : /* *INDENT-ON* */
     546             : 
     547             : /* *INDENT-OFF* */
     548      272887 : VLIB_CLI_COMMAND (vlib_cli_show_ip_command, static) = {
     549             :   .path = "show ip",
     550             :   .short_help = "Internet protocol (IP) show commands",
     551             : };
     552             : /* *INDENT-ON* */
     553             : 
     554             : /* *INDENT-OFF* */
     555      272887 : VLIB_CLI_COMMAND (vlib_cli_show_ip6_command, static) = {
     556             :   .path = "show ip6",
     557             :   .short_help = "Internet protocol version 6 (IPv6) show commands",
     558             : };
     559             : /* *INDENT-ON* */
     560             : 
     561             : /*?
     562             :  * This command is used to add or delete IPv4 or IPv6 routes. All
     563             :  * IP Addresses ('<em><dst-ip-addr>/<width></em>',
     564             :  * '<em><next-hop-ip-addr></em>' and '<em><adj-hop-ip-addr></em>')
     565             :  * can be IPv4 or IPv6, but all must be of the same form in a single
     566             :  * command. To display the current set of routes, use the commands
     567             :  * '<em>show ip fib</em>' and '<em>show ip6 fib</em>'.
     568             :  *
     569             :  * @cliexpar
     570             :  * Example of how to add a straight forward static route:
     571             :  * @cliexcmd{ip route add 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
     572             :  * Example of how to delete a straight forward static route:
     573             :  * @cliexcmd{ip route del 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
     574             :  * Mainly for route add/del performance testing, one can add or delete
     575             :  * multiple routes by adding 'count N' to the previous item:
     576             :  * @cliexcmd{ip route add count 10 7.0.0.0/24 via 6.0.0.1 GigabitEthernet2/0/0}
     577             :  * Add multiple routes for the same destination to create equal-cost multipath:
     578             :  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0}
     579             :  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0}
     580             :  * For unequal-cost multipath, specify the desired weights. This
     581             :  * combination of weights results in 3/4 of the traffic following the
     582             :  * second path, 1/4 following the first path:
     583             :  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0 weight 1}
     584             :  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0 weight 3}
     585             :  * To add a route to a particular FIB table (VRF), use:
     586             :  * @cliexcmd{ip route add 172.16.24.0/24 table 7 via GigabitEthernet2/0/0}
     587             :  ?*/
     588             : /* *INDENT-OFF* */
     589      272887 : VLIB_CLI_COMMAND (ip_route_command, static) = {
     590             :   .path = "ip route",
     591             :   .short_help = "ip route [add|del] [count <n>] <dst-ip-addr>/<width> [table "
     592             :                 "<table-id>] via [next-hop-address] [next-hop-interface] "
     593             :                 "[next-hop-table <value>] [weight <value>] [preference "
     594             :                 "<value>] [udp-encap <value>] [ip4-lookup-in-table <value>] "
     595             :                 "[ip6-lookup-in-table <value>] [mpls-lookup-in-table <value>] "
     596             :                 "[resolve-via-host] [resolve-via-connected] [rx-ip4 "
     597             :                 "<interface>] [out-labels <value value value>]",
     598             :   .function = vnet_ip_route_cmd,
     599             :   .is_mp_safe = 1,
     600             : };
     601             : 
     602             : /* *INDENT-ON* */
     603             : /*?
     604             :  * This command is used to add or delete IPv4  Tables. All
     605             :  * Tables must be explicitly added before that can be used. Creating a
     606             :  * table will add both unicast and multicast FIBs
     607             :  *
     608             :  ?*/
     609             : /* *INDENT-OFF* */
     610      272887 : VLIB_CLI_COMMAND (ip4_table_command, static) = {
     611             :   .path = "ip table",
     612             :   .short_help = "ip table [add|del] <table-id>",
     613             :   .function = vnet_ip4_table_cmd,
     614             : };
     615             : /* *INDENT-ON* */
     616             : 
     617             : /* *INDENT-ON* */
     618             : /*?
     619             :  * This command is used to add or delete IPv4  Tables. All
     620             :  * Tables must be explicitly added before that can be used. Creating a
     621             :  * table will add both unicast and multicast FIBs
     622             :  *
     623             :  ?*/
     624             : /* *INDENT-OFF* */
     625      272887 : VLIB_CLI_COMMAND (ip6_table_command, static) = {
     626             :   .path = "ip6 table",
     627             :   .short_help = "ip6 table [add|del] <table-id>",
     628             :   .function = vnet_ip6_table_cmd,
     629             : };
     630             : 
     631      272887 : VLIB_CLI_COMMAND (show_ip4_table_command, static) = {
     632             :   .path = "show ip table",
     633             :   .short_help = "show ip table <table-id>",
     634             :   .function = vnet_show_ip4_table_cmd,
     635             : };
     636             : 
     637      272887 : VLIB_CLI_COMMAND (show_ip6_table_command, static) = {
     638             :   .path = "show ip6 table",
     639             :   .short_help = "show ip6 table <table-id>",
     640             :   .function = vnet_show_ip6_table_cmd,
     641             : };
     642             : 
     643             : static clib_error_t *
     644           2 : ip_table_bind_cmd (vlib_main_t * vm,
     645             :                    unformat_input_t * input,
     646             :                    vlib_cli_command_t * cmd,
     647             :                    fib_protocol_t fproto)
     648             : {
     649           2 :   vnet_main_t *vnm = vnet_get_main ();
     650           2 :   clib_error_t *error = 0;
     651             :   u32 sw_if_index, table_id;
     652             :   int rv;
     653             : 
     654           2 :   sw_if_index = ~0;
     655             : 
     656           2 :   if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
     657             :     {
     658           0 :       error = clib_error_return (0, "unknown interface `%U'",
     659             :                                  format_unformat_error, input);
     660           0 :       goto done;
     661             :     }
     662             : 
     663           2 :   if (unformat (input, "%d", &table_id))
     664             :     ;
     665             :   else
     666             :     {
     667           0 :       error = clib_error_return (0, "expected table id `%U'",
     668             :                                  format_unformat_error, input);
     669           0 :       goto done;
     670             :     }
     671             : 
     672           2 :   rv = ip_table_bind (fproto, sw_if_index, table_id);
     673             : 
     674           2 :   if (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE == rv)
     675             :     {
     676           0 :       error = clib_error_return (0, "IP addresses are still present on %U",
     677             :                                  format_vnet_sw_if_index_name,
     678             :                                  vnet_get_main(),
     679             :                                  sw_if_index);
     680             :     }
     681           2 :   else if (VNET_API_ERROR_NO_SUCH_FIB == rv)
     682             :     {
     683           0 :       error = clib_error_return (0, "no such table %d", table_id);
     684             :     }
     685           2 :   else if (0 != rv)
     686             :     {
     687           0 :       error = clib_error_return (0, "unknown error");
     688             :     }
     689             : 
     690           2 :  done:
     691           2 :   return error;
     692             : }
     693             : 
     694             : static clib_error_t *
     695           1 : ip4_table_bind_cmd (vlib_main_t * vm,
     696             :                     unformat_input_t * input,
     697             :                     vlib_cli_command_t * cmd)
     698             : {
     699           1 :   return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP4));
     700             : }
     701             : 
     702             : static clib_error_t *
     703           1 : ip6_table_bind_cmd (vlib_main_t * vm,
     704             :                     unformat_input_t * input,
     705             :                     vlib_cli_command_t * cmd)
     706             : {
     707           1 :   return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP6));
     708             : }
     709             : 
     710             : /*?
     711             :  * Place the indicated interface into the supplied IPv4 FIB table (also known
     712             :  * as a VRF). The FIB table must be created using "ip table add" already. To
     713             :  * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
     714             :  * FIB table will only be displayed if a route has been added to the table, or
     715             :  * an IP Address is assigned to an interface in the table (which adds a route
     716             :  * automatically).
     717             :  *
     718             :  * @note IP addresses added after setting the interface IP table are added to
     719             :  * the indicated FIB table. If an IP address is added prior to changing the
     720             :  * table then this is an error. The control plane must remove these addresses
     721             :  * first and then change the table. VPP will not automatically move the
     722             :  * addresses from the old to the new table as it does not know the validity
     723             :  * of such a change.
     724             :  *
     725             :  * @cliexpar
     726             :  * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id):
     727             :  * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
     728             :  ?*/
     729             : /* *INDENT-OFF* */
     730      272887 : VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
     731             : {
     732             :   .path = "set interface ip table",
     733             :   .function = ip4_table_bind_cmd,
     734             :   .short_help = "set interface ip table <interface> <table-id>",
     735             : };
     736             : /* *INDENT-ON* */
     737             : 
     738             : /*?
     739             :  * Place the indicated interface into the supplied IPv6 FIB table (also known
     740             :  * as a VRF). The FIB table must be created using "ip6 table add" already. To
     741             :  * display the current IPv6 FIB table, use the command '<em>show ip6 fib</em>'.
     742             :  * FIB table will only be displayed if a route has been added to the table, or
     743             :  * an IP Address is assigned to an interface in the table (which adds a route
     744             :  * automatically).
     745             :  *
     746             :  * @note IP addresses added after setting the interface IP table are added to
     747             :  * the indicated FIB table. If an IP address is added prior to changing the
     748             :  * table then this is an error. The control plane must remove these addresses
     749             :  * first and then change the table. VPP will not automatically move the
     750             :  * addresses from the old to the new table as it does not know the validity
     751             :  * of such a change.
     752             :  *
     753             :  * @cliexpar
     754             :  * Example of how to add an interface to an IPv6 FIB table (where 2 is the table-id):
     755             :  * @cliexcmd{set interface ip6 table GigabitEthernet2/0/0 2}
     756             :  ?*/
     757             : /* *INDENT-OFF* */
     758      272887 : VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) =
     759             : {
     760             :   .path = "set interface ip6 table",
     761             :   .function = ip6_table_bind_cmd,
     762             :   .short_help = "set interface ip6 table <interface> <table-id>"
     763             : };
     764             : /* *INDENT-ON* */
     765             : 
     766             : clib_error_t *
     767           0 : vnet_ip_mroute_cmd (vlib_main_t * vm,
     768             :                     unformat_input_t * main_input, vlib_cli_command_t * cmd)
     769             : {
     770           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     771           0 :   fib_route_path_t rpath, *rpaths = NULL;
     772           0 :   clib_error_t *error = NULL;
     773             :   u32 table_id, is_del, payload_proto;
     774             :   mfib_prefix_t pfx;
     775             :   u32 fib_index;
     776           0 :   mfib_entry_flags_t eflags = 0;
     777             :   u32 gcount, scount, ss, gg, incr;
     778             :   f64 timet[2];
     779           0 :   u32 rpf_id = MFIB_RPF_ID_NONE;
     780             : 
     781           0 :   gcount = scount = 1;
     782           0 :   is_del = 0;
     783           0 :   table_id = 0;
     784           0 :   clib_memset (&pfx, 0, sizeof (pfx));
     785           0 :   clib_memset (&rpath, 0, sizeof (rpath));
     786           0 :   rpath.frp_sw_if_index = ~0;
     787             : 
     788             :   /* Get a line of input. */
     789           0 :   if (!unformat_user (main_input, unformat_line_input, line_input))
     790           0 :     return 0;
     791             : 
     792           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     793             :     {
     794           0 :       if (unformat (line_input, "table %d", &table_id))
     795             :         ;
     796           0 :       else if (unformat (line_input, "del"))
     797           0 :         is_del = 1;
     798           0 :       else if (unformat (line_input, "add"))
     799           0 :         is_del = 0;
     800           0 :       else if (unformat (line_input, "rpf-id %d", &rpf_id))
     801             :         ;
     802           0 :       else if (unformat (line_input, "scount %d", &scount))
     803             :         ;
     804           0 :       else if (unformat (line_input, "gcount %d", &gcount))
     805             :         ;
     806           0 :       else if (unformat (line_input, "%U %U",
     807             :                          unformat_ip4_address,
     808             :                          &pfx.fp_src_addr.ip4,
     809             :                          unformat_ip4_address, &pfx.fp_grp_addr.ip4))
     810             :         {
     811           0 :           payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP4;
     812           0 :           pfx.fp_len = 64;
     813             :         }
     814           0 :       else if (unformat (line_input, "%U %U",
     815             :                          unformat_ip6_address,
     816             :                          &pfx.fp_src_addr.ip6,
     817             :                          unformat_ip6_address, &pfx.fp_grp_addr.ip6))
     818             :         {
     819           0 :           payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP6;
     820           0 :           pfx.fp_len = 256;
     821             :         }
     822           0 :       else if (unformat (line_input, "%U/%d",
     823             :                          unformat_ip4_address,
     824             :                          &pfx.fp_grp_addr.ip4, &pfx.fp_len))
     825             :         {
     826           0 :           clib_memset (&pfx.fp_src_addr.ip4, 0, sizeof (pfx.fp_src_addr.ip4));
     827           0 :           payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP4;
     828             :         }
     829           0 :       else if (unformat (line_input, "%U/%d",
     830             :                          unformat_ip6_address,
     831             :                          &pfx.fp_grp_addr.ip6, &pfx.fp_len))
     832             :         {
     833           0 :           clib_memset (&pfx.fp_src_addr.ip6, 0, sizeof (pfx.fp_src_addr.ip6));
     834           0 :           payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP6;
     835             :         }
     836           0 :       else if (unformat (line_input, "%U",
     837             :                          unformat_ip4_address, &pfx.fp_grp_addr.ip4))
     838             :         {
     839           0 :           clib_memset (&pfx.fp_src_addr.ip4, 0, sizeof (pfx.fp_src_addr.ip4));
     840           0 :           payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP4;
     841           0 :           pfx.fp_len = 32;
     842             :         }
     843           0 :       else if (unformat (line_input, "%U",
     844             :                          unformat_ip6_address, &pfx.fp_grp_addr.ip6))
     845             :         {
     846           0 :           clib_memset (&pfx.fp_src_addr.ip6, 0, sizeof (pfx.fp_src_addr.ip6));
     847           0 :           payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP6;
     848           0 :           pfx.fp_len = 128;
     849             :         }
     850           0 :       else if (unformat (line_input, "via local Forward"))
     851             :         {
     852           0 :           clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr));
     853           0 :           rpath.frp_sw_if_index = ~0;
     854           0 :           rpath.frp_weight = 1;
     855           0 :           rpath.frp_flags |= FIB_ROUTE_PATH_LOCAL;
     856             :           /*
     857             :            * set the path proto appropriately for the prefix
     858             :            */
     859           0 :           rpath.frp_proto = fib_proto_to_dpo (pfx.fp_proto);
     860           0 :           rpath.frp_mitf_flags = MFIB_ITF_FLAG_FORWARD;
     861             : 
     862           0 :           vec_add1 (rpaths, rpath);
     863             :         }
     864           0 :       else if (unformat (line_input, "via %U",
     865             :                          unformat_fib_route_path, &rpath, &payload_proto))
     866             :         {
     867           0 :           vec_add1 (rpaths, rpath);
     868             :         }
     869           0 :       else if (unformat (line_input, "%U",
     870             :                          unformat_mfib_entry_flags, &eflags))
     871             :         ;
     872             :       else
     873             :         {
     874           0 :           error = unformat_parse_error (line_input);
     875           0 :           goto done;
     876             :         }
     877             :     }
     878             : 
     879           0 :   if (~0 == table_id)
     880             :     {
     881             :       /*
     882             :        * if no table_id is passed we will manipulate the default
     883             :        */
     884           0 :       fib_index = 0;
     885             :     }
     886             :   else
     887             :     {
     888           0 :       fib_index = mfib_table_find (pfx.fp_proto, table_id);
     889             : 
     890           0 :       if (~0 == fib_index)
     891             :         {
     892           0 :           error = clib_error_return (0, "Nonexistent table id %d", table_id);
     893           0 :           goto done;
     894             :         }
     895             :     }
     896             : 
     897           0 :   timet[0] = vlib_time_now (vm);
     898             : 
     899           0 :   if (FIB_PROTOCOL_IP4 == pfx.fp_proto)
     900             :     {
     901           0 :       incr = 1 << (32 - (pfx.fp_len % 32));
     902             :     }
     903             :   else
     904             :     {
     905           0 :       incr = 1 << (128 - (pfx.fp_len % 128));
     906             :     }
     907             : 
     908           0 :   for (ss = 0; ss < scount; ss++)
     909             :     {
     910           0 :       for (gg = 0; gg < gcount; gg++)
     911             :         {
     912           0 :           if (is_del && 0 == vec_len (rpaths))
     913             :             {
     914             :               /* no path provided => route delete */
     915           0 :               mfib_table_entry_delete (fib_index, &pfx, MFIB_SOURCE_CLI);
     916             :             }
     917           0 :           else if (eflags || (MFIB_RPF_ID_NONE != rpf_id))
     918             :             {
     919           0 :               mfib_table_entry_update (fib_index, &pfx, MFIB_SOURCE_CLI,
     920             :                                        rpf_id, eflags);
     921             :             }
     922             :           else
     923             :             {
     924           0 :               if (is_del)
     925           0 :                 mfib_table_entry_path_remove (fib_index,
     926             :                                               &pfx, MFIB_SOURCE_CLI, rpaths);
     927             :               else
     928           0 :                 mfib_table_entry_path_update (fib_index, &pfx, MFIB_SOURCE_CLI,
     929             :                                               MFIB_ENTRY_FLAG_NONE, rpaths);
     930             :             }
     931             : 
     932           0 :           if (FIB_PROTOCOL_IP4 == pfx.fp_proto)
     933             :             {
     934           0 :               pfx.fp_grp_addr.ip4.as_u32 =
     935           0 :                 clib_host_to_net_u32 (incr +
     936           0 :                                       clib_net_to_host_u32 (pfx.
     937             :                                                             fp_grp_addr.ip4.
     938             :                                                             as_u32));
     939             :             }
     940             :           else
     941             :             {
     942           0 :               int bucket = (incr < 64 ? 0 : 1);
     943           0 :               pfx.fp_grp_addr.ip6.as_u64[bucket] =
     944           0 :                 clib_host_to_net_u64 (incr +
     945           0 :                                       clib_net_to_host_u64 (pfx.
     946             :                                                             fp_grp_addr.ip6.as_u64
     947             :                                                             [bucket]));
     948             : 
     949             :             }
     950             :         }
     951           0 :       if (FIB_PROTOCOL_IP4 == pfx.fp_proto)
     952             :         {
     953           0 :           pfx.fp_src_addr.ip4.as_u32 =
     954           0 :             clib_host_to_net_u32 (1 +
     955           0 :                                   clib_net_to_host_u32 (pfx.fp_src_addr.
     956             :                                                         ip4.as_u32));
     957             :         }
     958             :       else
     959             :         {
     960           0 :           pfx.fp_src_addr.ip6.as_u64[1] =
     961           0 :             clib_host_to_net_u64 (1 +
     962           0 :                                   clib_net_to_host_u64 (pfx.fp_src_addr.
     963             :                                                         ip6.as_u64[1]));
     964             :         }
     965             :     }
     966             : 
     967           0 :   timet[1] = vlib_time_now (vm);
     968             : 
     969           0 :   if (scount > 1 || gcount > 1)
     970           0 :     vlib_cli_output (vm, "%.6e routes/sec",
     971           0 :                      (scount * gcount) / (timet[1] - timet[0]));
     972             : 
     973           0 : done:
     974           0 :   vec_free (rpaths);
     975           0 :   unformat_free (line_input);
     976             : 
     977           0 :   return error;
     978             : }
     979             : 
     980             : /*?
     981             :  * This command is used to add or delete IPv4 or IPv6  multicast routes. All
     982             :  * IP Addresses ('<em><dst-ip-addr>/<width></em>',
     983             :  * '<em><next-hop-ip-addr></em>' and '<em><adj-hop-ip-addr></em>')
     984             :  * can be IPv4 or IPv6, but all must be of the same form in a single
     985             :  * command. To display the current set of routes, use the commands
     986             :  * '<em>show ip mfib</em>' and '<em>show ip6 mfib</em>'.
     987             :  * The full set of support flags for interfaces and route is shown via;
     988             :  * '<em>show mfib route flags</em>' and '<em>show mfib itf flags</em>'
     989             :  * respectively.
     990             :  * @cliexpar
     991             :  * Example of how to add a forwarding interface to a route (and create the
     992             :  * route if it does not exist)
     993             :  * @cliexcmd{ip mroute add 232.1.1.1 via GigabitEthernet2/0/0 Forward}
     994             :  * Example of how to add an accepting interface to a route (and create the
     995             :  * route if it does not exist)
     996             :  * @cliexcmd{ip mroute add 232.1.1.1 via GigabitEthernet2/0/1 Accept}
     997             :  * Example of changing the route's flags to send signals via the API
     998             :  * @cliexcmd{ip mroute add 232.1.1.1 Signal}
     999             : 
    1000             :  ?*/
    1001             : /* *INDENT-OFF* */
    1002      272887 : VLIB_CLI_COMMAND (ip_mroute_command, static) =
    1003             : {
    1004             :   .path = "ip mroute",
    1005             :   .short_help = "ip mroute [add|del] <dst-ip-addr>/<width> [table <table-id>] [rpf-id <ID>] [via <next-hop-ip-addr> [<interface>],",
    1006             :   .function = vnet_ip_mroute_cmd,
    1007             :   .is_mp_safe = 1,
    1008             : };
    1009             : /* *INDENT-ON* */
    1010             : 
    1011             : /*
    1012             :  * fd.io coding-style-patch-verification: ON
    1013             :  *
    1014             :  * Local Variables:
    1015             :  * eval: (c-set-style "gnu")
    1016             :  * End:
    1017             :  */

Generated by: LCOV version 1.14