LCOV - code coverage report
Current view: top level - plugins/svs - svs.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 124 215 57.7 %
Date: 2023-07-05 22:20:52 Functions: 34 38 89.5 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2018 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             : #include <plugins/svs/svs.h>
      17             : 
      18             : #include <vlib/vlib.h>
      19             : #include <vnet/plugin/plugin.h>
      20             : #include <vnet/fib/fib_table.h>
      21             : #include <vnet/fib/ip6_fib.h>
      22             : #include <vnet/fib/ip4_fib.h>
      23             : #include <vnet/dpo/lookup_dpo.h>
      24             : #include <vnet/dpo/load_balance.h>
      25             : #include <vnet/dpo/load_balance_map.h>
      26             : 
      27             : u32 *svs_itf_db[FIB_PROTOCOL_IP_MAX];
      28             : 
      29             : static fib_source_t svs_fib_src;
      30             : 
      31             : int
      32           4 : svs_table_add (fib_protocol_t fproto, u32 table_id)
      33             : {
      34           4 :   fib_table_find_or_create_and_lock (fproto, table_id, svs_fib_src);
      35             : 
      36           4 :   return (0);
      37             : }
      38             : 
      39             : int
      40           4 : svs_table_delete (fib_protocol_t fproto, u32 table_id)
      41             : {
      42             :   u32 fib_index, ii;
      43             : 
      44           4 :   fib_index = fib_table_find (fproto, table_id);
      45             : 
      46          16 :   vec_foreach_index (ii, svs_itf_db[fproto])
      47             :   {
      48          12 :     if (svs_itf_db[fproto][ii] == fib_index)
      49           0 :       return VNET_API_ERROR_INSTANCE_IN_USE;
      50             :   }
      51             : 
      52           4 :   if (~0 == fib_index)
      53           0 :     return VNET_API_ERROR_NO_SUCH_FIB;
      54             : 
      55           4 :   fib_table_unlock (fib_index, fproto, svs_fib_src);
      56             : 
      57           4 :   return (0);
      58             : }
      59             : 
      60             : static int
      61          16 : svs_route_add_i (u32 fib_index, const fib_prefix_t * pfx, u32 src_fib_index)
      62             : {
      63          16 :   dpo_id_t dpo = DPO_INVALID;
      64             : 
      65             : 
      66          16 :   lookup_dpo_add_or_lock_w_fib_index (src_fib_index,
      67          16 :                                       fib_proto_to_dpo (pfx->fp_proto),
      68             :                                       LOOKUP_UNICAST,
      69             :                                       LOOKUP_INPUT_SRC_ADDR,
      70             :                                       LOOKUP_TABLE_FROM_CONFIG, &dpo);
      71             : 
      72          16 :   fib_table_entry_special_dpo_add (fib_index, pfx,
      73             :                                    svs_fib_src,
      74             :                                    FIB_ENTRY_FLAG_EXCLUSIVE, &dpo);
      75             : 
      76          16 :   dpo_unlock (&dpo);
      77             : 
      78          16 :   return (0);
      79             : }
      80             : 
      81             : int
      82          12 : svs_route_add (u32 table_id, const fib_prefix_t * pfx, u32 source_table_id)
      83             : {
      84             :   u32 fib_index, src_fib_index;
      85             :   int rv;
      86             : 
      87          12 :   fib_index = fib_table_find (pfx->fp_proto, table_id);
      88             : 
      89          12 :   if (~0 == fib_index)
      90           0 :     return VNET_API_ERROR_NO_SUCH_FIB;
      91             : 
      92          12 :   src_fib_index = fib_table_find (pfx->fp_proto, source_table_id);
      93             : 
      94          12 :   if (~0 == src_fib_index)
      95           0 :     return (VNET_API_ERROR_NO_SUCH_FIB);
      96             : 
      97          12 :   rv = svs_route_add_i (fib_index, pfx, src_fib_index);
      98             : 
      99          12 :   return (rv);
     100             : }
     101             : 
     102             : int
     103          12 : svs_route_delete (u32 table_id, const fib_prefix_t * pfx)
     104             : {
     105             :   u32 fib_index;
     106             : 
     107          12 :   fib_index = fib_table_find (pfx->fp_proto, table_id);
     108             : 
     109          12 :   if (~0 == fib_index)
     110           0 :     return VNET_API_ERROR_NO_SUCH_FIB;
     111             : 
     112          12 :   fib_table_entry_special_remove (fib_index, pfx, svs_fib_src);
     113             : 
     114          12 :   return (0);
     115             : }
     116             : 
     117             : int
     118           4 : svs_enable (fib_protocol_t fproto, u32 table_id, u32 sw_if_index)
     119             : {
     120           4 :   fib_prefix_t pfx = {
     121             :     .fp_proto = fproto,
     122             :   };
     123             :   u32 fib_index;
     124             : 
     125           4 :   fib_index = fib_table_find (fproto, table_id);
     126             : 
     127           4 :   if (~0 == fib_index)
     128           0 :     return VNET_API_ERROR_NO_SUCH_FIB;
     129             : 
     130             :   /*
     131             :    * now we know which interface the table will serve, we can add the default
     132             :    * route to use the table that the interface is bound to.
     133             :    */
     134           4 :   svs_route_add_i (fib_index, &pfx,
     135             :                    fib_table_get_index_for_sw_if_index (fproto, sw_if_index));
     136             : 
     137          10 :   vec_validate_init_empty (svs_itf_db[fproto], sw_if_index, ~0);
     138             : 
     139           4 :   svs_itf_db[fproto][sw_if_index] = fib_index;
     140             : 
     141           4 :   vnet_feature_enable_disable ((FIB_PROTOCOL_IP4 == fproto ?
     142             :                                 "ip4-unicast" :
     143             :                                 "ip6-unicast"),
     144             :                                (FIB_PROTOCOL_IP4 == fproto ?
     145             :                                 "svs-ip4" :
     146             :                                 "svs-ip6"), sw_if_index, 1, NULL, 0);
     147             : 
     148           4 :   return (0);
     149             : }
     150             : 
     151             : static void
     152        1625 : svs_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 itf_fib_index)
     153             : {
     154             :   /*
     155             :    * update the default route to use the interface's newly bound FIB
     156             :    */
     157             :   u32 svs_fib_index;
     158             : 
     159        1625 :   if (sw_if_index >= vec_len (svs_itf_db[FIB_PROTOCOL_IP6]))
     160        1621 :     return;
     161             : 
     162           4 :   svs_fib_index = svs_itf_db[FIB_PROTOCOL_IP6][sw_if_index];
     163             : 
     164           4 :   if (~0 != svs_fib_index)
     165             :     {
     166           0 :       fib_prefix_t pfx = {
     167             :         .fp_proto = fproto,
     168             :       };
     169             : 
     170           0 :       svs_route_add (svs_fib_index, &pfx, itf_fib_index);
     171             :     }
     172             :   /*
     173             :    * else
     174             :    *  no SVS enable on this interface
     175             :    */
     176             : }
     177             : 
     178             : static void
     179         729 : svs_ip6_table_bind (ip6_main_t * im,
     180             :                     uword opaque,
     181             :                     u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
     182             : {
     183         729 :   svs_table_bind (FIB_PROTOCOL_IP6, sw_if_index, new_fib_index);
     184         729 : }
     185             : 
     186             : static void
     187         896 : svs_ip4_table_bind (ip4_main_t * im,
     188             :                     uword opaque,
     189             :                     u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
     190             : {
     191         896 :   svs_table_bind (FIB_PROTOCOL_IP4, sw_if_index, new_fib_index);
     192         896 : }
     193             : 
     194             : int
     195           4 : svs_disable (fib_protocol_t fproto, u32 table_id, u32 sw_if_index)
     196             : {
     197           4 :   fib_prefix_t pfx = {
     198             :     .fp_proto = fproto,
     199             :   };
     200             :   u32 fib_index;
     201             : 
     202           4 :   fib_index = fib_table_find (fproto, table_id);
     203             : 
     204           4 :   if (~0 == fib_index)
     205           0 :     return VNET_API_ERROR_NO_SUCH_FIB;
     206             : 
     207           4 :   if (sw_if_index >= vec_len (svs_itf_db[fproto]))
     208           0 :     return VNET_API_ERROR_INVALID_SW_IF_INDEX;
     209             : 
     210           4 :   svs_itf_db[fproto][sw_if_index] = ~0;
     211             : 
     212           4 :   vnet_feature_enable_disable ((FIB_PROTOCOL_IP4 == fproto ?
     213             :                                 "ip4-unicast" :
     214             :                                 "ip6-unicast"),
     215             :                                (FIB_PROTOCOL_IP4 == fproto ?
     216             :                                 "svs-ip4" :
     217             :                                 "svs-ip6"), sw_if_index, 0, NULL, 0);
     218             : 
     219           4 :   fib_table_entry_special_remove (fib_index, &pfx, svs_fib_src);
     220             : 
     221           4 :   return (0);
     222             : }
     223             : 
     224             : void
     225           2 : svs_walk (svs_walk_fn_t fn, void *ctx)
     226             : {
     227             :   fib_protocol_t fproto;
     228             :   u32 ii, fib_index;
     229             : 
     230           6 :   FOR_EACH_FIB_IP_PROTOCOL (fproto)
     231             :   {
     232          13 :     vec_foreach_index (ii, svs_itf_db[fproto])
     233             :     {
     234           9 :       fib_index = svs_itf_db[fproto][ii];
     235             : 
     236           9 :       if (~0 != fib_index)
     237             :         {
     238           4 :           if (WALK_CONTINUE != fn (fproto,
     239             :                                    fib_table_get_table_id (fib_index, fproto),
     240             :                                    ii, ctx))
     241           0 :             return;
     242             :         }
     243             :     }
     244             :   }
     245             : }
     246             : 
     247             : typedef enum svs_next_t_
     248             : {
     249             :   SVS_NEXT_DROP,
     250             :   SVS_N_NEXT,
     251             : } svs_next_t;
     252             : 
     253             : typedef struct svs_input_trace_t_
     254             : {
     255             :   u32 fib_index;
     256             : } svs_input_trace_t;
     257             : 
     258             : always_inline uword
     259          16 : svs_input_inline (vlib_main_t * vm,
     260             :                   vlib_node_runtime_t * node,
     261             :                   vlib_frame_t * frame, fib_protocol_t fproto)
     262             : {
     263             :   u32 n_left_from, *from, *to_next, next_index;
     264             : 
     265          16 :   from = vlib_frame_vector_args (frame);
     266          16 :   n_left_from = frame->n_vectors;
     267          16 :   next_index = node->cached_next_index;
     268             : 
     269          32 :   while (n_left_from > 0)
     270             :     {
     271             :       u32 n_left_to_next;
     272             : 
     273          16 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
     274             : 
     275        1088 :       while (n_left_from > 0 && n_left_to_next > 0)
     276             :         {
     277             :           const load_balance_t *lb0;
     278             :           const lookup_dpo_t *lk0;
     279             :           u32 bi0, sw_if_index0;
     280             :           const dpo_id_t *dpo0;
     281             :           vlib_buffer_t *b0;
     282             :           svs_next_t next0;
     283             :           index_t lbi0;
     284             : 
     285        1072 :           bi0 = from[0];
     286        1072 :           to_next[0] = bi0;
     287        1072 :           from += 1;
     288        1072 :           to_next += 1;
     289        1072 :           n_left_from -= 1;
     290        1072 :           n_left_to_next -= 1;
     291             : 
     292        1072 :           b0 = vlib_get_buffer (vm, bi0);
     293        1072 :           sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
     294             : 
     295        1072 :           if (FIB_PROTOCOL_IP4 == fproto)
     296             :             {
     297             :               ip4_header_t *ip0;
     298             : 
     299         536 :               ip0 = vlib_buffer_get_current (b0);
     300             :               lbi0 =
     301         536 :                 ip4_fib_forwarding_lookup (svs_itf_db[fproto][sw_if_index0],
     302         536 :                                            &ip0->src_address);
     303             :             }
     304             :           else
     305             :             {
     306             :               ip6_header_t *ip0;
     307             : 
     308         536 :               ip0 = vlib_buffer_get_current (b0);
     309         536 :               lbi0 = ip6_fib_table_fwding_lookup (svs_itf_db[fproto]
     310         536 :                                                   [sw_if_index0],
     311         536 :                                                   &ip0->src_address);
     312             :             }
     313        1072 :           lb0 = load_balance_get (lbi0);
     314        1072 :           dpo0 = load_balance_get_fwd_bucket (lb0, 0);
     315        1072 :           lk0 = lookup_dpo_get (dpo0->dpoi_index);
     316             : 
     317        1072 :           vnet_buffer (b0)->sw_if_index[VLIB_TX] = lk0->lkd_fib_index;
     318             : 
     319        1072 :           vnet_feature_next (&next0, b0);
     320             : 
     321        1072 :           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
     322             :             {
     323             :               svs_input_trace_t *tr;
     324             : 
     325        1072 :               tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
     326        1072 :               tr->fib_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
     327             :             }
     328             : 
     329             :           /* verify speculative enqueue, maybe switch current next frame */
     330        1072 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
     331             :                                            to_next, n_left_to_next, bi0,
     332             :                                            next0);
     333             :         }
     334             : 
     335          16 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     336             :     }
     337             : 
     338          16 :   return frame->n_vectors;
     339             : }
     340             : 
     341             : static uword
     342           8 : svs_input_ip4 (vlib_main_t * vm,
     343             :                vlib_node_runtime_t * node, vlib_frame_t * frame)
     344             : {
     345           8 :   return svs_input_inline (vm, node, frame, FIB_PROTOCOL_IP4);
     346             : }
     347             : 
     348             : static uword
     349           8 : svs_input_ip6 (vlib_main_t * vm,
     350             :                vlib_node_runtime_t * node, vlib_frame_t * frame)
     351             : {
     352           8 :   return svs_input_inline (vm, node, frame, FIB_PROTOCOL_IP6);
     353             : }
     354             : 
     355             : static u8 *
     356         934 : format_svs_input_trace (u8 * s, va_list * args)
     357             : {
     358         934 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
     359         934 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
     360         934 :   svs_input_trace_t *t = va_arg (*args, svs_input_trace_t *);
     361             : 
     362         934 :   s = format (s, " fib_index %d", t->fib_index);
     363         934 :   return s;
     364             : }
     365             : 
     366             : /* *INDENT-OFF* */
     367       27999 : VLIB_REGISTER_NODE (svs_ip4_node) =
     368             : {
     369             :   .function = svs_input_ip4,
     370             :   .name = "svs-ip4",
     371             :   .vector_size = sizeof (u32),
     372             :   .format_trace = format_svs_input_trace,
     373             :   .type = VLIB_NODE_TYPE_INTERNAL,
     374             :   .n_next_nodes = SVS_N_NEXT,
     375             :   .next_nodes =
     376             :   {
     377             :     [SVS_NEXT_DROP] = "error-drop",
     378             :   }
     379             : };
     380             : 
     381       27999 : VLIB_REGISTER_NODE (svs_ip6_node) =
     382             : {
     383             :   .function = svs_input_ip6,
     384             :   .name = "svs-ip6",
     385             :   .vector_size = sizeof (u32),
     386             :   .format_trace = format_svs_input_trace,
     387             :   .type = VLIB_NODE_TYPE_INTERNAL,
     388             :   .next_nodes =
     389             :   {
     390             :     [SVS_NEXT_DROP] = "error-drop",
     391             :   }
     392             : };
     393             : 
     394        9519 : VNET_FEATURE_INIT (svs_ip4_feat, static) =
     395             : {
     396             :   .arc_name = "ip4-unicast",
     397             :   .node_name = "svs-ip4",
     398             : };
     399             : 
     400        9519 : VNET_FEATURE_INIT (svs_ip6_feat, static) =
     401             : {
     402             :   .arc_name = "ip6-unicast",
     403             :   .node_name = "svs-ip6",
     404             : };
     405             : /* *INDENT-ON* */
     406             : 
     407             : static clib_error_t *
     408           0 : svs_table_cli (vlib_main_t * vm,
     409             :                unformat_input_t * input, vlib_cli_command_t * cmd)
     410             : {
     411             :   fib_protocol_t fproto;
     412             :   u32 table_id;
     413             :   u8 add;
     414             : 
     415           0 :   fproto = FIB_PROTOCOL_IP4;
     416           0 :   table_id = ~0;
     417           0 :   add = 1;
     418             : 
     419           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     420             :     {
     421           0 :       if (unformat (input, "add"))
     422           0 :         add = 1;
     423           0 :       else if (unformat (input, "del"))
     424           0 :         add = 0;
     425           0 :       else if (unformat (input, "ip4"))
     426           0 :         fproto = FIB_PROTOCOL_IP4;
     427           0 :       else if (unformat (input, "ip6"))
     428           0 :         fproto = FIB_PROTOCOL_IP6;
     429           0 :       else if (unformat (input, "table-id %d", &table_id))
     430             :         ;
     431             :       else
     432           0 :         break;
     433             :     }
     434             : 
     435           0 :   if (~0 == table_id)
     436           0 :     return clib_error_return (0, "table-id must be specified");
     437             : 
     438           0 :   if (add)
     439           0 :     svs_table_add (fproto, table_id);
     440             :   else
     441           0 :     svs_table_delete (fproto, table_id);
     442             : 
     443           0 :   return (NULL);
     444             : }
     445             : 
     446             : /* *INDENT-OFF* */
     447       36399 : VLIB_CLI_COMMAND (svs_table_cmd_cli, static) = {
     448             :     .path = "svs table",
     449             :     .short_help = "Source VRF select table [add|delete] [ip4|ip6] table-id X",
     450             :     .function = svs_table_cli,
     451             : };
     452             : /* *INDENT-ON* */
     453             : 
     454             : static clib_error_t *
     455           0 : svs_enable_cli (vlib_main_t * vm,
     456             :                 unformat_input_t * input, vlib_cli_command_t * cmd)
     457             : {
     458             :   u32 sw_if_index, table_id;
     459             :   fib_protocol_t fproto;
     460             :   vnet_main_t *vnm;
     461             :   u8 enable;
     462             : 
     463           0 :   vnm = vnet_get_main ();
     464           0 :   sw_if_index = table_id = ~0;
     465           0 :   fproto = FIB_PROTOCOL_IP4;
     466           0 :   enable = 1;
     467             : 
     468           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     469             :     {
     470           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface,
     471             :                     vnm, &sw_if_index))
     472             :         ;
     473           0 :       else if (unformat (input, "enable"))
     474           0 :         enable = 1;
     475           0 :       else if (unformat (input, "disable"))
     476           0 :         enable = 0;
     477           0 :       else if (unformat (input, "ip4"))
     478           0 :         fproto = FIB_PROTOCOL_IP4;
     479           0 :       else if (unformat (input, "ip6"))
     480           0 :         fproto = FIB_PROTOCOL_IP6;
     481           0 :       else if (unformat (input, "table-id %d", &table_id))
     482             :         ;
     483             :       else
     484           0 :         break;
     485             :     }
     486             : 
     487           0 :   if (~0 == sw_if_index)
     488           0 :     return clib_error_return (0, "interface must be specified");
     489           0 :   if (~0 == table_id)
     490           0 :     return clib_error_return (0, "table-id must be specified");
     491             : 
     492           0 :   if (enable)
     493           0 :     svs_enable (fproto, table_id, sw_if_index);
     494             :   else
     495           0 :     svs_disable (fproto, table_id, sw_if_index);
     496             : 
     497           0 :   return (NULL);
     498             : }
     499             : 
     500             : /* *INDENT-OFF* */
     501       36399 : VLIB_CLI_COMMAND (svs_enable_cli_cmd, static) = {
     502             :     .path = "svs enable",
     503             :     .short_help = "Source VRF select [enable|disable] [ip4|ip6] <table-id> X <interface>",
     504             :     .function = svs_enable_cli,
     505             : };
     506             : /* *INDENT-ON* */
     507             : 
     508             : static clib_error_t *
     509           0 : svs_route_cli (vlib_main_t * vm,
     510             :                unformat_input_t * input, vlib_cli_command_t * cmd)
     511             : {
     512             :   u32 table_id, src_table_id;
     513             :   fib_prefix_t pfx;
     514             :   int rv;
     515             :   u8 add;
     516             : 
     517           0 :   src_table_id = table_id = ~0;
     518           0 :   add = 1;
     519             : 
     520           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     521             :     {
     522           0 :       if (unformat (input, "add"))
     523           0 :         add = 1;
     524           0 :       else if (unformat (input, "del"))
     525           0 :         add = 0;
     526           0 :       else if (unformat (input, "table-id %d", &table_id))
     527             :         ;
     528           0 :       else if (unformat (input, "src-table-id %d", &src_table_id))
     529             :         ;
     530           0 :       else if (unformat (input, "%U/%d",
     531             :                          unformat_ip4_address, &pfx.fp_addr.ip4, &pfx.fp_len))
     532             :         {
     533           0 :           pfx.fp_proto = FIB_PROTOCOL_IP4;
     534             :         }
     535           0 :       else if (unformat (input, "%U/%d",
     536             :                          unformat_ip6_address, &pfx.fp_addr.ip6, &pfx.fp_len))
     537             :         {
     538           0 :           pfx.fp_proto = FIB_PROTOCOL_IP6;
     539             :         }
     540             :       else
     541           0 :         break;
     542             :     }
     543             : 
     544           0 :   if (~0 == table_id)
     545           0 :     return clib_error_return (0, "table-id must be specified");
     546           0 :   if (~0 == src_table_id)
     547           0 :     return clib_error_return (0, "src-table-id must be specified");
     548             : 
     549           0 :   if (add)
     550           0 :     rv = svs_route_add (table_id, &pfx, src_table_id);
     551             :   else
     552           0 :     rv = svs_route_delete (table_id, &pfx);
     553             : 
     554           0 :   if (rv != 0)
     555           0 :     return clib_error_return (0,
     556             :                               "failed, rv=%d:%U",
     557             :                               (int) rv, format_vnet_api_errno, rv);
     558             : 
     559           0 :   return (NULL);
     560             : }
     561             : 
     562             : /* *INDENT-OFF* */
     563       36399 : VLIB_CLI_COMMAND (svs_route_cmd_cli, static) = {
     564             :     .path = "svs route",
     565             :     .short_help = "Source VRF select route [add|delete] <table-id> <prefix> <src-table-id>",
     566             :     .function = svs_route_cli,
     567             : };
     568             : /* *INDENT-ON* */
     569             : 
     570             : static clib_error_t *
     571           0 : svs_show_cli (vlib_main_t * vm,
     572             :               unformat_input_t * input, vlib_cli_command_t * cmd)
     573             : {
     574             :   fib_protocol_t fproto;
     575             :   u32 ii;
     576             : 
     577           0 :   vlib_cli_output (vm, "Source VRF select interface to fib-index mappings:");
     578           0 :   FOR_EACH_FIB_IP_PROTOCOL (fproto)
     579             :   {
     580           0 :     vlib_cli_output (vm, " %U", format_fib_protocol, fproto);
     581           0 :     vec_foreach_index (ii, svs_itf_db[fproto])
     582             :     {
     583           0 :       if (~0 != svs_itf_db[fproto][ii])
     584           0 :         vlib_cli_output (vm, "  %U -> %d", format_vnet_sw_if_index_name,
     585           0 :                          vnet_get_main (), ii, svs_itf_db[fproto][ii]);
     586             :     }
     587             :   }
     588           0 :   return (NULL);
     589             : }
     590             : 
     591             : /* *INDENT-OFF* */
     592       36399 : VLIB_CLI_COMMAND (svs_show_cli_cmd, static) = {
     593             :   .path = "show svs",
     594             :   .short_help = "Source VRF select show",
     595             :   .function = svs_show_cli,
     596             : };
     597             : /* *INDENT-ON* */
     598             : 
     599             : static clib_error_t *
     600         559 : svs_init (vlib_main_t * vm)
     601             : {
     602         559 :   ip6_table_bind_callback_t cbt6 = {
     603             :     .function = svs_ip6_table_bind,
     604             :   };
     605         559 :   vec_add1 (ip6_main.table_bind_callbacks, cbt6);
     606             : 
     607         559 :   ip4_table_bind_callback_t cbt4 = {
     608             :     .function = svs_ip4_table_bind,
     609             :   };
     610         559 :   vec_add1 (ip4_main.table_bind_callbacks, cbt4);
     611             : 
     612         559 :   svs_fib_src = fib_source_allocate ("svs",
     613             :                                      FIB_SOURCE_PRIORITY_LOW,
     614             :                                      FIB_SOURCE_BH_SIMPLE);
     615             : 
     616         559 :   return (NULL);
     617             : }
     618             : 
     619        1119 : VLIB_INIT_FUNCTION (svs_init);
     620             : 
     621             : /*
     622             :  * fd.io coding-style-patch-verification: ON
     623             :  *
     624             :  * Local Variables:
     625             :  * eval: (c-set-style "gnu")
     626             :  * End:
     627             :  */

Generated by: LCOV version 1.14