LCOV - code coverage report
Current view: top level - plugins/lisp/lisp-gpe - lisp_gpe.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 42 299 14.0 %
Date: 2023-07-05 22:20:52 Functions: 22 36 61.1 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : /**
      16             :  * @file
      17             :  * @brief Common utility functions for IPv4, IPv6 and L2 LISP-GPE tunnels.
      18             :  *
      19             :  */
      20             : 
      21             : #include <lisp/lisp-gpe/lisp_gpe.h>
      22             : #include <lisp/lisp-gpe/lisp_gpe_fwd_entry.h>
      23             : #include <lisp/lisp-gpe/lisp_gpe_adjacency.h>
      24             : #include <lisp/lisp-gpe/lisp_gpe_tenant.h>
      25             : #include <vnet/fib/fib_path_list.h>
      26             : #include <vnet/fib/fib_table.h>
      27             : #include <vnet/fib/fib_internal.h>
      28             : 
      29             : /** LISP-GPE global state */
      30             : lisp_gpe_main_t lisp_gpe_main;
      31             : 
      32             : 
      33             : /** CLI command to add/del forwarding entry. */
      34             : static clib_error_t *
      35           0 : lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm,
      36             :                                        unformat_input_t * input,
      37             :                                        vlib_cli_command_t * cmd)
      38             : {
      39           0 :   unformat_input_t _line_input, *line_input = &_line_input;
      40           0 :   u8 is_add = 1;
      41             :   ip_address_t lloc, rloc;
      42           0 :   clib_error_t *error = 0;
      43           0 :   gid_address_t _reid, *reid = &_reid, _leid, *leid = &_leid;
      44           0 :   u8 reid_set = 0, leid_set = 0, is_negative = 0, dp_table_set = 0,
      45           0 :     vni_set = 0;
      46           0 :   u32 vni = 0, dp_table = 0, action = ~0, w;
      47           0 :   locator_pair_t pair, *pairs = 0;
      48             :   int rv;
      49             : 
      50           0 :   clib_memset (leid, 0, sizeof (*leid));
      51           0 :   clib_memset (reid, 0, sizeof (*reid));
      52             : 
      53             :   /* Get a line of input. */
      54           0 :   if (!unformat_user (input, unformat_line_input, line_input))
      55           0 :     return 0;
      56             : 
      57           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
      58             :     {
      59           0 :       if (unformat (line_input, "del"))
      60           0 :         is_add = 0;
      61           0 :       else if (unformat (line_input, "add"))
      62           0 :         is_add = 1;
      63           0 :       else if (unformat (line_input, "leid %U", unformat_gid_address, leid))
      64             :         {
      65           0 :           leid_set = 1;
      66             :         }
      67           0 :       else if (unformat (line_input, "reid %U", unformat_gid_address, reid))
      68             :         {
      69           0 :           reid_set = 1;
      70             :         }
      71           0 :       else if (unformat (line_input, "vni %u", &vni))
      72             :         {
      73           0 :           gid_address_vni (leid) = vni;
      74           0 :           gid_address_vni (reid) = vni;
      75           0 :           vni_set = 1;
      76             :         }
      77           0 :       else if (unformat (line_input, "vrf %u", &dp_table))
      78             :         {
      79           0 :           dp_table_set = 1;
      80             :         }
      81           0 :       else if (unformat (line_input, "bd %u", &dp_table))
      82             :         {
      83           0 :           dp_table_set = 1;
      84             :         }
      85           0 :       else if (unformat (line_input, "negative action %U",
      86             :                          unformat_negative_mapping_action, &action))
      87             :         {
      88           0 :           is_negative = 1;
      89             :         }
      90           0 :       else if (unformat (line_input, "loc-pair %U %U w %d",
      91             :                          unformat_ip_address, &lloc,
      92             :                          unformat_ip_address, &rloc, &w))
      93             :         {
      94           0 :           ip_address_copy (&pair.lcl_loc, &lloc);
      95           0 :           ip_address_copy (&pair.rmt_loc, &rloc);
      96           0 :           pair.weight = w;
      97           0 :           pair.priority = 0;
      98           0 :           vec_add1 (pairs, pair);
      99             :         }
     100             :       else
     101             :         {
     102           0 :           error = unformat_parse_error (line_input);
     103           0 :           vlib_cli_output (vm, "parse error: '%U'",
     104             :                            format_unformat_error, line_input);
     105           0 :           goto done;
     106             :         }
     107             :     }
     108             : 
     109           0 :   if (!reid_set)
     110             :     {
     111           0 :       vlib_cli_output (vm, "remote eid must be set!");
     112           0 :       goto done;
     113             :     }
     114             : 
     115           0 :   if (gid_address_type (reid) != GID_ADDR_NSH && (!vni_set || !dp_table_set))
     116             :     {
     117           0 :       vlib_cli_output (vm, "vni and vrf/bd must be set!");
     118           0 :       goto done;
     119             :     }
     120             : 
     121           0 :   if (is_negative)
     122             :     {
     123           0 :       if (~0 == action)
     124             :         {
     125           0 :           vlib_cli_output (vm, "no action set for negative tunnel!");
     126           0 :           goto done;
     127             :         }
     128             :     }
     129             :   else
     130             :     {
     131           0 :       if (vec_len (pairs) == 0)
     132             :         {
     133           0 :           vlib_cli_output (vm, "expected ip4/ip6 locators");
     134           0 :           goto done;
     135             :         }
     136             :     }
     137             : 
     138           0 :   if (!leid_set)
     139             :     {
     140             :       /* if leid not set, make sure it's the same AFI like reid */
     141           0 :       gid_address_type (leid) = gid_address_type (reid);
     142           0 :       if (GID_ADDR_IP_PREFIX == gid_address_type (reid))
     143           0 :         gid_address_ip_version (leid) = gid_address_ip_version (reid);
     144             :     }
     145             : 
     146             :   /* add fwd entry */
     147           0 :   vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
     148           0 :   clib_memset (a, 0, sizeof (a[0]));
     149             : 
     150           0 :   a->is_add = is_add;
     151           0 :   a->is_negative = is_negative;
     152           0 :   a->vni = vni;
     153           0 :   a->table_id = dp_table;
     154           0 :   gid_address_copy (&a->lcl_eid, leid);
     155           0 :   gid_address_copy (&a->rmt_eid, reid);
     156           0 :   a->locator_pairs = pairs;
     157           0 :   a->action = action;
     158             : 
     159           0 :   rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
     160           0 :   if (0 != rv)
     161             :     {
     162           0 :       vlib_cli_output (vm, "failed to %s gpe tunnel!",
     163             :                        is_add ? "add" : "delete");
     164             :     }
     165             : 
     166           0 : done:
     167           0 :   unformat_free (line_input);
     168           0 :   vec_free (pairs);
     169           0 :   return error;
     170             : }
     171             : 
     172             : /* *INDENT-OFF* */
     173      116069 : VLIB_CLI_COMMAND (lisp_gpe_add_del_fwd_entry_command, static) = {
     174             :   .path = "gpe entry",
     175             :   .short_help = "gpe entry add/del vni <vni> vrf/bd <id> [leid <leid>]"
     176             :       "reid <reid> [loc-pair <lloc> <rloc> w <weight>] "
     177             :       "[negative action <action>]",
     178             :   .function = lisp_gpe_add_del_fwd_entry_command_fn,
     179             : };
     180             : /* *INDENT-ON* */
     181             : 
     182             : /** Check if LISP-GPE is enabled. */
     183             : u8
     184           2 : vnet_lisp_gpe_enable_disable_status (void)
     185             : {
     186           2 :   lisp_gpe_main_t *lgm = &lisp_gpe_main;
     187             : 
     188           2 :   return lgm->is_en;
     189             : }
     190             : 
     191             : /** Enable/disable LISP-GPE. */
     192             : clib_error_t *
     193           1 : vnet_lisp_gpe_enable_disable (vnet_lisp_gpe_enable_disable_args_t * a)
     194             : {
     195           1 :   lisp_gpe_main_t *lgm = &lisp_gpe_main;
     196           1 :   vlib_main_t *vm = vlib_get_main ();
     197             : 
     198           1 :   if (a->is_en)
     199             :     {
     200           1 :       lgm->is_en = 1;
     201           1 :       udp_register_dst_port (vm, UDP_DST_PORT_lisp_gpe,
     202             :                              lisp_gpe_ip4_input_node.index, 1 /* is_ip4 */ );
     203           1 :       udp_register_dst_port (vm, UDP_DST_PORT_lisp_gpe6,
     204             :                              lisp_gpe_ip6_input_node.index, 0 /* is_ip4 */ );
     205             :     }
     206             :   else
     207             :     {
     208             :       /* remove all entries */
     209           0 :       vnet_lisp_gpe_fwd_entry_flush ();
     210             : 
     211             :       /* disable all l3 ifaces */
     212           0 :       lisp_gpe_tenant_flush ();
     213             : 
     214           0 :       udp_unregister_dst_port (vm, UDP_DST_PORT_lisp_gpe, 0 /* is_ip4 */ );
     215           0 :       udp_unregister_dst_port (vm, UDP_DST_PORT_lisp_gpe6, 1 /* is_ip4 */ );
     216           0 :       lgm->is_en = 0;
     217             :     }
     218             : 
     219           1 :   return 0;
     220             : }
     221             : 
     222             : /** Set GPE encapsulation mode. */
     223             : int
     224           0 : vnet_gpe_set_encap_mode (gpe_encap_mode_t mode)
     225             : {
     226           0 :   lisp_gpe_main_t *lgm = &lisp_gpe_main;
     227             : 
     228           0 :   if (mode >= GPE_ENCAP_COUNT)
     229           0 :     return VNET_API_ERROR_INVALID_GPE_MODE;
     230             : 
     231           0 :   if (pool_elts (lgm->lisp_fwd_entry_pool) != 0)
     232           0 :     return VNET_API_ERROR_LISP_GPE_ENTRIES_PRESENT;
     233             : 
     234           0 :   lgm->encap_mode = mode;
     235           0 :   return 0;
     236             : }
     237             : 
     238             : /** CLI command to set GPE encap */
     239             : static clib_error_t *
     240           0 : gpe_set_encap_mode_command_fn (vlib_main_t * vm,
     241             :                                unformat_input_t * input,
     242             :                                vlib_cli_command_t * cmd)
     243             : {
     244           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     245           0 :   gpe_encap_mode_t mode = GPE_ENCAP_COUNT;
     246             :   vnet_api_error_t rv;
     247             : 
     248             :   /* Get a line of input. */
     249           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     250           0 :     return 0;
     251             : 
     252           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     253             :     {
     254           0 :       if (unformat (line_input, "lisp"))
     255           0 :         mode = GPE_ENCAP_LISP;
     256           0 :       else if (unformat (line_input, "vxlan"))
     257           0 :         mode = GPE_ENCAP_VXLAN;
     258             :       else
     259             :         {
     260           0 :           return clib_error_return (0, "parse error: '%U'",
     261             :                                     format_unformat_error, line_input);
     262             :         }
     263             :     }
     264           0 :   rv = vnet_gpe_set_encap_mode (mode);
     265           0 :   if (rv)
     266             :     {
     267           0 :       return clib_error_return (0,
     268             :                                 "Error: invalid mode or GPE entries are present!");
     269             :     }
     270             : 
     271           0 :   return 0;
     272             : }
     273             : 
     274             : /* *INDENT-OFF* */
     275      116069 : VLIB_CLI_COMMAND (gpe_set_encap_mode_command, static) = {
     276             :   .path = "gpe encap",
     277             :   .short_help = "gpe encap [lisp|vxlan]",
     278             :   .function = gpe_set_encap_mode_command_fn,
     279             : };
     280             : /* *INDENT-ON* */
     281             : 
     282             : /** Format GPE encap mode. */
     283             : u8 *
     284           0 : format_vnet_gpe_encap_mode (u8 * s, va_list * args)
     285             : {
     286           0 :   lisp_gpe_main_t *lgm = &lisp_gpe_main;
     287             : 
     288           0 :   switch (lgm->encap_mode)
     289             :     {
     290           0 :     case GPE_ENCAP_LISP:
     291           0 :       return format (s, "lisp");
     292           0 :     case GPE_ENCAP_VXLAN:
     293           0 :       return format (s, "vxlan");
     294           0 :     default:
     295           0 :       return 0;
     296             :     }
     297             :   return 0;
     298             : }
     299             : 
     300             : /** CLI command to show GPE encap */
     301             : static clib_error_t *
     302           0 : gpe_show_encap_mode_command_fn (vlib_main_t * vm,
     303             :                                 unformat_input_t * input,
     304             :                                 vlib_cli_command_t * cmd)
     305             : {
     306           0 :   vlib_cli_output (vm, "encap mode: %U", format_vnet_gpe_encap_mode);
     307           0 :   return 0;
     308             : }
     309             : 
     310             : /* *INDENT-OFF* */
     311      116069 : VLIB_CLI_COMMAND (gpe_show_encap_mode_command, static) = {
     312             :   .path = "show gpe encap",
     313             :   .short_help = "show GPE encapulation mode",
     314             :   .function = gpe_show_encap_mode_command_fn,
     315             : };
     316             : /* *INDENT-ON* */
     317             : 
     318             : /** CLI command to enable/disable LISP-GPE. */
     319             : static clib_error_t *
     320           0 : lisp_gpe_enable_disable_command_fn (vlib_main_t * vm,
     321             :                                     unformat_input_t * input,
     322             :                                     vlib_cli_command_t * cmd)
     323             : {
     324           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     325           0 :   u8 is_en = 1;
     326           0 :   vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a;
     327           0 :   clib_error_t *error = NULL;
     328             : 
     329             :   /* Get a line of input. */
     330           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     331           0 :     return clib_error_return (0, "expected enable | disable");
     332             : 
     333           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     334             :     {
     335           0 :       if (unformat (line_input, "enable"))
     336           0 :         is_en = 1;
     337           0 :       else if (unformat (line_input, "disable"))
     338           0 :         is_en = 0;
     339             :       else
     340             :         {
     341           0 :           error = clib_error_return (0, "parse error: '%U'",
     342             :                                      format_unformat_error, line_input);
     343           0 :           goto done;
     344             :         }
     345             :     }
     346           0 :   a->is_en = is_en;
     347           0 :   error = vnet_lisp_gpe_enable_disable (a);
     348             : 
     349           0 : done:
     350           0 :   unformat_free (line_input);
     351             : 
     352           0 :   return error;
     353             : }
     354             : 
     355             : /* *INDENT-OFF* */
     356      116069 : VLIB_CLI_COMMAND (enable_disable_lisp_gpe_command, static) = {
     357             :   .path = "gpe",
     358             :   .short_help = "gpe [enable|disable]",
     359             :   .function = lisp_gpe_enable_disable_command_fn,
     360             : };
     361             : /* *INDENT-ON* */
     362             : 
     363             : /** CLI command to show LISP-GPE interfaces. */
     364             : static clib_error_t *
     365           0 : lisp_show_iface_command_fn (vlib_main_t * vm,
     366             :                             unformat_input_t * input,
     367             :                             vlib_cli_command_t * cmd)
     368             : {
     369           0 :   lisp_gpe_main_t *lgm = &lisp_gpe_main;
     370             :   hash_pair_t *p;
     371             : 
     372           0 :   vlib_cli_output (vm, "%=10s%=12s", "vrf", "hw_if_index");
     373             : 
     374             :   /* *INDENT-OFF* */
     375           0 :   hash_foreach_pair (p, lgm->l3_ifaces.hw_if_index_by_dp_table, ({
     376             :     vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]);
     377             :   }));
     378             :   /* *INDENT-ON* */
     379             : 
     380           0 :   if (0 != lgm->l2_ifaces.hw_if_index_by_dp_table)
     381             :     {
     382           0 :       vlib_cli_output (vm, "%=10s%=12s", "bd_id", "hw_if_index");
     383             :       /* *INDENT-OFF* */
     384           0 :       hash_foreach_pair (p, lgm->l2_ifaces.hw_if_index_by_dp_table, ({
     385             :         vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]);
     386             :       }));
     387             :       /* *INDENT-ON* */
     388             :     }
     389           0 :   return 0;
     390             : }
     391             : 
     392             : /* *INDENT-OFF* */
     393      116069 : VLIB_CLI_COMMAND (lisp_show_iface_command) = {
     394             :     .path = "show gpe interface",
     395             :     .short_help = "show gpe interface",
     396             :     .function = lisp_show_iface_command_fn,
     397             : };
     398             : /* *INDENT-ON* */
     399             : 
     400             : /** CLI command to show GPE fwd native route path. */
     401             : static clib_error_t *
     402           0 : gpe_show_native_fwd_rpath_command_fn (vlib_main_t * vm,
     403             :                                       unformat_input_t * input,
     404             :                                       vlib_cli_command_t * cmd)
     405             : {
     406           0 :   lisp_gpe_main_t *lgm = &lisp_gpe_main;
     407             :   fib_route_path_t *rpath;
     408             : 
     409           0 :   if (vec_len (lgm->native_fwd_rpath[AF_IP4]))
     410             :     {
     411           0 :       vec_foreach (rpath, lgm->native_fwd_rpath[AF_IP4])
     412             :       {
     413           0 :         vlib_cli_output (vm, "nh: %U fib_index %u sw_if_index %u",
     414             :                          format_ip46_address, &rpath->frp_addr,
     415             :                          IP46_TYPE_IP4, rpath->frp_fib_index,
     416             :                          rpath->frp_sw_if_index);
     417             :       }
     418             :     }
     419           0 :   if (vec_len (lgm->native_fwd_rpath[AF_IP6]))
     420             :     {
     421           0 :       vec_foreach (rpath, lgm->native_fwd_rpath[AF_IP6])
     422             :       {
     423           0 :         vlib_cli_output (vm, "nh: %U fib_index %u sw_if_index %u",
     424             :                          format_ip46_address, &rpath->frp_addr, IP46_TYPE_IP6,
     425             :                          rpath->frp_fib_index, rpath->frp_sw_if_index);
     426             :       }
     427             :     }
     428           0 :   return 0;
     429             : }
     430             : 
     431             : /* *INDENT-OFF* */
     432      116069 : VLIB_CLI_COMMAND (gpe_show_native_fwd_rpath_command) = {
     433             :     .path = "show gpe native-forward",
     434             :     .short_help = "show gpe native-forward",
     435             :     .function = gpe_show_native_fwd_rpath_command_fn,
     436             : };
     437             : /* *INDENT-ON* */
     438             : 
     439             : void
     440           0 : gpe_update_native_fwd_path (u8 ip_version)
     441             : {
     442           0 :   lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
     443             :   lisp_gpe_fwd_entry_t *lfe;
     444             :   fib_prefix_t fib_prefix;
     445             :   u32 *lfei;
     446             : 
     447           0 :   vec_foreach (lfei, lgm->native_fwd_lfes[ip_version])
     448             :   {
     449           0 :     lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, lfei[0]);
     450           0 :     ip_prefix_to_fib_prefix (&lfe->key->rmt.ippref, &fib_prefix);
     451           0 :     fib_table_entry_update (lfe->eid_fib_index, &fib_prefix, FIB_SOURCE_LISP,
     452             :                             FIB_ENTRY_FLAG_NONE,
     453             :                             lgm->native_fwd_rpath[ip_version]);
     454             :   }
     455           0 : }
     456             : 
     457             : int
     458           0 : vnet_gpe_add_del_native_fwd_rpath (vnet_gpe_native_fwd_rpath_args_t * a)
     459             : {
     460           0 :   lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
     461             :   fib_route_path_t *rpath;
     462             :   u8 ip_version;
     463             : 
     464           0 :   ip_version = a->rpath.frp_proto == DPO_PROTO_IP4 ? AF_IP4 : AF_IP6;
     465             : 
     466           0 :   if (a->is_add)
     467             :     {
     468           0 :       vec_add1 (lgm->native_fwd_rpath[ip_version], a->rpath);
     469             :     }
     470             :   else
     471             :     {
     472           0 :       vec_foreach (rpath, lgm->native_fwd_rpath[ip_version])
     473             :       {
     474           0 :         if (!fib_route_path_cmp (rpath, &a->rpath))
     475             :           {
     476           0 :             vec_del1 (lgm->native_fwd_rpath[ip_version],
     477             :                       rpath - lgm->native_fwd_rpath[ip_version]);
     478           0 :             break;
     479             :           }
     480             :       }
     481             :     }
     482           0 :   gpe_update_native_fwd_path (ip_version);
     483           0 :   return 0;
     484             : }
     485             : 
     486             : /**
     487             :  * CLI command to add action for native forward.
     488             :  */
     489             : static clib_error_t *
     490           0 : gpe_native_forward_command_fn (vlib_main_t * vm, unformat_input_t * input,
     491             :                                vlib_cli_command_t * cmd)
     492             : {
     493           0 :   vnet_main_t *vnm = vnet_get_main ();
     494           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     495             :   vnet_api_error_t rv;
     496             :   fib_route_path_t rpath;
     497           0 :   u32 table_id = ~0;
     498           0 :   vnet_gpe_native_fwd_rpath_args_t _a, *a = &_a;
     499           0 :   u8 is_add = 1;
     500           0 :   clib_error_t *error = 0;
     501             : 
     502             :   /* Get a line of input. */
     503           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     504           0 :     return 0;
     505             : 
     506           0 :   clib_memset (&rpath, 0, sizeof (rpath));
     507             : 
     508           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     509             :     {
     510           0 :       if (unformat (line_input, "table %d", &table_id))
     511             :         ;
     512           0 :       else if (unformat (line_input, "del"))
     513           0 :         is_add = 0;
     514           0 :       else if (unformat (line_input, "via %U %U",
     515             :                          unformat_ip4_address,
     516             :                          &rpath.frp_addr.ip4,
     517             :                          unformat_vnet_sw_interface, vnm,
     518             :                          &rpath.frp_sw_if_index))
     519             :         {
     520           0 :           rpath.frp_weight = 1;
     521           0 :           rpath.frp_proto = DPO_PROTO_IP4;
     522             :         }
     523           0 :       else if (unformat (line_input, "via %U %U",
     524             :                          unformat_ip6_address,
     525             :                          &rpath.frp_addr.ip6,
     526             :                          unformat_vnet_sw_interface, vnm,
     527             :                          &rpath.frp_sw_if_index))
     528             :         {
     529           0 :           rpath.frp_weight = 1;
     530           0 :           rpath.frp_proto = DPO_PROTO_IP6;
     531             :         }
     532           0 :       else if (unformat (line_input, "via %U",
     533             :                          unformat_ip4_address, &rpath.frp_addr.ip4))
     534             :         {
     535           0 :           rpath.frp_weight = 1;
     536           0 :           rpath.frp_sw_if_index = ~0;
     537           0 :           rpath.frp_proto = DPO_PROTO_IP4;
     538             :         }
     539           0 :       else if (unformat (line_input, "via %U",
     540             :                          unformat_ip6_address, &rpath.frp_addr.ip6))
     541             :         {
     542           0 :           rpath.frp_weight = 1;
     543           0 :           rpath.frp_sw_if_index = ~0;
     544           0 :           rpath.frp_proto = DPO_PROTO_IP6;
     545             :         }
     546             :       else
     547             :         {
     548           0 :           return clib_error_return (0, "parse error: '%U'",
     549             :                                     format_unformat_error, line_input);
     550             :         }
     551             :     }
     552             : 
     553           0 :   if ((u32) ~ 0 == table_id)
     554             :     {
     555           0 :       rpath.frp_fib_index = 0;
     556             :     }
     557             :   else
     558             :     {
     559           0 :       rpath.frp_fib_index =
     560           0 :         fib_table_find (dpo_proto_to_fib (rpath.frp_proto), table_id);
     561           0 :       if ((u32) ~ 0 == rpath.frp_fib_index)
     562             :         {
     563           0 :           error = clib_error_return (0, "Nonexistent table id %d", table_id);
     564           0 :           goto done;
     565             :         }
     566             :     }
     567             : 
     568           0 :   a->rpath = rpath;
     569           0 :   a->is_add = is_add;
     570             : 
     571           0 :   rv = vnet_gpe_add_del_native_fwd_rpath (a);
     572           0 :   if (rv)
     573             :     {
     574           0 :       return clib_error_return (0, "Error: couldn't add path!");
     575             :     }
     576             : 
     577           0 : done:
     578           0 :   return error;
     579             : }
     580             : 
     581             : /* *INDENT-OFF* */
     582      116069 : VLIB_CLI_COMMAND (gpe_native_forward_command) = {
     583             :     .path = "gpe native-forward",
     584             :     .short_help = "gpe native-forward [del] via <nh-ip-addr> [iface] "
     585             :         "[table <table>]",
     586             :     .function = gpe_native_forward_command_fn,
     587             : };
     588             : /* *INDENT-ON* */
     589             : 
     590             : /** Format LISP-GPE status. */
     591             : u8 *
     592           0 : format_vnet_lisp_gpe_status (u8 * s, va_list * args)
     593             : {
     594           0 :   lisp_gpe_main_t *lgm = &lisp_gpe_main;
     595           0 :   return format (s, "%s", lgm->is_en ? "enabled" : "disabled");
     596             : }
     597             : 
     598             : /** LISP-GPE init function. */
     599             : clib_error_t *
     600         559 : lisp_gpe_init (vlib_main_t * vm)
     601             : {
     602         559 :   lisp_gpe_main_t *lgm = &lisp_gpe_main;
     603         559 :   clib_error_t *error = 0;
     604             : 
     605         559 :   if ((error = vlib_call_init_function (vm, ip_main_init)))
     606           0 :     return error;
     607             : 
     608         559 :   if ((error = vlib_call_init_function (vm, ip4_lookup_init)))
     609           0 :     return error;
     610             : 
     611         559 :   lgm->vnet_main = vnet_get_main ();
     612         559 :   lgm->vlib_main = vm;
     613         559 :   lgm->im4 = &ip4_main;
     614         559 :   lgm->im6 = &ip6_main;
     615         559 :   lgm->lm4 = &ip4_main.lookup_main;
     616         559 :   lgm->lm6 = &ip6_main.lookup_main;
     617         559 :   lgm->encap_mode = GPE_ENCAP_LISP;
     618             : 
     619         559 :   lgm->lisp_gpe_fwd_entries =
     620         559 :     hash_create_mem (0, sizeof (lisp_gpe_fwd_entry_key_t), sizeof (uword));
     621             : 
     622         559 :   lgm->lisp_stats_index_by_key =
     623         559 :     hash_create_mem (0, sizeof (lisp_stats_key_t), sizeof (uword));
     624         559 :   clib_memset (&lgm->counters, 0, sizeof (lgm->counters));
     625         559 :   lgm->counters.name = "LISP counters";
     626             : 
     627         559 :   return 0;
     628             : }
     629             : 
     630             : gpe_encap_mode_t
     631           1 : vnet_gpe_get_encap_mode (void)
     632             : {
     633           1 :   lisp_gpe_main_t *lgm = &lisp_gpe_main;
     634           1 :   return lgm->encap_mode;
     635             : }
     636             : 
     637             : static clib_error_t *
     638           0 : lisp_gpe_test_send_nsh_packet (u8 * file_name)
     639             : {
     640             :   vlib_frame_t *f;
     641             :   vlib_buffer_t *b;
     642           0 :   lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
     643             :   pcap_main_t pm;
     644           0 :   clib_error_t *error = 0;
     645             : 
     646           0 :   if (!file_name)
     647           0 :     return clib_error_create ("no pcap file specified!");
     648             : 
     649           0 :   clib_memset (&pm, 0, sizeof (pm));
     650           0 :   pm.file_name = (char *) file_name;
     651           0 :   error = pcap_read (&pm);
     652           0 :   if (error)
     653           0 :     return error;
     654             : 
     655             :   u32 bi;
     656           0 :   if (vlib_buffer_alloc (lgm->vlib_main, &bi, 1) != 1)
     657           0 :     return clib_error_create ("cannot allocate memory!");
     658             : 
     659           0 :   b = vlib_get_buffer (lgm->vlib_main, bi);
     660           0 :   tunnel_lookup_t *nsh_ifaces = &lgm->nsh_ifaces;
     661             :   uword *hip;
     662             :   vnet_hw_interface_t *hi;
     663             : 
     664           0 :   hip = hash_get (nsh_ifaces->hw_if_index_by_dp_table, 0);
     665           0 :   if (hip == 0)
     666           0 :     return clib_error_create ("The NSH 0 interface doesn't exist");
     667             : 
     668           0 :   hi = vnet_get_hw_interface (lgm->vnet_main, hip[0]);
     669             : 
     670           0 :   vnet_buffer (b)->sw_if_index[VLIB_TX] = hi->sw_if_index;
     671           0 :   u8 *p = vlib_buffer_put_uninit (b, vec_len (pm.packets_read[0]));
     672           0 :   clib_memcpy_fast (p, pm.packets_read[0], vec_len (pm.packets_read[0]));
     673           0 :   vlib_buffer_pull (b, sizeof (ethernet_header_t));
     674             : 
     675             :   vlib_node_t *n =
     676           0 :     vlib_get_node_by_name (lgm->vlib_main, (u8 *) "interface-output-arc-end");
     677           0 :   f = vlib_get_frame_to_node (lgm->vlib_main, n->index);
     678           0 :   u32 *to_next = vlib_frame_vector_args (f);
     679           0 :   to_next[0] = bi;
     680           0 :   f->n_vectors = 1;
     681           0 :   vlib_put_frame_to_node (lgm->vlib_main, n->index, f);
     682             : 
     683           0 :   return error;
     684             : }
     685             : 
     686             : static clib_error_t *
     687           0 : lisp_test_nsh_command_fn (vlib_main_t * vm, unformat_input_t * input,
     688             :                           vlib_cli_command_t * cmd)
     689             : {
     690           0 :   clib_error_t *error = 0;
     691           0 :   u8 *file_name = 0;
     692             : 
     693           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     694             :     {
     695           0 :       if (unformat (input, "pcap %v", &file_name))
     696             :         {
     697           0 :           error = lisp_gpe_test_send_nsh_packet (file_name);
     698           0 :           goto done;
     699             :         }
     700             :       else
     701             :         {
     702           0 :           error = clib_error_create ("unknown input `%U'",
     703             :                                      format_unformat_error, input);
     704           0 :           goto done;
     705             :         }
     706             :     }
     707             : 
     708           0 : done:
     709           0 :   return error;
     710             : }
     711             : 
     712             : /* *INDENT-OFF* */
     713      116069 : VLIB_CLI_COMMAND (lisp_test_nsh_command, static) = {
     714             :   .path = "test one nsh",
     715             :   .short_help = "test gpe nsh pcap <path-to-pcap-file>",
     716             :   .function = lisp_test_nsh_command_fn,
     717             : };
     718             : /* *INDENT-ON* */
     719             : 
     720        1679 : VLIB_INIT_FUNCTION (lisp_gpe_init);
     721             : 
     722             : /*
     723             :  * fd.io coding-style-patch-verification: ON
     724             :  *
     725             :  * Local Variables:
     726             :  * eval: (c-set-style "gnu")
     727             :  * End:
     728             :  */

Generated by: LCOV version 1.14