LCOV - code coverage report
Current view: top level - vnet/ip - ip_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 563 861 65.4 %
Date: 2023-10-26 01:39:38 Functions: 56 74 75.7 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * ip_api.c - vnet ip api
       4             :  *
       5             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       6             :  * Licensed under the Apache License, Version 2.0 (the "License");
       7             :  * you may not use this file except in compliance with the License.
       8             :  * You may obtain a copy of the License at:
       9             :  *
      10             :  *     http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  * Unless required by applicable law or agreed to in writing, software
      13             :  * distributed under the License is distributed on an "AS IS" BASIS,
      14             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  * See the License for the specific language governing permissions and
      16             :  * limitations under the License.
      17             :  *------------------------------------------------------------------
      18             :  */
      19             : 
      20             : #include <vnet/vnet.h>
      21             : #include <vlibmemory/api.h>
      22             : 
      23             : #include <vnet/interface.h>
      24             : #include <vnet/api_errno.h>
      25             : #include <vnet/ethernet/ethernet.h>
      26             : #include <vnet/ethernet/ethernet_types_api.h>
      27             : #include <vnet/ip/ip.h>
      28             : #include <vnet/ip/ip_types_api.h>
      29             : #include <vnet/ip/ip_punt_drop.h>
      30             : #include <vnet/ip/ip_types_api.h>
      31             : #include <vnet/ip/ip_path_mtu.h>
      32             : #include <vnet/fib/fib_table.h>
      33             : #include <vnet/fib/fib_api.h>
      34             : #include <vnet/ethernet/arp_packet.h>
      35             : #include <vnet/mfib/ip6_mfib.h>
      36             : #include <vnet/mfib/ip4_mfib.h>
      37             : #include <vnet/mfib/mfib_signal.h>
      38             : #include <vnet/mfib/mfib_entry.h>
      39             : #include <vnet/mfib/mfib_api.h>
      40             : #include <vnet/ip/ip_source_and_port_range_check.h>
      41             : #include <vnet/fib/fib_path_list.h>
      42             : #include <vnet/ip/ip6_hop_by_hop.h>
      43             : #include <vnet/ip/ip6_link.h>
      44             : #include <vnet/ip/reass/ip4_sv_reass.h>
      45             : #include <vnet/ip/reass/ip4_full_reass.h>
      46             : #include <vnet/ip/reass/ip6_sv_reass.h>
      47             : #include <vnet/ip/reass/ip6_full_reass.h>
      48             : #include <vnet/ip/ip_table.h>
      49             : #include <vnet/ip/ip_container_proxy.h>
      50             : 
      51             : #include <vnet/format_fns.h>
      52             : #include <vnet/ip/ip.api_enum.h>
      53             : #include <vnet/ip/ip.api_types.h>
      54             : 
      55             : #define REPLY_MSG_ID_BASE ip4_main.msg_id_base
      56             : #include <vlibapi/api_helper_macros.h>
      57             : 
      58             : static void
      59           2 :   vl_api_sw_interface_ip6_enable_disable_t_handler
      60             :   (vl_api_sw_interface_ip6_enable_disable_t * mp)
      61             : {
      62             :   vl_api_sw_interface_ip6_enable_disable_reply_t *rmp;
      63           2 :   int rv = 0;
      64             : 
      65           2 :   VALIDATE_SW_IF_INDEX (mp);
      66             : 
      67           2 :   rv = ((mp->enable == 1) ?
      68           2 :         ip6_link_enable (ntohl (mp->sw_if_index), NULL) :
      69           0 :         ip6_link_disable (ntohl (mp->sw_if_index)));
      70             : 
      71           2 :   BAD_SW_IF_INDEX_LABEL;
      72             : 
      73           2 :   REPLY_MACRO (VL_API_SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY);
      74             : }
      75             : 
      76             : static void
      77           0 : send_ip_table_details (vpe_api_main_t * am,
      78             :                        vl_api_registration_t * reg,
      79             :                        u32 context, const fib_table_t * table)
      80             : {
      81             :   vl_api_ip_table_details_t *mp;
      82             : 
      83           0 :   mp = vl_msg_api_alloc (sizeof (*mp));
      84           0 :   if (!mp)
      85           0 :     return;
      86           0 :   clib_memset (mp, 0, sizeof (*mp));
      87           0 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IP_TABLE_DETAILS);
      88           0 :   mp->context = context;
      89             : 
      90           0 :   mp->table.is_ip6 = (table->ft_proto == FIB_PROTOCOL_IP6);
      91           0 :   mp->table.table_id = htonl (table->ft_table_id);
      92           0 :   memcpy (mp->table.name, table->ft_desc,
      93           0 :           clib_min (vec_len (table->ft_desc), sizeof (mp->table.name)));
      94             : 
      95           0 :   vl_api_send_msg (reg, (u8 *) mp);
      96             : }
      97             : 
      98             : static void
      99           0 : vl_api_ip_table_dump_t_handler (vl_api_ip_table_dump_t * mp)
     100             : {
     101           0 :   vpe_api_main_t *am = &vpe_api_main;
     102             :   vl_api_registration_t *reg;
     103             :   fib_table_t *fib_table;
     104             : 
     105           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     106           0 :   if (!reg)
     107           0 :     return;
     108             : 
     109             :   /* *INDENT-OFF* */
     110           0 :   pool_foreach (fib_table, ip4_main.fibs)
     111             :    {
     112           0 :     send_ip_table_details(am, reg, mp->context, fib_table);
     113             :   }
     114           0 :   pool_foreach (fib_table, ip6_main.fibs)
     115             :    {
     116             :     /* don't send link locals */
     117           0 :     if (fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL)
     118           0 :       continue;
     119           0 :     send_ip_table_details(am, reg, mp->context, fib_table);
     120             :   }
     121             :   /* *INDENT-ON* */
     122             : }
     123             : 
     124             : typedef struct vl_api_ip_fib_dump_walk_ctx_t_
     125             : {
     126             :   fib_node_index_t *feis;
     127             : } vl_api_ip_fib_dump_walk_ctx_t;
     128             : 
     129             : static fib_table_walk_rc_t
     130      154990 : vl_api_ip_fib_dump_walk (fib_node_index_t fei, void *arg)
     131             : {
     132      154990 :   vl_api_ip_fib_dump_walk_ctx_t *ctx = arg;
     133             : 
     134      154990 :   vec_add1 (ctx->feis, fei);
     135             : 
     136      154990 :   return (FIB_TABLE_WALK_CONTINUE);
     137             : }
     138             : 
     139             : static void
     140      154970 : send_ip_route_details (vpe_api_main_t * am,
     141             :                        vl_api_registration_t * reg,
     142             :                        u32 context, fib_node_index_t fib_entry_index)
     143             : {
     144             :   fib_route_path_t *rpaths, *rpath;
     145             :   vl_api_ip_route_details_t *mp;
     146             :   const fib_prefix_t *pfx;
     147             :   vl_api_fib_path_t *fp;
     148             :   int path_count;
     149             : 
     150      154970 :   rpaths = NULL;
     151      154970 :   pfx = fib_entry_get_prefix (fib_entry_index);
     152      154970 :   rpaths = fib_entry_encode (fib_entry_index);
     153             : 
     154      154970 :   path_count = vec_len (rpaths);
     155      154970 :   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
     156      154970 :   if (!mp)
     157           0 :     return;
     158      154970 :   clib_memset (mp, 0, sizeof (*mp));
     159      154970 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IP_ROUTE_DETAILS);
     160      154970 :   mp->context = context;
     161             : 
     162      154970 :   ip_prefix_encode (pfx, &mp->route.prefix);
     163      154970 :   mp->route.table_id =
     164      154970 :     htonl (fib_table_get_table_id
     165      154970 :            (fib_entry_get_fib_index (fib_entry_index), pfx->fp_proto));
     166      154970 :   mp->route.n_paths = path_count;
     167      154970 :   mp->route.stats_index =
     168      154970 :     htonl (fib_table_entry_get_stats_index
     169             :            (fib_entry_get_fib_index (fib_entry_index), pfx));
     170             : 
     171      154970 :   fp = mp->route.paths;
     172      324658 :   vec_foreach (rpath, rpaths)
     173             :   {
     174      169688 :     fib_api_path_encode (rpath, fp);
     175      169688 :     fp++;
     176             :   }
     177             : 
     178      154970 :   vl_api_send_msg (reg, (u8 *) mp);
     179      154970 :   vec_free (rpaths);
     180             : }
     181             : 
     182             : static void
     183          20 : send_ip_route_v2_details (vpe_api_main_t *am, vl_api_registration_t *reg,
     184             :                           u32 context, fib_node_index_t fib_entry_index)
     185             : {
     186             :   fib_route_path_t *rpaths, *rpath;
     187             :   vl_api_ip_route_v2_details_t *mp;
     188             :   const fib_prefix_t *pfx;
     189             :   vl_api_fib_path_t *fp;
     190             :   int path_count;
     191             : 
     192          20 :   rpaths = NULL;
     193          20 :   pfx = fib_entry_get_prefix (fib_entry_index);
     194          20 :   rpaths = fib_entry_encode (fib_entry_index);
     195             : 
     196          20 :   path_count = vec_len (rpaths);
     197          20 :   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
     198          20 :   if (!mp)
     199           0 :     return;
     200          20 :   clib_memset (mp, 0, sizeof (*mp));
     201          20 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IP_ROUTE_V2_DETAILS);
     202          20 :   mp->context = context;
     203             : 
     204          20 :   ip_prefix_encode (pfx, &mp->route.prefix);
     205          20 :   mp->route.table_id = htonl (fib_table_get_table_id (
     206          20 :     fib_entry_get_fib_index (fib_entry_index), pfx->fp_proto));
     207          20 :   mp->route.n_paths = path_count;
     208          20 :   mp->route.src = fib_entry_get_best_source (fib_entry_index);
     209          20 :   mp->route.stats_index = htonl (fib_table_entry_get_stats_index (
     210             :     fib_entry_get_fib_index (fib_entry_index), pfx));
     211             : 
     212          20 :   fp = mp->route.paths;
     213          40 :   vec_foreach (rpath, rpaths)
     214             :     {
     215          20 :       fib_api_path_encode (rpath, fp);
     216          20 :       fp++;
     217             :     }
     218             : 
     219          20 :   vl_api_send_msg (reg, (u8 *) mp);
     220          20 :   vec_free (rpaths);
     221             : }
     222             : 
     223             : typedef struct apt_ip6_fib_show_ctx_t_
     224             : {
     225             :   fib_node_index_t *entries;
     226             : } api_ip6_fib_show_ctx_t;
     227             : 
     228             : static void
     229        4372 : vl_api_ip_route_dump_t_handler (vl_api_ip_route_dump_t * mp)
     230             : {
     231        4372 :   vpe_api_main_t *am = &vpe_api_main;
     232             :   fib_node_index_t *fib_entry_index;
     233             :   vl_api_registration_t *reg;
     234             :   fib_protocol_t fproto;
     235             :   u32 fib_index;
     236             : 
     237        4372 :   reg = vl_api_client_index_to_registration (mp->client_index);
     238        4372 :   if (!reg)
     239         311 :     return;
     240             : 
     241        4372 :   vl_api_ip_fib_dump_walk_ctx_t ctx = {
     242             :     .feis = NULL,
     243             :   };
     244             : 
     245        4372 :   fproto = (mp->table.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
     246        4372 :   fib_index = fib_table_find (fproto, ntohl (mp->table.table_id));
     247             : 
     248        4372 :   if (INDEX_INVALID == fib_index)
     249         311 :     return;
     250             : 
     251        4061 :   fib_table_walk (fib_index, fproto, vl_api_ip_fib_dump_walk, &ctx);
     252             : 
     253      159031 :   vec_foreach (fib_entry_index, ctx.feis)
     254             :   {
     255      154970 :     send_ip_route_details (am, reg, mp->context, *fib_entry_index);
     256             :   }
     257             : 
     258        4061 :   vec_free (ctx.feis);
     259             : }
     260             : 
     261             : static void
     262           5 : vl_api_ip_route_v2_dump_t_handler (vl_api_ip_route_v2_dump_t *mp)
     263             : {
     264           5 :   vpe_api_main_t *am = &vpe_api_main;
     265             :   fib_node_index_t *fib_entry_index;
     266             :   vl_api_registration_t *reg;
     267             :   fib_protocol_t fproto;
     268             :   fib_source_t src;
     269             :   u32 fib_index;
     270             : 
     271           5 :   reg = vl_api_client_index_to_registration (mp->client_index);
     272           5 :   if (!reg)
     273           0 :     return;
     274             : 
     275           5 :   vl_api_ip_fib_dump_walk_ctx_t ctx = {
     276             :     .feis = NULL,
     277             :   };
     278             : 
     279           5 :   fproto = (mp->table.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
     280           5 :   fib_index = fib_table_find (fproto, ntohl (mp->table.table_id));
     281           5 :   src = mp->src;
     282             : 
     283           5 :   if (INDEX_INVALID == fib_index)
     284           0 :     return;
     285             : 
     286           5 :   if (src)
     287           4 :     fib_table_walk_w_src (fib_index, fproto, src, vl_api_ip_fib_dump_walk,
     288             :                           &ctx);
     289             :   else
     290           1 :     fib_table_walk (fib_index, fproto, vl_api_ip_fib_dump_walk, &ctx);
     291             : 
     292          25 :   vec_foreach (fib_entry_index, ctx.feis)
     293             :     {
     294          20 :       send_ip_route_v2_details (am, reg, mp->context, *fib_entry_index);
     295             :     }
     296             : 
     297           5 :   vec_free (ctx.feis);
     298             : }
     299             : 
     300             : static void
     301           0 : send_ip_mtable_details (vl_api_registration_t * reg,
     302             :                         u32 context, const mfib_table_t * mfib_table)
     303             : {
     304             :   vl_api_ip_mtable_details_t *mp;
     305             : 
     306           0 :   mp = vl_msg_api_alloc (sizeof (*mp));
     307           0 :   if (!mp)
     308           0 :     return;
     309           0 :   memset (mp, 0, sizeof (*mp));
     310           0 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IP_MTABLE_DETAILS);
     311           0 :   mp->context = context;
     312             : 
     313           0 :   mp->table.table_id = htonl (mfib_table->mft_table_id);
     314           0 :   mp->table.is_ip6 = (FIB_PROTOCOL_IP6 == mfib_table->mft_proto);
     315             : 
     316           0 :   vl_api_send_msg (reg, (u8 *) mp);
     317             : }
     318             : 
     319             : static void
     320           0 : vl_api_ip_mtable_dump_t_handler (vl_api_ip_mtable_dump_t * mp)
     321             : {
     322             :   vl_api_registration_t *reg;
     323             :   mfib_table_t *mfib_table;
     324             : 
     325           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     326           0 :   if (!reg)
     327           0 :     return;
     328             : 
     329             :   /* *INDENT-OFF* */
     330           0 :   pool_foreach (mfib_table, ip4_main.mfibs)
     331             :    {
     332           0 :       send_ip_mtable_details (reg, mp->context, mfib_table);
     333             :   }
     334           0 :   pool_foreach (mfib_table, ip6_main.mfibs)
     335             :    {
     336           0 :       send_ip_mtable_details (reg, mp->context, mfib_table);
     337             :   }
     338             :   /* *INDENT-ON* */
     339             : }
     340             : 
     341             : typedef struct vl_api_ip_mfib_dump_ctx_t_
     342             : {
     343             :   fib_node_index_t *entries;
     344             : } vl_api_ip_mfib_dump_ctx_t;
     345             : 
     346             : static walk_rc_t
     347        2451 : mfib_route_dump_walk (fib_node_index_t fei, void *arg)
     348             : {
     349        2451 :   vl_api_ip_mfib_dump_ctx_t *ctx = arg;
     350             : 
     351        2451 :   vec_add1 (ctx->entries, fei);
     352             : 
     353        2451 :   return (WALK_CONTINUE);
     354             : }
     355             : 
     356             : static void
     357        2451 : send_ip_mroute_details (vpe_api_main_t * am,
     358             :                         vl_api_registration_t * reg,
     359             :                         u32 context, fib_node_index_t mfib_entry_index)
     360             : {
     361             :   fib_route_path_t *rpaths, *rpath;
     362             :   vl_api_ip_mroute_details_t *mp;
     363             :   const mfib_prefix_t *pfx;
     364             :   vl_api_mfib_path_t *fp;
     365             :   u8 path_count;
     366             : 
     367        2451 :   rpaths = NULL;
     368        2451 :   pfx = mfib_entry_get_prefix (mfib_entry_index);
     369        2451 :   rpaths = mfib_entry_encode (mfib_entry_index);
     370             : 
     371        2451 :   path_count = vec_len (rpaths);
     372        2451 :   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
     373        2451 :   if (!mp)
     374           0 :     return;
     375        2451 :   clib_memset (mp, 0, sizeof (*mp));
     376        2451 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IP_MROUTE_DETAILS);
     377        2451 :   mp->context = context;
     378             : 
     379        2451 :   ip_mprefix_encode (pfx, &mp->route.prefix);
     380        2451 :   mp->route.table_id =
     381        2451 :     htonl (mfib_table_get_table_id
     382        2451 :            (mfib_entry_get_fib_index (mfib_entry_index), pfx->fp_proto));
     383        2451 :   mp->route.n_paths = path_count;
     384        2451 :   fp = mp->route.paths;
     385        8378 :   vec_foreach (rpath, rpaths)
     386             :   {
     387        5927 :     mfib_api_path_encode (rpath, fp);
     388        5927 :     fp++;
     389             :   }
     390             : 
     391        2451 :   vl_api_send_msg (reg, (u8 *) mp);
     392        2451 :   vec_free (rpaths);
     393             : }
     394             : 
     395             : static void
     396         310 : vl_api_ip_mroute_dump_t_handler (vl_api_ip_mroute_dump_t * mp)
     397             : {
     398         310 :   vpe_api_main_t *am = &vpe_api_main;
     399             :   vl_api_registration_t *reg;
     400             :   fib_node_index_t *mfeip;
     401             :   fib_protocol_t fproto;
     402             :   u32 fib_index;
     403             : 
     404         310 :   vl_api_ip_mfib_dump_ctx_t ctx = {
     405             :     .entries = NULL,
     406             :   };
     407             : 
     408         310 :   reg = vl_api_client_index_to_registration (mp->client_index);
     409         310 :   if (!reg)
     410           0 :     return;
     411             : 
     412         310 :   fproto = fib_ip_proto (mp->table.is_ip6);
     413         310 :   fib_index = mfib_table_find (fproto, ntohl (mp->table.table_id));
     414             : 
     415         310 :   if (INDEX_INVALID == fib_index)
     416           0 :     return;
     417             : 
     418         310 :   mfib_table_walk (fib_index, fproto, mfib_route_dump_walk, &ctx);
     419             : 
     420         310 :   vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort);
     421             : 
     422        2761 :   vec_foreach (mfeip, ctx.entries)
     423             :   {
     424        2451 :     send_ip_mroute_details (am, reg, mp->context, *mfeip);
     425             :   }
     426             : 
     427         310 :   vec_free (ctx.entries);
     428             : }
     429             : 
     430             : static void
     431          10 : vl_api_ip_punt_police_t_handler (vl_api_ip_punt_police_t * mp,
     432             :                                  vlib_main_t * vm)
     433             : {
     434             :   vl_api_ip_punt_police_reply_t *rmp;
     435          10 :   int rv = 0;
     436             : 
     437          10 :   if (mp->is_ip6)
     438           6 :     ip6_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index));
     439             :   else
     440           4 :     ip4_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index));
     441             : 
     442          10 :   REPLY_MACRO (VL_API_IP_PUNT_POLICE_REPLY);
     443             : }
     444             : 
     445             : static void
     446          56 : ip_punt_redirect_t_handler_common (u8 is_add, u32 rx_sw_if_index,
     447             :                                    ip_address_family_t af,
     448             :                                    const fib_route_path_t *rpaths)
     449             : {
     450          56 :   if (is_add)
     451             :     {
     452          29 :       if (af == AF_IP6)
     453          16 :         ip6_punt_redirect_add_paths (rx_sw_if_index, rpaths);
     454          13 :       else if (af == AF_IP4)
     455          13 :         ip4_punt_redirect_add_paths (rx_sw_if_index, rpaths);
     456             :     }
     457             :   else
     458             :     {
     459          27 :       if (af == AF_IP6)
     460          16 :         ip6_punt_redirect_del (rx_sw_if_index);
     461          11 :       else if (af == AF_IP4)
     462          11 :         ip4_punt_redirect_del (rx_sw_if_index);
     463             :     }
     464          56 : }
     465             : 
     466             : static void
     467          55 : vl_api_ip_punt_redirect_t_handler (vl_api_ip_punt_redirect_t *mp,
     468             :                                    vlib_main_t *vm)
     469             : {
     470             :   vl_api_ip_punt_redirect_reply_t *rmp;
     471          55 :   fib_route_path_t *rpaths = NULL, rpath = {
     472             :     .frp_weight = 1,
     473             :     .frp_fib_index = ~0,
     474             :   };
     475             :   ip_address_family_t af;
     476             :   ip46_type_t ipv;
     477             :   u32 rx_sw_if_index;
     478          55 :   int rv = 0;
     479             : 
     480          55 :   if (!vnet_sw_if_index_is_api_valid (ntohl (mp->punt.tx_sw_if_index)))
     481           0 :     goto bad_sw_if_index;
     482             : 
     483          55 :   ipv = ip_address_decode (&mp->punt.nh, &rpath.frp_addr);
     484          55 :   af = (ipv == IP46_TYPE_IP6) ? AF_IP6 : AF_IP4;
     485          55 :   rpath.frp_proto = (ipv == IP46_TYPE_IP6) ? DPO_PROTO_IP6 : DPO_PROTO_IP4;
     486          55 :   rpath.frp_sw_if_index = ntohl (mp->punt.tx_sw_if_index);
     487          55 :   rx_sw_if_index = ntohl (mp->punt.rx_sw_if_index);
     488             : 
     489          55 :   vec_add1 (rpaths, rpath);
     490          55 :   ip_punt_redirect_t_handler_common (mp->is_add, rx_sw_if_index, af, rpaths);
     491          55 :   vec_free (rpaths);
     492             : 
     493          55 :   BAD_SW_IF_INDEX_LABEL;
     494             : 
     495          55 :   REPLY_MACRO (VL_API_IP_PUNT_REDIRECT_REPLY);
     496             : }
     497             : 
     498             : static void
     499           1 : vl_api_add_del_ip_punt_redirect_v2_t_handler (
     500             :   vl_api_add_del_ip_punt_redirect_v2_t *mp, vlib_main_t *vm)
     501             : {
     502             :   vl_api_add_del_ip_punt_redirect_v2_reply_t *rmp;
     503           1 :   fib_route_path_t *rpaths = NULL, *rpath;
     504             :   vl_api_fib_path_t *apath;
     505             :   ip_address_family_t af;
     506             :   u32 rx_sw_if_index, n_paths;
     507           1 :   int rv = 0, ii;
     508             : 
     509           1 :   rx_sw_if_index = ntohl (mp->punt.rx_sw_if_index);
     510           1 :   n_paths = ntohl (mp->punt.n_paths);
     511             : 
     512           1 :   rv = ip_address_family_decode (mp->punt.af, &af);
     513           1 :   if (rv != 0)
     514           0 :     goto out;
     515             : 
     516           1 :   if (0 != n_paths)
     517             :     {
     518           0 :       vec_validate (rpaths, n_paths - 1);
     519             :     }
     520             : 
     521           1 :   for (ii = 0; ii < n_paths; ii++)
     522             :     {
     523           0 :       apath = &mp->punt.paths[ii];
     524           0 :       rpath = &rpaths[ii];
     525             : 
     526           0 :       rv = fib_api_path_decode (apath, rpath);
     527             : 
     528           0 :       if (rv != 0)
     529           0 :         goto out;
     530             :     }
     531             : 
     532           1 :   ip_punt_redirect_t_handler_common (mp->is_add, rx_sw_if_index, af, rpaths);
     533             : 
     534           1 : out:
     535           1 :   vec_free (rpaths);
     536             : 
     537           1 :   REPLY_MACRO (VL_API_ADD_DEL_IP_PUNT_REDIRECT_V2_REPLY);
     538             : }
     539             : 
     540             : static clib_error_t *
     541         788 : call_elf_section_ip_table_callbacks (vnet_main_t * vnm, u32 table_id,
     542             :                                      u32 flags,
     543             :                                      _vnet_ip_table_function_list_elt_t **
     544             :                                      elts)
     545             : {
     546             :   _vnet_ip_table_function_list_elt_t *elt;
     547             :   vnet_ip_table_function_priority_t prio;
     548         788 :   clib_error_t *error = 0;
     549             : 
     550        2364 :   for (prio = VNET_IP_TABLE_FUNC_PRIORITY_LOW;
     551        1576 :        prio <= VNET_IP_TABLE_FUNC_PRIORITY_HIGH; prio++)
     552             :     {
     553        1576 :       elt = elts[prio];
     554             : 
     555        2364 :       while (elt)
     556             :         {
     557         788 :           error = elt->fp (vnm, table_id, flags);
     558         788 :           if (error)
     559           0 :             return error;
     560         788 :           elt = elt->next_ip_table_function;
     561             :         }
     562             :     }
     563         788 :   return error;
     564             : }
     565             : 
     566             : void
     567         956 : ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api)
     568             : {
     569             :   u32 fib_index, mfib_index;
     570         956 :   vnet_main_t *vnm = vnet_get_main ();
     571             : 
     572             :   /*
     573             :    * ignore action on the default table - this is always present
     574             :    * and cannot be added nor deleted from the API
     575             :    */
     576         956 :   if (0 != table_id)
     577             :     {
     578             :       /*
     579             :        * The API holds only one lock on the table.
     580             :        * i.e. it can be added many times via the API but needs to be
     581             :        * deleted only once.
     582             :        * The FIB index for unicast and multicast is not necessarily the
     583             :        * same, since internal VPP systesm (like LISP and SR) create
     584             :        * their own unicast tables.
     585             :        */
     586         956 :       fib_index = fib_table_find (fproto, table_id);
     587         956 :       mfib_index = mfib_table_find (fproto, table_id);
     588             : 
     589         956 :       if ((~0 != fib_index) || (~0 != mfib_index))
     590         386 :         call_elf_section_ip_table_callbacks (vnm, table_id, 0 /* is_add */ ,
     591         386 :                                              vnm->ip_table_add_del_functions);
     592             : 
     593         956 :       if (~0 != fib_index)
     594             :         {
     595         386 :           fib_table_unlock (fib_index, fproto,
     596             :                             (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI));
     597             :         }
     598         956 :       if (~0 != mfib_index)
     599             :         {
     600         386 :           mfib_table_unlock (mfib_index, fproto,
     601             :                              (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI));
     602             :         }
     603             :     }
     604         956 : }
     605             : 
     606             : /*
     607             :  * Returns an unused table id, and ~0 if it can't find one.
     608             :  */
     609             : u32
     610           6 : ip_table_get_unused_id (fib_protocol_t fproto)
     611             : {
     612             :   int i, j;
     613             :   static u32 seed = 0;
     614             :   /* limit to 1M tries */
     615           6 :   for (j = 0; j < 1 << 10; j++)
     616             :     {
     617           6 :       seed = random_u32 (&seed);
     618           6 :       for (i = 0; i < 1 << 10; i++)
     619             :         {
     620             :           /* look around randomly generated id */
     621           6 :           seed += (2 * (i % 2) - 1) * i;
     622           6 :           if (seed == ~0)
     623           0 :             continue;
     624           6 :           if (fib_table_find (fproto, seed) == ~0)
     625           6 :             return seed;
     626             :         }
     627             :     }
     628             : 
     629           0 :   return ~0;
     630             : }
     631             : 
     632             : void
     633        1410 : vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp)
     634             : {
     635             :   vl_api_ip_table_add_del_reply_t *rmp;
     636        1410 :   fib_protocol_t fproto = (mp->table.is_ip6 ?
     637        1410 :                            FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
     638        1410 :   u32 table_id = ntohl (mp->table.table_id);
     639        1410 :   int rv = 0;
     640             : 
     641        1410 :   if (mp->is_add)
     642             :     {
     643         454 :       ip_table_create (fproto, table_id, 1, mp->table.name);
     644             :     }
     645             :   else
     646             :     {
     647         956 :       ip_table_delete (fproto, table_id, 1);
     648             :     }
     649             : 
     650        1410 :   REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY);
     651             : }
     652             : 
     653             : void
     654           8 : vl_api_ip_table_allocate_t_handler (vl_api_ip_table_allocate_t *mp)
     655             : {
     656             :   vl_api_ip_table_allocate_reply_t *rmp;
     657           8 :   fib_protocol_t fproto =
     658           8 :     (mp->table.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
     659           8 :   u32 table_id = ntohl (mp->table.table_id);
     660           8 :   int rv = 0;
     661             : 
     662           8 :   if (~0 == table_id)
     663           6 :     table_id = ip_table_get_unused_id (fproto);
     664             : 
     665           8 :   if (~0 == table_id)
     666           0 :     rv = VNET_API_ERROR_EAGAIN;
     667             :   else
     668           8 :     ip_table_create (fproto, table_id, 1, mp->table.name);
     669             : 
     670           8 :   REPLY_MACRO2 (VL_API_IP_TABLE_ALLOCATE_REPLY, {
     671             :     clib_memcpy_fast (&rmp->table, &mp->table, sizeof (mp->table));
     672             :     rmp->table.table_id = htonl (table_id);
     673             :   })
     674             : }
     675             : 
     676             : static int
     677        7366 : ip_route_add_del_t_handler (vl_api_ip_route_add_del_t * mp, u32 * stats_index)
     678             : {
     679        7366 :   fib_route_path_t *rpaths = NULL, *rpath;
     680             :   fib_entry_flag_t entry_flags;
     681             :   vl_api_fib_path_t *apath;
     682             :   fib_prefix_t pfx;
     683             :   u32 fib_index;
     684             :   int rv, ii;
     685             : 
     686        7366 :   entry_flags = FIB_ENTRY_FLAG_NONE;
     687        7366 :   ip_prefix_decode (&mp->route.prefix, &pfx);
     688             : 
     689        7366 :   rv = fib_api_table_id_decode (pfx.fp_proto,
     690             :                                 ntohl (mp->route.table_id), &fib_index);
     691        7366 :   if (0 != rv)
     692           0 :     goto out;
     693             : 
     694        7366 :   if (0 != mp->route.n_paths)
     695        4376 :     vec_validate (rpaths, mp->route.n_paths - 1);
     696             : 
     697       12844 :   for (ii = 0; ii < mp->route.n_paths; ii++)
     698             :     {
     699        5478 :       apath = &mp->route.paths[ii];
     700        5478 :       rpath = &rpaths[ii];
     701             : 
     702        5478 :       rv = fib_api_path_decode (apath, rpath);
     703             : 
     704        5478 :       if ((rpath->frp_flags & FIB_ROUTE_PATH_LOCAL) &&
     705           1 :           (~0 == rpath->frp_sw_if_index))
     706           0 :         entry_flags |= (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL);
     707             : 
     708        5478 :       if (0 != rv)
     709           0 :         goto out;
     710             :     }
     711             : 
     712        7366 :   rv = fib_api_route_add_del (mp->is_add, mp->is_multipath, fib_index, &pfx,
     713             :                               FIB_SOURCE_API, entry_flags, rpaths);
     714             : 
     715        7366 :   if (mp->is_add && 0 == rv)
     716        4371 :     *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx);
     717             : 
     718        2995 : out:
     719        7366 :   vec_free (rpaths);
     720             : 
     721        7366 :   return (rv);
     722             : }
     723             : 
     724             : static int
     725           4 : ip_route_add_del_v2_t_handler (vl_api_ip_route_add_del_v2_t *mp,
     726             :                                u32 *stats_index)
     727             : {
     728           4 :   fib_route_path_t *rpaths = NULL, *rpath;
     729             :   fib_entry_flag_t entry_flags;
     730             :   vl_api_fib_path_t *apath;
     731             :   fib_source_t src;
     732             :   fib_prefix_t pfx;
     733             :   u32 fib_index;
     734             :   int rv, ii;
     735             : 
     736           4 :   entry_flags = FIB_ENTRY_FLAG_NONE;
     737           4 :   ip_prefix_decode (&mp->route.prefix, &pfx);
     738             : 
     739           4 :   rv = fib_api_table_id_decode (pfx.fp_proto, ntohl (mp->route.table_id),
     740             :                                 &fib_index);
     741           4 :   if (0 != rv)
     742           0 :     goto out;
     743             : 
     744           4 :   if (0 != mp->route.n_paths)
     745           2 :     vec_validate (rpaths, mp->route.n_paths - 1);
     746             : 
     747           6 :   for (ii = 0; ii < mp->route.n_paths; ii++)
     748             :     {
     749           2 :       apath = &mp->route.paths[ii];
     750           2 :       rpath = &rpaths[ii];
     751             : 
     752           2 :       rv = fib_api_path_decode (apath, rpath);
     753             : 
     754           2 :       if ((rpath->frp_flags & FIB_ROUTE_PATH_LOCAL) &&
     755           0 :           (~0 == rpath->frp_sw_if_index))
     756           0 :         entry_flags |= (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL);
     757             : 
     758           2 :       if (0 != rv)
     759           0 :         goto out;
     760             :     }
     761             : 
     762           4 :   src = (0 == mp->route.src ? FIB_SOURCE_API : mp->route.src);
     763             : 
     764           4 :   rv = fib_api_route_add_del (mp->is_add, mp->is_multipath, fib_index, &pfx,
     765             :                               src, entry_flags, rpaths);
     766             : 
     767           4 :   if (mp->is_add && 0 == rv)
     768           2 :     *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx);
     769             : 
     770           2 : out:
     771           4 :   vec_free (rpaths);
     772             : 
     773           4 :   return (rv);
     774             : }
     775             : 
     776             : void
     777        7366 : vl_api_ip_route_add_del_t_handler (vl_api_ip_route_add_del_t * mp)
     778             : {
     779             :   vl_api_ip_route_add_del_reply_t *rmp;
     780        7366 :   u32 stats_index = ~0;
     781             :   int rv;
     782             : 
     783        7366 :   rv = ip_route_add_del_t_handler (mp, &stats_index);
     784             : 
     785             :   /* *INDENT-OFF* */
     786        7366 :   REPLY_MACRO2 (VL_API_IP_ROUTE_ADD_DEL_REPLY,
     787             :   ({
     788             :     rmp->stats_index = htonl (stats_index);
     789             :   }))
     790             :   /* *INDENT-ON* */
     791             : }
     792             : 
     793             : void
     794           4 : vl_api_ip_route_add_del_v2_t_handler (vl_api_ip_route_add_del_v2_t *mp)
     795             : {
     796             :   vl_api_ip_route_add_del_v2_reply_t *rmp;
     797           4 :   u32 stats_index = ~0;
     798             :   int rv;
     799             : 
     800           4 :   rv = ip_route_add_del_v2_t_handler (mp, &stats_index);
     801             : 
     802             :   /* clang-format off */
     803           4 :   REPLY_MACRO2 (VL_API_IP_ROUTE_ADD_DEL_V2_REPLY,
     804             :   ({
     805             :     rmp->stats_index = htonl (stats_index);
     806             :   }))
     807             :   /* clang-format on */
     808             : }
     809             : 
     810             : void
     811          10 : vl_api_ip_route_lookup_t_handler (vl_api_ip_route_lookup_t * mp)
     812             : {
     813          10 :   vl_api_ip_route_lookup_reply_t *rmp = NULL;
     814          10 :   fib_route_path_t *rpaths = NULL, *rpath;
     815          10 :   const fib_prefix_t *pfx = NULL;
     816             :   fib_prefix_t lookup;
     817             :   vl_api_fib_path_t *fp;
     818             :   fib_node_index_t fib_entry_index;
     819             :   u32 fib_index;
     820          10 :   int npaths = 0;
     821             :   int rv;
     822             : 
     823          10 :   ip_prefix_decode (&mp->prefix, &lookup);
     824          10 :   rv = fib_api_table_id_decode (lookup.fp_proto, ntohl (mp->table_id),
     825             :                                 &fib_index);
     826          10 :   if (PREDICT_TRUE (!rv))
     827             :     {
     828          10 :       if (mp->exact)
     829           6 :         fib_entry_index = fib_table_lookup_exact_match (fib_index, &lookup);
     830             :       else
     831           4 :         fib_entry_index = fib_table_lookup (fib_index, &lookup);
     832          10 :       if (fib_entry_index == FIB_NODE_INDEX_INVALID)
     833           2 :         rv = VNET_API_ERROR_NO_SUCH_ENTRY;
     834             :       else
     835             :         {
     836           8 :           pfx = fib_entry_get_prefix (fib_entry_index);
     837           8 :           rpaths = fib_entry_encode (fib_entry_index);
     838           8 :           npaths = vec_len (rpaths);
     839             :         }
     840             :     }
     841             : 
     842             :   /* *INDENT-OFF* */
     843          18 :   REPLY_MACRO3_ZERO(VL_API_IP_ROUTE_LOOKUP_REPLY,
     844             :                     npaths * sizeof (*fp),
     845             :   ({
     846             :     if (!rv)
     847             :       {
     848             :         ip_prefix_encode (pfx, &rmp->route.prefix);
     849             :         rmp->route.table_id = mp->table_id;
     850             :         rmp->route.n_paths = npaths;
     851             :         rmp->route.stats_index = fib_table_entry_get_stats_index (fib_index, pfx);
     852             :         rmp->route.stats_index = htonl (rmp->route.stats_index);
     853             : 
     854             :         fp = rmp->route.paths;
     855             :         vec_foreach (rpath, rpaths)
     856             :           {
     857             :             fib_api_path_encode (rpath, fp);
     858             :             fp++;
     859             :           }
     860             :       }
     861             :   }));
     862             :   /* *INDENT-ON* */
     863          10 :   vec_free (rpaths);
     864             : }
     865             : 
     866             : void
     867           0 : vl_api_ip_route_lookup_v2_t_handler (vl_api_ip_route_lookup_v2_t *mp)
     868             : {
     869           0 :   vl_api_ip_route_lookup_v2_reply_t *rmp = NULL;
     870           0 :   fib_route_path_t *rpaths = NULL, *rpath;
     871           0 :   const fib_prefix_t *pfx = NULL;
     872             :   fib_prefix_t lookup;
     873             :   vl_api_fib_path_t *fp;
     874             :   fib_node_index_t fib_entry_index;
     875             :   u32 fib_index;
     876           0 :   int npaths = 0;
     877           0 :   fib_source_t src = 0;
     878             :   int rv;
     879             : 
     880           0 :   ip_prefix_decode (&mp->prefix, &lookup);
     881           0 :   rv = fib_api_table_id_decode (lookup.fp_proto, ntohl (mp->table_id),
     882             :                                 &fib_index);
     883           0 :   if (PREDICT_TRUE (!rv))
     884             :     {
     885           0 :       if (mp->exact)
     886           0 :         fib_entry_index = fib_table_lookup_exact_match (fib_index, &lookup);
     887             :       else
     888           0 :         fib_entry_index = fib_table_lookup (fib_index, &lookup);
     889           0 :       if (fib_entry_index == FIB_NODE_INDEX_INVALID)
     890           0 :         rv = VNET_API_ERROR_NO_SUCH_ENTRY;
     891             :       else
     892             :         {
     893           0 :           pfx = fib_entry_get_prefix (fib_entry_index);
     894           0 :           rpaths = fib_entry_encode (fib_entry_index);
     895           0 :           npaths = vec_len (rpaths);
     896           0 :           src = fib_entry_get_best_source (fib_entry_index);
     897             :         }
     898             :     }
     899             : 
     900             :   /* clang-format off */
     901           0 :   REPLY_MACRO3_ZERO(VL_API_IP_ROUTE_LOOKUP_V2_REPLY,
     902             :                     npaths * sizeof (*fp),
     903             :   ({
     904             :     if (!rv)
     905             :       {
     906             :         ip_prefix_encode (pfx, &rmp->route.prefix);
     907             :         rmp->route.table_id = mp->table_id;
     908             :         rmp->route.n_paths = npaths;
     909             :         rmp->route.src = src;
     910             :         rmp->route.stats_index = fib_table_entry_get_stats_index (fib_index, pfx);
     911             :         rmp->route.stats_index = htonl (rmp->route.stats_index);
     912             : 
     913             :         fp = rmp->route.paths;
     914             :         vec_foreach (rpath, rpaths)
     915             :           {
     916             :             fib_api_path_encode (rpath, fp);
     917             :             fp++;
     918             :           }
     919             :       }
     920             :   }));
     921             :   /* clang-format on */
     922           0 :   vec_free (rpaths);
     923             : }
     924             : 
     925             : void
     926         466 : ip_table_create (fib_protocol_t fproto,
     927             :                  u32 table_id, u8 is_api, const u8 * name)
     928             : {
     929             :   u32 fib_index, mfib_index;
     930         466 :   vnet_main_t *vnm = vnet_get_main ();
     931             : 
     932             :   /*
     933             :    * ignore action on the default table - this is always present
     934             :    * and cannot be added nor deleted from the API
     935             :    */
     936         466 :   if (0 != table_id)
     937             :     {
     938             :       /*
     939             :        * The API holds only one lock on the table.
     940             :        * i.e. it can be added many times via the API but needs to be
     941             :        * deleted only once.
     942             :        * The FIB index for unicast and multicast is not necessarily the
     943             :        * same, since internal VPP systesm (like LISP and SR) create
     944             :        * their own unicast tables.
     945             :        */
     946         466 :       fib_index = fib_table_find (fproto, table_id);
     947         466 :       mfib_index = mfib_table_find (fproto, table_id);
     948             : 
     949             :       /*
     950             :        * Always try to re-lock in case the fib was deleted by an API call
     951             :        * but was not yet freed because some other locks were held
     952             :        */
     953         466 :       fib_table_find_or_create_and_lock_w_name (
     954             :         fproto, table_id, (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI), name);
     955         466 :       mfib_table_find_or_create_and_lock_w_name (
     956             :         fproto, table_id, (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI), name);
     957             : 
     958         466 :       if ((~0 == fib_index) || (~0 == mfib_index))
     959         402 :         call_elf_section_ip_table_callbacks (vnm, table_id, 1 /* is_add */ ,
     960         402 :                                              vnm->ip_table_add_del_functions);
     961             :     }
     962         466 : }
     963             : 
     964             : static u32
     965         938 : mroute_add_del_handler (u8 is_add,
     966             :                         u8 is_multipath,
     967             :                         u32 fib_index,
     968             :                         const mfib_prefix_t * prefix,
     969             :                         u32 entry_flags,
     970             :                         u32 rpf_id, fib_route_path_t * rpaths)
     971             : {
     972         938 :   u32 mfib_entry_index = ~0;
     973             : 
     974         938 :   if (0 == vec_len (rpaths))
     975             :     {
     976          15 :       mfib_entry_index = mfib_table_entry_update (fib_index, prefix,
     977             :                                                   MFIB_SOURCE_API,
     978             :                                                   rpf_id, entry_flags);
     979             :     }
     980             :   else
     981             :     {
     982         923 :       if (is_add)
     983             :         {
     984         896 :           mfib_entry_index = mfib_table_entry_paths_update (
     985             :             fib_index, prefix, MFIB_SOURCE_API, entry_flags, rpaths);
     986             :         }
     987             :       else
     988             :         {
     989          27 :           mfib_table_entry_paths_remove (fib_index, prefix,
     990             :                                          MFIB_SOURCE_API, rpaths);
     991             :         }
     992             :     }
     993             : 
     994         938 :   return (mfib_entry_index);
     995             : }
     996             : 
     997             : static int
     998         938 : api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp,
     999             :                               u32 * stats_index)
    1000             : {
    1001         938 :   fib_route_path_t *rpath, *rpaths = NULL;
    1002             :   fib_node_index_t mfib_entry_index;
    1003             :   mfib_entry_flags_t eflags;
    1004             :   mfib_prefix_t pfx;
    1005             :   u32 fib_index;
    1006             :   int rv;
    1007             :   u16 ii;
    1008             : 
    1009         938 :   ip_mprefix_decode (&mp->route.prefix, &pfx);
    1010             : 
    1011         938 :   rv = mfib_api_table_id_decode (pfx.fp_proto,
    1012             :                                  ntohl (mp->route.table_id), &fib_index);
    1013         938 :   if (0 != rv)
    1014           0 :     goto out;
    1015             : 
    1016         938 :   vec_validate (rpaths, mp->route.n_paths - 1);
    1017             : 
    1018        4529 :   for (ii = 0; ii < mp->route.n_paths; ii++)
    1019             :     {
    1020        3591 :       rpath = &rpaths[ii];
    1021             : 
    1022        3591 :       rv = mfib_api_path_decode (&mp->route.paths[ii], rpath);
    1023             : 
    1024        3591 :       if (0 != rv)
    1025           0 :         goto out;
    1026             :     }
    1027             : 
    1028         938 :   eflags = mfib_api_path_entry_flags_decode (mp->route.entry_flags);
    1029         938 :   mfib_entry_index = mroute_add_del_handler (mp->is_add,
    1030         938 :                                              mp->is_add,
    1031             :                                              fib_index, &pfx,
    1032             :                                              eflags,
    1033             :                                              ntohl (mp->route.rpf_id),
    1034             :                                              rpaths);
    1035             : 
    1036         938 :   if (~0 != mfib_entry_index)
    1037         911 :     *stats_index = mfib_entry_get_stats_index (mfib_entry_index);
    1038             : 
    1039          27 : out:
    1040         938 :   return (rv);
    1041             : }
    1042             : 
    1043             : void
    1044         938 : vl_api_ip_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
    1045             : {
    1046             :   vl_api_ip_mroute_add_del_reply_t *rmp;
    1047         938 :   u32 stats_index = ~0;
    1048             :   int rv;
    1049             : 
    1050         938 :   rv = api_mroute_add_del_t_handler (mp, &stats_index);
    1051             : 
    1052             :   /* *INDENT-OFF* */
    1053         938 :   REPLY_MACRO2 (VL_API_IP_MROUTE_ADD_DEL_REPLY,
    1054             :   ({
    1055             :     rmp->stats_index = htonl (stats_index);
    1056             :   }));
    1057             :   /* *INDENT-ON* */
    1058             : }
    1059             : 
    1060             : static void
    1061           0 : send_ip_details (vpe_api_main_t * am,
    1062             :                  vl_api_registration_t * reg, u32 sw_if_index, u8 is_ipv6,
    1063             :                  u32 context)
    1064             : {
    1065             :   vl_api_ip_details_t *mp;
    1066             : 
    1067           0 :   mp = vl_msg_api_alloc (sizeof (*mp));
    1068           0 :   clib_memset (mp, 0, sizeof (*mp));
    1069           0 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IP_DETAILS);
    1070             : 
    1071           0 :   mp->sw_if_index = ntohl (sw_if_index);
    1072           0 :   mp->is_ipv6 = is_ipv6;
    1073           0 :   mp->context = context;
    1074             : 
    1075           0 :   vl_api_send_msg (reg, (u8 *) mp);
    1076           0 : }
    1077             : 
    1078             : static void
    1079         185 : send_ip_address_details (vpe_api_main_t * am,
    1080             :                          vl_api_registration_t * reg,
    1081             :                          const fib_prefix_t * pfx,
    1082             :                          u32 sw_if_index, u32 context)
    1083             : {
    1084             :   vl_api_ip_address_details_t *mp;
    1085             : 
    1086         185 :   mp = vl_msg_api_alloc (sizeof (*mp));
    1087         185 :   clib_memset (mp, 0, sizeof (*mp));
    1088         185 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IP_ADDRESS_DETAILS);
    1089             : 
    1090         185 :   ip_prefix_encode (pfx, &mp->prefix);
    1091         185 :   mp->context = context;
    1092         185 :   mp->sw_if_index = htonl (sw_if_index);
    1093             : 
    1094         185 :   vl_api_send_msg (reg, (u8 *) mp);
    1095         185 : }
    1096             : 
    1097             : static void
    1098         164 : vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
    1099             : {
    1100         164 :   vpe_api_main_t *am = &vpe_api_main;
    1101             :   vl_api_registration_t *reg;
    1102         164 :   ip6_main_t *im6 = &ip6_main;
    1103         164 :   ip4_main_t *im4 = &ip4_main;
    1104         164 :   ip_lookup_main_t *lm6 = &im6->lookup_main;
    1105         164 :   ip_lookup_main_t *lm4 = &im4->lookup_main;
    1106         164 :   ip_interface_address_t *ia = 0;
    1107         164 :   u32 sw_if_index = ~0;
    1108         164 :   int rv __attribute__ ((unused)) = 0;
    1109             : 
    1110         164 :   VALIDATE_SW_IF_INDEX (mp);
    1111             : 
    1112         163 :   sw_if_index = ntohl (mp->sw_if_index);
    1113             : 
    1114         163 :   reg = vl_api_client_index_to_registration (mp->client_index);
    1115         163 :   if (!reg)
    1116           0 :     return;
    1117             : 
    1118         163 :   if (mp->is_ipv6)
    1119             :     {
    1120             :       /* *INDENT-OFF* */
    1121             :       /* Do not send subnet details of the IP-interface for
    1122             :        * unnumbered interfaces. otherwise listening clients
    1123             :        * will be confused that the subnet is applied on more
    1124             :        * than one interface */
    1125         172 :       foreach_ip_interface_address (lm6, ia, sw_if_index, 0,
    1126             :       ({
    1127             :         fib_prefix_t pfx = {
    1128             :           .fp_addr.ip6 = *(ip6_address_t *)ip_interface_address_get_address (lm6, ia),
    1129             :           .fp_len = ia->address_length,
    1130             :           .fp_proto = FIB_PROTOCOL_IP6,
    1131             :         };
    1132             :         send_ip_address_details(am, reg, &pfx, sw_if_index, mp->context);
    1133             :       }));
    1134             :       /* *INDENT-ON* */
    1135             :     }
    1136             :   else
    1137             :     {
    1138             :       /* *INDENT-OFF* */
    1139         176 :       foreach_ip_interface_address (lm4, ia, sw_if_index, 0,
    1140             :       ({
    1141             :         fib_prefix_t pfx = {
    1142             :           .fp_addr.ip4 = *(ip4_address_t *)ip_interface_address_get_address (lm4, ia),
    1143             :           .fp_len = ia->address_length,
    1144             :           .fp_proto = FIB_PROTOCOL_IP4,
    1145             :         };
    1146             : 
    1147             :         send_ip_address_details(am, reg, &pfx, sw_if_index, mp->context);
    1148             :       }));
    1149             :       /* *INDENT-ON* */
    1150             :     }
    1151             : 
    1152          83 :   BAD_SW_IF_INDEX_LABEL;
    1153             : }
    1154             : 
    1155             : static void
    1156           2 : send_ip_unnumbered_details (vpe_api_main_t * am,
    1157             :                             vl_api_registration_t * reg,
    1158             :                             u32 sw_if_index, u32 ip_sw_if_index, u32 context)
    1159             : {
    1160             :   vl_api_ip_unnumbered_details_t *mp;
    1161             : 
    1162           2 :   mp = vl_msg_api_alloc (sizeof (*mp));
    1163           2 :   clib_memset (mp, 0, sizeof (*mp));
    1164           2 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IP_UNNUMBERED_DETAILS);
    1165             : 
    1166           2 :   mp->context = context;
    1167           2 :   mp->sw_if_index = htonl (sw_if_index);
    1168           2 :   mp->ip_sw_if_index = htonl (ip_sw_if_index);
    1169             : 
    1170           2 :   vl_api_send_msg (reg, (u8 *) mp);
    1171           2 : }
    1172             : 
    1173             : static void
    1174           2 : vl_api_ip_unnumbered_dump_t_handler (vl_api_ip_unnumbered_dump_t * mp)
    1175             : {
    1176           2 :   vnet_main_t *vnm = vnet_get_main ();
    1177           2 :   vnet_interface_main_t *im = &vnm->interface_main;
    1178           2 :   int rv __attribute__ ((unused)) = 0;
    1179           2 :   vpe_api_main_t *am = &vpe_api_main;
    1180             :   vl_api_registration_t *reg;
    1181             :   vnet_sw_interface_t *si;
    1182             :   u32 sw_if_index;
    1183             : 
    1184           2 :   sw_if_index = ntohl (mp->sw_if_index);
    1185             : 
    1186           2 :   reg = vl_api_client_index_to_registration (mp->client_index);
    1187           2 :   if (!reg)
    1188           0 :     return;
    1189             : 
    1190           2 :   if (~0 != sw_if_index)
    1191             :     {
    1192           1 :       VALIDATE_SW_IF_INDEX (mp);
    1193             : 
    1194           1 :       si = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
    1195             : 
    1196           1 :       if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
    1197             :         {
    1198           1 :           send_ip_unnumbered_details (am, reg,
    1199             :                                       sw_if_index,
    1200             :                                       si->unnumbered_sw_if_index,
    1201             :                                       mp->context);
    1202             :         }
    1203             :     }
    1204             :   else
    1205             :     {
    1206             :       /* *INDENT-OFF* */
    1207           6 :       pool_foreach (si, im->sw_interfaces)
    1208             :        {
    1209           5 :         if ((si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
    1210             :           {
    1211           1 :             send_ip_unnumbered_details(am, reg,
    1212             :                                        si->sw_if_index,
    1213             :                                        si->unnumbered_sw_if_index,
    1214             :                                        mp->context);
    1215             :           }
    1216             :       }
    1217             :       /* *INDENT-ON* */
    1218             :     }
    1219             : 
    1220           1 :   BAD_SW_IF_INDEX_LABEL;
    1221             : }
    1222             : 
    1223             : static void
    1224           0 : vl_api_ip_dump_t_handler (vl_api_ip_dump_t * mp)
    1225             : {
    1226           0 :   vpe_api_main_t *am = &vpe_api_main;
    1227           0 :   vnet_main_t *vnm = vnet_get_main ();
    1228             :   //vlib_main_t *vm = vlib_get_main ();
    1229           0 :   vnet_interface_main_t *im = &vnm->interface_main;
    1230             :   vl_api_registration_t *reg;
    1231             :   vnet_sw_interface_t *si, *sorted_sis;
    1232           0 :   u32 sw_if_index = ~0;
    1233             : 
    1234           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
    1235           0 :   if (!reg)
    1236           0 :     return;
    1237             : 
    1238             :   /* Gather interfaces. */
    1239           0 :   sorted_sis = vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
    1240           0 :   vec_set_len (sorted_sis, 0);
    1241             :   /* *INDENT-OFF* */
    1242           0 :   pool_foreach (si, im->sw_interfaces)
    1243             :    {
    1244           0 :     vec_add1 (sorted_sis, si[0]);
    1245             :   }
    1246             :   /* *INDENT-ON* */
    1247             : 
    1248           0 :   vec_foreach (si, sorted_sis)
    1249             :   {
    1250           0 :     if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
    1251             :       {
    1252             :         /* if (mp->is_ipv6 && !ip6_interface_enabled (vm, si->sw_if_index)) */
    1253             :         /*   { */
    1254             :         /*     continue; */
    1255             :         /*   } */
    1256           0 :         sw_if_index = si->sw_if_index;
    1257           0 :         send_ip_details (am, reg, sw_if_index, mp->is_ipv6, mp->context);
    1258             :       }
    1259             :   }
    1260             : 
    1261           0 :   vec_free (sorted_sis);
    1262             : }
    1263             : 
    1264             : static void
    1265           3 : vl_api_set_ip_flow_hash_t_handler (vl_api_set_ip_flow_hash_t *mp)
    1266             : {
    1267             :   vl_api_set_ip_flow_hash_reply_t *rmp;
    1268             :   int rv;
    1269             :   u32 table_id;
    1270           3 :   flow_hash_config_t flow_hash_config = 0;
    1271             : 
    1272           3 :   table_id = ntohl (mp->vrf_id);
    1273             : 
    1274             : #define _(a,b) if (mp->a) flow_hash_config |= b;
    1275           3 :   foreach_flow_hash_bit_v1;
    1276             : #undef _
    1277             : 
    1278           3 :   rv = ip_flow_hash_set ((mp->is_ipv6 ? AF_IP6 : AF_IP4), table_id,
    1279             :                          flow_hash_config);
    1280             : 
    1281           3 :   REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
    1282             : }
    1283             : 
    1284             : static void
    1285           1 : vl_api_set_ip_flow_hash_v2_t_handler (vl_api_set_ip_flow_hash_v2_t *mp)
    1286             : {
    1287             :   vl_api_set_ip_flow_hash_v2_reply_t *rmp;
    1288             :   ip_address_family_t af;
    1289             :   int rv;
    1290             : 
    1291           1 :   rv = ip_address_family_decode (mp->af, &af);
    1292             : 
    1293           1 :   if (!rv)
    1294           1 :     rv = ip_flow_hash_set (af, htonl (mp->table_id),
    1295           1 :                            htonl (mp->flow_hash_config));
    1296             : 
    1297           1 :   REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_V2_REPLY);
    1298             : }
    1299             : 
    1300             : static void
    1301           1 : vl_api_set_ip_flow_hash_v3_t_handler (vl_api_set_ip_flow_hash_v3_t *mp)
    1302             : {
    1303             :   vl_api_set_ip_flow_hash_v3_reply_t *rmp;
    1304             :   ip_address_family_t af;
    1305             :   int rv;
    1306             : 
    1307           1 :   rv = ip_address_family_decode (mp->af, &af);
    1308             : 
    1309           1 :   if (!rv)
    1310           1 :     rv = ip_flow_hash_set (af, htonl (mp->table_id),
    1311           1 :                            htonl (mp->flow_hash_config));
    1312             : 
    1313           1 :   REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_V3_REPLY);
    1314             : }
    1315             : 
    1316             : static void
    1317           2 : vl_api_set_ip_flow_hash_router_id_t_handler (
    1318             :   vl_api_set_ip_flow_hash_router_id_t *mp)
    1319             : {
    1320             :   vl_api_set_ip_flow_hash_router_id_reply_t *rmp;
    1321           2 :   int rv = 0;
    1322             : 
    1323           2 :   ip_flow_hash_router_id_set (ntohl (mp->router_id));
    1324             : 
    1325           2 :   REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_ROUTER_ID_REPLY);
    1326             : }
    1327             : 
    1328             : void
    1329           7 : vl_mfib_signal_send_one (vl_api_registration_t * reg,
    1330             :                          u32 context, const mfib_signal_t * mfs)
    1331             : {
    1332             :   vl_api_mfib_signal_details_t *mp;
    1333             :   const mfib_prefix_t *prefix;
    1334             :   mfib_table_t *mfib;
    1335             :   mfib_itf_t *mfi;
    1336             : 
    1337           7 :   mp = vl_msg_api_alloc (sizeof (*mp));
    1338             : 
    1339           7 :   clib_memset (mp, 0, sizeof (*mp));
    1340           7 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_MFIB_SIGNAL_DETAILS);
    1341           7 :   mp->context = context;
    1342             : 
    1343           7 :   mfi = mfib_itf_get (mfs->mfs_itf);
    1344           7 :   prefix = mfib_entry_get_prefix (mfs->mfs_entry);
    1345           7 :   mfib = mfib_table_get (mfib_entry_get_fib_index (mfs->mfs_entry),
    1346           7 :                          prefix->fp_proto);
    1347           7 :   mp->table_id = ntohl (mfib->mft_table_id);
    1348           7 :   mp->sw_if_index = ntohl (mfi->mfi_sw_if_index);
    1349             : 
    1350           7 :   ip_mprefix_encode (prefix, &mp->prefix);
    1351             : 
    1352           7 :   if (0 != mfs->mfs_buffer_len)
    1353             :     {
    1354           7 :       mp->ip_packet_len = ntohs (mfs->mfs_buffer_len);
    1355             : 
    1356           7 :       memcpy (mp->ip_packet_data, mfs->mfs_buffer, mfs->mfs_buffer_len);
    1357             :     }
    1358             :   else
    1359             :     {
    1360           0 :       mp->ip_packet_len = 0;
    1361             :     }
    1362             : 
    1363           7 :   vl_api_send_msg (reg, (u8 *) mp);
    1364           7 : }
    1365             : 
    1366             : static void
    1367           8 : vl_api_mfib_signal_dump_t_handler (vl_api_mfib_signal_dump_t * mp)
    1368             : {
    1369             :   vl_api_registration_t *reg;
    1370             : 
    1371           8 :   reg = vl_api_client_index_to_registration (mp->client_index);
    1372           8 :   if (!reg)
    1373           0 :     return;
    1374             : 
    1375          15 :   while (vl_api_can_send_msg (reg) && mfib_signal_send_one (reg, mp->context))
    1376             :     ;
    1377             : }
    1378             : 
    1379             : static void
    1380           0 :   vl_api_ip_container_proxy_add_del_t_handler
    1381             :   (vl_api_ip_container_proxy_add_del_t * mp)
    1382             : {
    1383             :   vl_api_ip_container_proxy_add_del_reply_t *rmp;
    1384             :   vnet_ip_container_proxy_args_t args;
    1385           0 :   int rv = 0;
    1386             :   clib_error_t *error;
    1387             : 
    1388           0 :   clib_memset (&args, 0, sizeof (args));
    1389             : 
    1390           0 :   ip_prefix_decode (&mp->pfx, &args.prefix);
    1391             : 
    1392           0 :   args.sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
    1393           0 :   args.is_add = mp->is_add;
    1394           0 :   if ((error = vnet_ip_container_proxy_add_del (&args)))
    1395             :     {
    1396           0 :       rv = clib_error_get_code (error);
    1397           0 :       clib_error_report (error);
    1398             :     }
    1399             : 
    1400           0 :   REPLY_MACRO (VL_API_IP_CONTAINER_PROXY_ADD_DEL_REPLY);
    1401             : }
    1402             : 
    1403             : typedef struct ip_walk_ctx_t_
    1404             : {
    1405             :   vl_api_registration_t *reg;
    1406             :   u32 context;
    1407             : } ip_walk_ctx_t;
    1408             : 
    1409             : static int
    1410           0 : ip_container_proxy_send_details (const fib_prefix_t * pfx, u32 sw_if_index,
    1411             :                                  void *args)
    1412             : {
    1413             :   vl_api_ip_container_proxy_details_t *mp;
    1414           0 :   ip_walk_ctx_t *ctx = args;
    1415             : 
    1416           0 :   mp = vl_msg_api_alloc (sizeof (*mp));
    1417           0 :   if (!mp)
    1418           0 :     return 1;
    1419             : 
    1420           0 :   clib_memset (mp, 0, sizeof (*mp));
    1421           0 :   mp->_vl_msg_id =
    1422           0 :     ntohs (REPLY_MSG_ID_BASE + VL_API_IP_CONTAINER_PROXY_DETAILS);
    1423           0 :   mp->context = ctx->context;
    1424             : 
    1425           0 :   mp->sw_if_index = ntohl (sw_if_index);
    1426           0 :   ip_prefix_encode (pfx, &mp->prefix);
    1427             : 
    1428           0 :   vl_api_send_msg (ctx->reg, (u8 *) mp);
    1429             : 
    1430           0 :   return 1;
    1431             : }
    1432             : 
    1433             : static void
    1434           0 : vl_api_ip_container_proxy_dump_t_handler (vl_api_ip_container_proxy_dump_t *
    1435             :                                           mp)
    1436             : {
    1437             :   vl_api_registration_t *reg;
    1438             : 
    1439           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
    1440           0 :   if (!reg)
    1441           0 :     return;
    1442             : 
    1443           0 :   ip_walk_ctx_t ctx = {
    1444           0 :     .context = mp->context,
    1445             :     .reg = reg,
    1446             :   };
    1447             : 
    1448           0 :   ip_container_proxy_walk (ip_container_proxy_send_details, &ctx);
    1449             : }
    1450             : 
    1451             : static void
    1452           0 : vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
    1453             : {
    1454           0 :   int rv = 0;
    1455             :   vl_api_ioam_enable_reply_t *rmp;
    1456             :   clib_error_t *error;
    1457             : 
    1458             :   /* Ignoring the profile id as currently a single profile
    1459             :    * is supported */
    1460           0 :   error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
    1461           0 :                            mp->seqno, mp->analyse);
    1462           0 :   if (error)
    1463             :     {
    1464           0 :       clib_error_report (error);
    1465           0 :       rv = clib_error_get_code (error);
    1466             :     }
    1467             : 
    1468           0 :   REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
    1469             : }
    1470             : 
    1471             : static void
    1472           0 : vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
    1473             : {
    1474           0 :   int rv = 0;
    1475             :   vl_api_ioam_disable_reply_t *rmp;
    1476             :   clib_error_t *error;
    1477             : 
    1478           0 :   error = clear_ioam_rewrite_fn ();
    1479           0 :   if (error)
    1480             :     {
    1481           0 :       clib_error_report (error);
    1482           0 :       rv = clib_error_get_code (error);
    1483             :     }
    1484             : 
    1485           0 :   REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
    1486             : }
    1487             : 
    1488             : static void
    1489           0 :   vl_api_ip_source_and_port_range_check_add_del_t_handler
    1490             :   (vl_api_ip_source_and_port_range_check_add_del_t * mp)
    1491             : {
    1492             :   vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
    1493           0 :   int rv = 0;
    1494             : 
    1495           0 :   u8 is_add = mp->is_add;
    1496             :   fib_prefix_t pfx;
    1497           0 :   u16 *low_ports = 0;
    1498           0 :   u16 *high_ports = 0;
    1499             :   u32 vrf_id;
    1500             :   u16 tmp_low, tmp_high;
    1501             :   u8 num_ranges;
    1502             :   int i;
    1503             : 
    1504           0 :   ip_prefix_decode (&mp->prefix, &pfx);
    1505             : 
    1506             :   // Validate port range
    1507           0 :   num_ranges = mp->number_of_ranges;
    1508           0 :   if (num_ranges > 32)
    1509             :     {                           // This is size of array in VPE.API
    1510           0 :       rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
    1511           0 :       goto reply;
    1512             :     }
    1513             : 
    1514           0 :   vec_reset_length (low_ports);
    1515           0 :   vec_reset_length (high_ports);
    1516             : 
    1517           0 :   for (i = 0; i < num_ranges; i++)
    1518             :     {
    1519           0 :       tmp_low = mp->low_ports[i];
    1520           0 :       tmp_high = mp->high_ports[i];
    1521             :       // If tmp_low <= tmp_high then only need to check tmp_low = 0
    1522             :       // If tmp_low <= tmp_high then only need to check tmp_high > 65535
    1523           0 :       if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
    1524             :         {
    1525           0 :           rv = VNET_API_ERROR_INVALID_VALUE;
    1526           0 :           goto reply;
    1527             :         }
    1528           0 :       vec_add1 (low_ports, tmp_low);
    1529           0 :       vec_add1 (high_ports, tmp_high + 1);
    1530             :     }
    1531             : 
    1532           0 :   vrf_id = ntohl (mp->vrf_id);
    1533             : 
    1534           0 :   if (vrf_id < 1)
    1535             :     {
    1536           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
    1537           0 :       goto reply;
    1538             :     }
    1539             : 
    1540             : 
    1541           0 :   if (FIB_PROTOCOL_IP6 == pfx.fp_proto)
    1542             :     {
    1543           0 :       rv = ip6_source_and_port_range_check_add_del (&pfx.fp_addr.ip6,
    1544           0 :                                                     pfx.fp_len,
    1545             :                                                     vrf_id,
    1546             :                                                     low_ports,
    1547             :                                                     high_ports, is_add);
    1548             :     }
    1549             :   else
    1550             :     {
    1551           0 :       rv = ip4_source_and_port_range_check_add_del (&pfx.fp_addr.ip4,
    1552           0 :                                                     pfx.fp_len,
    1553             :                                                     vrf_id,
    1554             :                                                     low_ports,
    1555             :                                                     high_ports, is_add);
    1556             :     }
    1557             : 
    1558           0 : reply:
    1559           0 :   vec_free (low_ports);
    1560           0 :   vec_free (high_ports);
    1561           0 :   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
    1562             : }
    1563             : 
    1564             : static void
    1565           0 :   vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
    1566             :   (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
    1567             : {
    1568           0 :   vlib_main_t *vm = vlib_get_main ();
    1569             :   vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
    1570           0 :   ip4_main_t *im = &ip4_main;
    1571             :   int rv;
    1572             :   u32 sw_if_index;
    1573             :   u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
    1574             :   u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
    1575           0 :   uword *p = 0;
    1576             :   int i;
    1577             : 
    1578           0 :   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
    1579           0 :     ntohl (mp->tcp_out_vrf_id);
    1580           0 :   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
    1581           0 :     ntohl (mp->udp_out_vrf_id);
    1582           0 :   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
    1583           0 :     ntohl (mp->tcp_in_vrf_id);
    1584           0 :   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
    1585           0 :     ntohl (mp->udp_in_vrf_id);
    1586             : 
    1587             : 
    1588           0 :   for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
    1589             :     {
    1590           0 :       if (vrf_id[i] != 0 && vrf_id[i] != ~0)
    1591             :         {
    1592           0 :           p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
    1593             : 
    1594           0 :           if (p == 0)
    1595             :             {
    1596           0 :               rv = VNET_API_ERROR_INVALID_VALUE;
    1597           0 :               goto reply;
    1598             :             }
    1599             : 
    1600           0 :           fib_index[i] = p[0];
    1601             :         }
    1602             :       else
    1603           0 :         fib_index[i] = ~0;
    1604             :     }
    1605           0 :   sw_if_index = ntohl (mp->sw_if_index);
    1606             : 
    1607           0 :   VALIDATE_SW_IF_INDEX (mp);
    1608             : 
    1609             :   rv =
    1610           0 :     set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
    1611           0 :                                         mp->is_add);
    1612             : 
    1613           0 :   BAD_SW_IF_INDEX_LABEL;
    1614           0 : reply:
    1615             : 
    1616           0 :   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
    1617             : }
    1618             : 
    1619             : static void
    1620           3 :   vl_api_sw_interface_ip6_set_link_local_address_t_handler
    1621             :   (vl_api_sw_interface_ip6_set_link_local_address_t * mp)
    1622             : {
    1623             :   vl_api_sw_interface_ip6_set_link_local_address_reply_t *rmp;
    1624             :   ip6_address_t ip;
    1625             :   int rv;
    1626             : 
    1627           3 :   VALIDATE_SW_IF_INDEX (mp);
    1628             : 
    1629           3 :   ip6_address_decode (mp->ip, &ip);
    1630             : 
    1631           3 :   rv = ip6_link_set_local_address (ntohl (mp->sw_if_index), &ip);
    1632             : 
    1633           3 :   BAD_SW_IF_INDEX_LABEL;
    1634           3 :   REPLY_MACRO (VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY);
    1635             : }
    1636             : 
    1637             : static void
    1638          24 : vl_api_sw_interface_ip6_get_link_local_address_t_handler (
    1639             :   vl_api_sw_interface_ip6_get_link_local_address_t *mp)
    1640             : {
    1641             :   vl_api_sw_interface_ip6_get_link_local_address_reply_t *rmp;
    1642          24 :   const ip6_address_t *ip = NULL;
    1643          24 :   int rv = 0;
    1644             : 
    1645          24 :   VALIDATE_SW_IF_INDEX (mp);
    1646             : 
    1647          24 :   ip = ip6_get_link_local_address (ntohl (mp->sw_if_index));
    1648          24 :   if (NULL == ip)
    1649           0 :     rv = VNET_API_ERROR_IP6_NOT_ENABLED;
    1650             : 
    1651          24 :   BAD_SW_IF_INDEX_LABEL;
    1652             :   /* clang-format off */
    1653          24 :   REPLY_MACRO2 (VL_API_SW_INTERFACE_IP6_GET_LINK_LOCAL_ADDRESS_REPLY,
    1654             :   ({
    1655             :     if (!rv)
    1656             :       ip6_address_encode (ip, rmp->ip);
    1657             :   }))
    1658             :   /* clang-format on */
    1659             : }
    1660             : 
    1661             : static void
    1662          24 : vl_api_ip_table_replace_begin_t_handler (vl_api_ip_table_replace_begin_t * mp)
    1663             : {
    1664             :   vl_api_ip_table_replace_begin_reply_t *rmp;
    1665             :   fib_protocol_t fproto;
    1666             :   u32 fib_index;
    1667          24 :   int rv = 0;
    1668             : 
    1669          24 :   fproto = (mp->table.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
    1670          24 :   fib_index = fib_table_find (fproto, ntohl (mp->table.table_id));
    1671             : 
    1672          24 :   if (INDEX_INVALID == fib_index)
    1673           0 :     rv = VNET_API_ERROR_NO_SUCH_FIB;
    1674             :   else
    1675             :     {
    1676          24 :       fib_table_mark (fib_index, fproto, FIB_SOURCE_API);
    1677          24 :       mfib_table_mark (mfib_table_find (fproto, ntohl (mp->table.table_id)),
    1678             :                        fproto, MFIB_SOURCE_API);
    1679             :     }
    1680          24 :   REPLY_MACRO (VL_API_IP_TABLE_REPLACE_BEGIN_REPLY);
    1681             : }
    1682             : 
    1683             : static void
    1684          24 : vl_api_ip_table_replace_end_t_handler (vl_api_ip_table_replace_end_t * mp)
    1685             : {
    1686             :   vl_api_ip_table_replace_end_reply_t *rmp;
    1687             :   fib_protocol_t fproto;
    1688             :   u32 fib_index;
    1689          24 :   int rv = 0;
    1690             : 
    1691          24 :   fproto = (mp->table.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
    1692          24 :   fib_index = fib_table_find (fproto, ntohl (mp->table.table_id));
    1693             : 
    1694          24 :   if (INDEX_INVALID == fib_index)
    1695           0 :     rv = VNET_API_ERROR_NO_SUCH_FIB;
    1696             :   else
    1697             :     {
    1698          24 :       fib_table_sweep (fib_index, fproto, FIB_SOURCE_API);
    1699          24 :       mfib_table_sweep (mfib_table_find
    1700             :                         (fproto, ntohl (mp->table.table_id)), fproto,
    1701             :                         MFIB_SOURCE_API);
    1702             :     }
    1703          24 :   REPLY_MACRO (VL_API_IP_TABLE_REPLACE_END_REPLY);
    1704             : }
    1705             : 
    1706             : static void
    1707          34 : vl_api_ip_table_flush_t_handler (vl_api_ip_table_flush_t * mp)
    1708             : {
    1709             :   vl_api_ip_table_flush_reply_t *rmp;
    1710             :   fib_protocol_t fproto;
    1711             :   u32 fib_index;
    1712          34 :   int rv = 0;
    1713             : 
    1714          34 :   fproto = (mp->table.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
    1715          34 :   fib_index = fib_table_find (fproto, ntohl (mp->table.table_id));
    1716             : 
    1717          34 :   if (INDEX_INVALID == fib_index)
    1718           0 :     rv = VNET_API_ERROR_NO_SUCH_FIB;
    1719             :   else
    1720             :     {
    1721          34 :       vnet_main_t *vnm = vnet_get_main ();
    1722          34 :       vnet_interface_main_t *im = &vnm->interface_main;
    1723             :       vnet_sw_interface_t *si;
    1724             : 
    1725             :       /* Shut down interfaces in this FIB / clean out intfc routes */
    1726             :       /* *INDENT-OFF* */
    1727         466 :       pool_foreach (si, im->sw_interfaces)
    1728             :        {
    1729         432 :         if (fib_index == fib_table_get_index_for_sw_if_index (fproto,
    1730             :                                                               si->sw_if_index))
    1731             :           {
    1732          72 :             u32 flags = si->flags;
    1733          72 :             flags &= ~VNET_SW_INTERFACE_FLAG_ADMIN_UP;
    1734          72 :             vnet_sw_interface_set_flags (vnm, si->sw_if_index, flags);
    1735             :           }
    1736             :       }
    1737             :       /* *INDENT-ON* */
    1738             : 
    1739          34 :       fib_table_flush (fib_index, fproto, FIB_SOURCE_API);
    1740          34 :       mfib_table_flush (mfib_table_find (fproto, ntohl (mp->table.table_id)),
    1741             :                         fproto, MFIB_SOURCE_API);
    1742             :     }
    1743             : 
    1744          34 :   REPLY_MACRO (VL_API_IP_TABLE_FLUSH_REPLY);
    1745             : }
    1746             : 
    1747             : void
    1748         123 : vl_api_ip_reassembly_set_t_handler (vl_api_ip_reassembly_set_t * mp)
    1749             : {
    1750             :   vl_api_ip_reassembly_set_reply_t *rmp;
    1751         123 :   int rv = 0;
    1752         123 :   switch ((vl_api_ip_reass_type_t) clib_net_to_host_u32 (mp->type))
    1753             :     {
    1754          95 :     case IP_REASS_TYPE_FULL:
    1755          95 :       if (mp->is_ip6)
    1756             :         {
    1757          51 :           rv = ip6_full_reass_set (clib_net_to_host_u32 (mp->timeout_ms),
    1758             :                                    clib_net_to_host_u32
    1759             :                                    (mp->max_reassemblies),
    1760             :                                    clib_net_to_host_u32
    1761             :                                    (mp->max_reassembly_length),
    1762             :                                    clib_net_to_host_u32
    1763             :                                    (mp->expire_walk_interval_ms));
    1764             :         }
    1765             :       else
    1766             :         {
    1767          44 :           rv = ip4_full_reass_set (clib_net_to_host_u32 (mp->timeout_ms),
    1768             :                                    clib_net_to_host_u32
    1769             :                                    (mp->max_reassemblies),
    1770             :                                    clib_net_to_host_u32
    1771             :                                    (mp->max_reassembly_length),
    1772             :                                    clib_net_to_host_u32
    1773             :                                    (mp->expire_walk_interval_ms));
    1774             :         }
    1775          95 :       break;
    1776          28 :     case IP_REASS_TYPE_SHALLOW_VIRTUAL:
    1777          28 :       if (mp->is_ip6)
    1778             :         {
    1779             :           rv =
    1780          16 :             ip6_sv_reass_set (clib_net_to_host_u32 (mp->timeout_ms),
    1781             :                               clib_net_to_host_u32 (mp->max_reassemblies),
    1782             :                               clib_net_to_host_u32
    1783             :                               (mp->max_reassembly_length),
    1784             :                               clib_net_to_host_u32
    1785             :                               (mp->expire_walk_interval_ms));
    1786             :         }
    1787             :       else
    1788             :         {
    1789          12 :           rv = ip4_sv_reass_set (clib_net_to_host_u32 (mp->timeout_ms),
    1790             :                                  clib_net_to_host_u32 (mp->max_reassemblies),
    1791             :                                  clib_net_to_host_u32
    1792             :                                  (mp->max_reassembly_length),
    1793             :                                  clib_net_to_host_u32
    1794             :                                  (mp->expire_walk_interval_ms));
    1795             :         }
    1796          28 :       break;
    1797             :     }
    1798             : 
    1799         123 :   REPLY_MACRO (VL_API_IP_REASSEMBLY_SET_REPLY);
    1800             : }
    1801             : 
    1802             : void
    1803           0 : vl_api_ip_reassembly_get_t_handler (vl_api_ip_reassembly_get_t * mp)
    1804             : {
    1805             :   vl_api_registration_t *rp;
    1806             : 
    1807           0 :   rp = vl_api_client_index_to_registration (mp->client_index);
    1808           0 :   if (rp == 0)
    1809           0 :     return;
    1810             : 
    1811           0 :   vl_api_ip_reassembly_get_reply_t *rmp = vl_msg_api_alloc (sizeof (*rmp));
    1812           0 :   clib_memset (rmp, 0, sizeof (*rmp));
    1813           0 :   rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IP_REASSEMBLY_GET_REPLY);
    1814           0 :   rmp->context = mp->context;
    1815           0 :   rmp->retval = 0;
    1816             :   u32 timeout_ms;
    1817             :   u32 max_reassemblies;
    1818             :   u32 max_reassembly_length;
    1819             :   u32 expire_walk_interval_ms;
    1820           0 :   switch ((vl_api_ip_reass_type_t) clib_net_to_host_u32 (mp->type))
    1821             :     {
    1822           0 :     case IP_REASS_TYPE_FULL:
    1823           0 :       if (mp->is_ip6)
    1824             :         {
    1825           0 :           rmp->is_ip6 = 1;
    1826           0 :           ip6_full_reass_get (&timeout_ms, &max_reassemblies,
    1827             :                               &max_reassembly_length,
    1828             :                               &expire_walk_interval_ms);
    1829             :         }
    1830             :       else
    1831             :         {
    1832           0 :           rmp->is_ip6 = 0;
    1833           0 :           ip4_full_reass_get (&timeout_ms, &max_reassemblies,
    1834             :                               &max_reassembly_length,
    1835             :                               &expire_walk_interval_ms);
    1836             :         }
    1837           0 :       break;
    1838           0 :     case IP_REASS_TYPE_SHALLOW_VIRTUAL:
    1839           0 :       if (mp->is_ip6)
    1840             :         {
    1841           0 :           rmp->is_ip6 = 1;
    1842           0 :           ip6_sv_reass_get (&timeout_ms, &max_reassemblies,
    1843             :                             &max_reassembly_length, &expire_walk_interval_ms);
    1844             :         }
    1845             :       else
    1846             :         {
    1847           0 :           rmp->is_ip6 = 0;
    1848           0 :           ip4_sv_reass_get (&timeout_ms, &max_reassemblies,
    1849             :                             &max_reassembly_length, &expire_walk_interval_ms);
    1850             :         }
    1851           0 :       break;
    1852             :     }
    1853           0 :   rmp->timeout_ms = clib_host_to_net_u32 (timeout_ms);
    1854           0 :   rmp->max_reassemblies = clib_host_to_net_u32 (max_reassemblies);
    1855           0 :   rmp->max_reassembly_length = clib_host_to_net_u32 (max_reassembly_length);
    1856           0 :   rmp->expire_walk_interval_ms =
    1857           0 :     clib_host_to_net_u32 (expire_walk_interval_ms);
    1858           0 :   vl_api_send_msg (rp, (u8 *) rmp);
    1859             : }
    1860             : 
    1861             : void
    1862         156 :   vl_api_ip_reassembly_enable_disable_t_handler
    1863             :   (vl_api_ip_reassembly_enable_disable_t * mp)
    1864             : {
    1865             :   vl_api_ip_reassembly_enable_disable_reply_t *rmp;
    1866         156 :   int rv = 0;
    1867         156 :   switch ((vl_api_ip_reass_type_t) clib_net_to_host_u32 (mp->type))
    1868             :     {
    1869         144 :     case IP_REASS_TYPE_FULL:
    1870             :       rv =
    1871         144 :         ip4_full_reass_enable_disable (clib_net_to_host_u32 (mp->sw_if_index),
    1872         144 :                                        mp->enable_ip4);
    1873         144 :       if (0 == rv)
    1874             :         rv =
    1875         144 :           ip6_full_reass_enable_disable (clib_net_to_host_u32
    1876         144 :                                          (mp->sw_if_index), mp->enable_ip6);
    1877         144 :       break;
    1878          12 :     case IP_REASS_TYPE_SHALLOW_VIRTUAL:
    1879             :       rv =
    1880          12 :         ip4_sv_reass_enable_disable (clib_net_to_host_u32 (mp->sw_if_index),
    1881          12 :                                      mp->enable_ip4);
    1882          12 :       if (0 == rv)
    1883             :         {
    1884             :           rv =
    1885          12 :             ip6_sv_reass_enable_disable (clib_net_to_host_u32
    1886          12 :                                          (mp->sw_if_index), mp->enable_ip6);
    1887             :         }
    1888          12 :       break;
    1889             :     }
    1890             : 
    1891         156 :   REPLY_MACRO (VL_API_IP_REASSEMBLY_ENABLE_DISABLE_REPLY);
    1892             : }
    1893             : 
    1894             : void
    1895           6 : vl_api_ip_local_reass_enable_disable_t_handler (
    1896             :   vl_api_ip_local_reass_enable_disable_t *mp)
    1897             : {
    1898             :   vl_api_ip_local_reass_enable_disable_reply_t *rmp;
    1899           6 :   int rv = 0;
    1900             : 
    1901           6 :   ip4_local_full_reass_enable_disable (mp->enable_ip4);
    1902           6 :   ip6_local_full_reass_enable_disable (mp->enable_ip6);
    1903             : 
    1904           6 :   REPLY_MACRO (VL_API_IP_LOCAL_REASS_ENABLE_DISABLE_REPLY);
    1905             : }
    1906             : 
    1907             : void
    1908           0 : vl_api_ip_local_reass_get_t_handler (vl_api_ip_local_reass_get_t *mp)
    1909             : {
    1910             :   vl_api_ip_local_reass_get_reply_t *rmp;
    1911           0 :   int rv = 0;
    1912           0 :   REPLY_MACRO2 (VL_API_IP_LOCAL_REASS_GET, {
    1913             :     rmp->ip4_is_enabled = ip4_local_full_reass_enabled ();
    1914             :     rmp->ip6_is_enabled = ip6_local_full_reass_enabled ();
    1915             :   });
    1916             : }
    1917             : 
    1918             : static walk_rc_t
    1919          35 : send_ip_punt_redirect_details (u32 rx_sw_if_index,
    1920             :                                const ip_punt_redirect_rx_t * ipr, void *arg)
    1921             : {
    1922             :   vl_api_ip_punt_redirect_details_t *mp;
    1923          35 :   fib_path_encode_ctx_t path_ctx = {
    1924             :     .rpaths = NULL,
    1925             :   };
    1926          35 :   ip_walk_ctx_t *ctx = arg;
    1927             : 
    1928          35 :   mp = vl_msg_api_alloc (sizeof (*mp));
    1929          35 :   if (!mp)
    1930           0 :     return (WALK_STOP);;
    1931             : 
    1932          35 :   clib_memset (mp, 0, sizeof (*mp));
    1933          35 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IP_PUNT_REDIRECT_DETAILS);
    1934          35 :   mp->context = ctx->context;
    1935             : 
    1936          35 :   fib_path_list_walk_w_ext (ipr->pl, NULL, fib_path_encode, &path_ctx);
    1937             : 
    1938          35 :   mp->punt.rx_sw_if_index = htonl (rx_sw_if_index);
    1939          35 :   mp->punt.tx_sw_if_index = htonl (path_ctx.rpaths[0].frp_sw_if_index);
    1940             : 
    1941          35 :   ip_address_encode (&path_ctx.rpaths[0].frp_addr,
    1942          35 :                      fib_proto_to_ip46 (ipr->fproto), &mp->punt.nh);
    1943             : 
    1944          35 :   vl_api_send_msg (ctx->reg, (u8 *) mp);
    1945             : 
    1946          35 :   vec_free (path_ctx.rpaths);
    1947             : 
    1948          35 :   return (WALK_CONTINUE);
    1949             : }
    1950             : 
    1951             : static walk_rc_t
    1952           0 : send_ip_punt_redirect_v2_details (u32 rx_sw_if_index,
    1953             :                                   const ip_punt_redirect_rx_t *ipr, void *arg)
    1954             : {
    1955             :   vl_api_ip_punt_redirect_v2_details_t *mp;
    1956           0 :   fib_path_encode_ctx_t path_ctx = {
    1957             :     .rpaths = NULL,
    1958             :   };
    1959             :   fib_route_path_t *rpath;
    1960           0 :   ip_walk_ctx_t *ctx = arg;
    1961             :   vl_api_fib_path_t *fp;
    1962             :   int n_paths;
    1963             : 
    1964           0 :   fib_path_list_walk_w_ext (ipr->pl, NULL, fib_path_encode, &path_ctx);
    1965             : 
    1966           0 :   n_paths = vec_len (path_ctx.rpaths);
    1967           0 :   mp = vl_msg_api_alloc (sizeof (*mp) + n_paths * sizeof (*fp));
    1968           0 :   if (!mp)
    1969           0 :     return (WALK_STOP);
    1970             : 
    1971           0 :   clib_memset (mp, 0, sizeof (*mp));
    1972           0 :   mp->_vl_msg_id =
    1973           0 :     ntohs (REPLY_MSG_ID_BASE + VL_API_IP_PUNT_REDIRECT_V2_DETAILS);
    1974           0 :   mp->context = ctx->context;
    1975           0 :   mp->punt.rx_sw_if_index = htonl (rx_sw_if_index);
    1976           0 :   mp->punt.n_paths = htonl (n_paths);
    1977           0 :   fp = mp->punt.paths;
    1978           0 :   vec_foreach (rpath, path_ctx.rpaths)
    1979             :     {
    1980           0 :       fib_api_path_encode (rpath, fp);
    1981           0 :       fp++;
    1982             :     }
    1983           0 :   mp->punt.af = (ipr->fproto == FIB_PROTOCOL_IP6) ? ADDRESS_IP6 : ADDRESS_IP4;
    1984             : 
    1985           0 :   vl_api_send_msg (ctx->reg, (u8 *) mp);
    1986             : 
    1987           0 :   vec_free (path_ctx.rpaths);
    1988             : 
    1989           0 :   return (WALK_CONTINUE);
    1990             : }
    1991             : 
    1992             : static void
    1993          56 : vl_api_ip_punt_redirect_dump_common (ip_walk_ctx_t *ctx, fib_protocol_t fproto,
    1994             :                                      u32 rx_sw_if_index,
    1995             :                                      ip_punt_redirect_walk_cb_t cb)
    1996             : {
    1997             : 
    1998          56 :   if ((u32) ~0 != rx_sw_if_index)
    1999             :     {
    2000             :       index_t pri;
    2001          50 :       pri = ip_punt_redirect_find (fproto, rx_sw_if_index);
    2002             : 
    2003          50 :       if (INDEX_INVALID == pri)
    2004          24 :         return;
    2005             : 
    2006          26 :       cb (rx_sw_if_index, ip_punt_redirect_get (pri), ctx);
    2007             :     }
    2008             :   else
    2009           6 :     ip_punt_redirect_walk (fproto, cb, ctx);
    2010             : }
    2011             : 
    2012             : static void
    2013          56 : vl_api_ip_punt_redirect_dump_t_handler (vl_api_ip_punt_redirect_dump_t * mp)
    2014             : {
    2015             :   vl_api_registration_t *reg;
    2016             :   fib_protocol_t fproto;
    2017             : 
    2018          56 :   reg = vl_api_client_index_to_registration (mp->client_index);
    2019          56 :   if (!reg)
    2020           0 :     return;
    2021             : 
    2022          56 :   fproto = (mp->is_ipv6 == 1) ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4;
    2023             : 
    2024          56 :   ip_walk_ctx_t ctx = {
    2025             :     .reg = reg,
    2026          56 :     .context = mp->context,
    2027             :   };
    2028             : 
    2029          56 :   vl_api_ip_punt_redirect_dump_common (&ctx, fproto, ntohl (mp->sw_if_index),
    2030             :                                        send_ip_punt_redirect_details);
    2031             : }
    2032             : 
    2033             : static void
    2034           0 : vl_api_ip_punt_redirect_v2_dump_t_handler (
    2035             :   vl_api_ip_punt_redirect_v2_dump_t *mp)
    2036             : {
    2037             :   vl_api_registration_t *reg;
    2038             :   ip_address_family_t af;
    2039             :   fib_protocol_t fproto;
    2040           0 :   int rv = 0;
    2041             : 
    2042           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
    2043           0 :   if (!reg)
    2044           0 :     return;
    2045             : 
    2046           0 :   rv = ip_address_family_decode (mp->af, &af);
    2047           0 :   if (rv != 0)
    2048           0 :     return;
    2049             : 
    2050           0 :   fproto = (af == AF_IP6) ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4;
    2051             : 
    2052           0 :   ip_walk_ctx_t ctx = {
    2053             :     .reg = reg,
    2054           0 :     .context = mp->context,
    2055             :   };
    2056             : 
    2057           0 :   vl_api_ip_punt_redirect_dump_common (&ctx, fproto, ntohl (mp->sw_if_index),
    2058             :                                        send_ip_punt_redirect_v2_details);
    2059             : }
    2060             : 
    2061             : void
    2062          46 : vl_api_ip_path_mtu_update_t_handler (vl_api_ip_path_mtu_update_t *mp)
    2063             : {
    2064             :   vl_api_ip_path_mtu_update_reply_t *rmp;
    2065             :   ip_address_t nh;
    2066          46 :   int rv = 0;
    2067             : 
    2068          46 :   ip_address_decode2 (&mp->pmtu.nh, &nh);
    2069             : 
    2070          46 :   rv = ip_path_mtu_update (&nh, ntohl (mp->pmtu.table_id),
    2071          46 :                            ntohs (mp->pmtu.path_mtu));
    2072             : 
    2073          46 :   REPLY_MACRO (VL_API_IP_PATH_MTU_UPDATE_REPLY);
    2074             : }
    2075             : 
    2076             : void
    2077           2 : vl_api_ip_path_mtu_replace_begin_t_handler (
    2078             :   vl_api_ip_path_mtu_replace_begin_t *mp)
    2079             : {
    2080             :   vl_api_ip_path_mtu_replace_begin_reply_t *rmp;
    2081             :   int rv;
    2082             : 
    2083           2 :   rv = ip_path_mtu_replace_begin ();
    2084             : 
    2085           2 :   REPLY_MACRO (VL_API_IP_PATH_MTU_REPLACE_BEGIN_REPLY);
    2086             : }
    2087             : 
    2088             : void
    2089           2 : vl_api_ip_path_mtu_replace_end_t_handler (vl_api_ip_path_mtu_replace_end_t *mp)
    2090             : {
    2091             :   vl_api_ip_path_mtu_replace_end_reply_t *rmp;
    2092             :   int rv;
    2093             : 
    2094           2 :   rv = ip_path_mtu_replace_end ();
    2095             : 
    2096           2 :   REPLY_MACRO (VL_API_IP_PATH_MTU_REPLACE_END_REPLY);
    2097             : }
    2098             : 
    2099             : static void
    2100         410 : send_ip_path_mtu_details (index_t ipti, vl_api_registration_t *rp, u32 context)
    2101             : {
    2102             :   vl_api_ip_path_mtu_details_t *rmp;
    2103             :   ip_address_t ip;
    2104             :   ip_pmtu_t *ipt;
    2105             : 
    2106         410 :   ipt = ip_path_mtu_get (ipti);
    2107             : 
    2108         410 :   REPLY_MACRO_DETAILS4 (VL_API_IP_PATH_MTU_DETAILS, rp, context, ({
    2109             :                           ip_pmtu_get_ip (ipt, &ip);
    2110             :                           ip_address_encode2 (&ip, &rmp->pmtu.nh);
    2111             :                           rmp->pmtu.table_id =
    2112             :                             htonl (ip_pmtu_get_table_id (ipt));
    2113             :                           rmp->pmtu.path_mtu = htons (ipt->ipt_cfg_pmtu);
    2114             :                         }));
    2115         410 : }
    2116             : 
    2117             : static void
    2118          50 : vl_api_ip_path_mtu_get_t_handler (vl_api_ip_path_mtu_get_t *mp)
    2119             : {
    2120             :   vl_api_ip_path_mtu_get_reply_t *rmp;
    2121          50 :   i32 rv = 0;
    2122             : 
    2123         460 :   REPLY_AND_DETAILS_MACRO (
    2124             :     VL_API_IP_PATH_MTU_GET_REPLY, ip_pmtu_pool,
    2125             :     ({ send_ip_path_mtu_details (cursor, rp, mp->context); }));
    2126             : }
    2127             : 
    2128             : #include <vnet/ip/ip.api.c>
    2129             : 
    2130             : static clib_error_t *
    2131         575 : ip_api_hookup (vlib_main_t * vm)
    2132             : {
    2133         575 :   api_main_t *am = vlibapi_get_main ();
    2134             : 
    2135             :   /*
    2136             :    * Set up the (msg_name, crc, message-id) table
    2137             :    */
    2138         575 :   REPLY_MSG_ID_BASE = setup_message_id_table ();
    2139             : 
    2140             :   /*
    2141             :    * Mark the route add/del API as MP safe
    2142             :    */
    2143         575 :   vl_api_set_msg_thread_safe (am, REPLY_MSG_ID_BASE + VL_API_IP_ROUTE_ADD_DEL,
    2144             :                               1);
    2145         575 :   vl_api_set_msg_thread_safe (
    2146         575 :     am, REPLY_MSG_ID_BASE + VL_API_IP_ROUTE_ADD_DEL_REPLY, 1);
    2147         575 :   vl_api_set_msg_thread_safe (
    2148         575 :     am, REPLY_MSG_ID_BASE + VL_API_IP_ROUTE_ADD_DEL_V2, 1);
    2149         575 :   vl_api_set_msg_thread_safe (
    2150         575 :     am, REPLY_MSG_ID_BASE + VL_API_IP_ROUTE_ADD_DEL_V2_REPLY, 1);
    2151             : 
    2152         575 :   return 0;
    2153             : }
    2154             : 
    2155        5183 : VLIB_API_INIT_FUNCTION (ip_api_hookup);
    2156             : 
    2157             : /*
    2158             :  * fd.io coding-style-patch-verification: ON
    2159             :  *
    2160             :  * Local Variables:
    2161             :  * eval: (c-set-style "gnu")
    2162             :  * End:
    2163             :  */

Generated by: LCOV version 1.14