LCOV - code coverage report
Current view: top level - vnet/ip6-nd - ip6_nd_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 195 248 78.6 %
Date: 2023-07-05 22:20:52 Functions: 16 19 84.2 %

          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 <stddef.h>
      21             : 
      22             : #include <vnet/ip6-nd/ip6_nd.h>
      23             : #include <vnet/ip6-nd/ip6_ra.h>
      24             : 
      25             : #include <vnet/fib/fib_table.h>
      26             : #include <vnet/ip/ip_types_api.h>
      27             : 
      28             : #include <vpp/app/version.h>
      29             : 
      30             : #include <vlibapi/api.h>
      31             : #include <vlibmemory/api.h>
      32             : 
      33             : /* define message IDs */
      34             : #include <vnet/format_fns.h>
      35             : #include <vnet/ip6-nd/ip6_nd.api_enum.h>
      36             : #include <vnet/ip6-nd/ip6_nd.api_types.h>
      37             : 
      38             : /**
      39             :  * Base message ID fot the plugin
      40             :  */
      41             : static u32 ip6_nd_base_msg_id;
      42             : #define REPLY_MSG_ID_BASE ip6_nd_base_msg_id
      43             : 
      44             : #include <vlibapi/api_helper_macros.h>
      45             : 
      46             : static void
      47           0 : send_ip6nd_proxy_details (vl_api_registration_t * reg,
      48             :                           u32 context,
      49             :                           const ip46_address_t * addr, u32 sw_if_index)
      50             : {
      51             :   vl_api_ip6nd_proxy_details_t *mp;
      52             : 
      53           0 :   mp = vl_msg_api_alloc (sizeof (*mp));
      54           0 :   clib_memset (mp, 0, sizeof (*mp));
      55           0 :   mp->_vl_msg_id = ntohs (VL_API_IP6ND_PROXY_DETAILS);
      56           0 :   mp->context = context;
      57           0 :   mp->sw_if_index = htonl (sw_if_index);
      58             : 
      59           0 :   ip6_address_encode (&addr->ip6, mp->ip);
      60             : 
      61           0 :   vl_api_send_msg (reg, (u8 *) mp);
      62           0 : }
      63             : 
      64             : typedef struct api_ip6nd_proxy_fib_table_walk_ctx_t_
      65             : {
      66             :   u32 *indices;
      67             : } api_ip6nd_proxy_fib_table_walk_ctx_t;
      68             : 
      69             : static fib_table_walk_rc_t
      70           0 : api_ip6nd_proxy_fib_table_walk (fib_node_index_t fei, void *arg)
      71             : {
      72           0 :   api_ip6nd_proxy_fib_table_walk_ctx_t *ctx = arg;
      73             : 
      74           0 :   if (fib_entry_is_sourced (fei, FIB_SOURCE_IP6_ND_PROXY))
      75             :     {
      76           0 :       vec_add1 (ctx->indices, fei);
      77             :     }
      78             : 
      79           0 :   return (FIB_TABLE_WALK_CONTINUE);
      80             : }
      81             : 
      82             : static void
      83           0 : vl_api_ip6nd_proxy_dump_t_handler (vl_api_ip6nd_proxy_dump_t * mp)
      84             : {
      85           0 :   ip6_main_t *im6 = &ip6_main;
      86             :   u32 fib_index;
      87           0 :   api_ip6nd_proxy_fib_table_walk_ctx_t ctx = {
      88             :     .indices = NULL,
      89             :   };
      90             :   fib_node_index_t *feip;
      91             :   const fib_prefix_t *pfx;
      92             :   vl_api_registration_t *reg;
      93             : 
      94           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
      95           0 :   if (!reg)
      96           0 :     return;
      97             : 
      98             :   /* *INDENT-OFF* */
      99           0 :   pool_foreach_index (fib_index, im6->fibs)
     100             :     {
     101           0 :       fib_table_walk (fib_index, FIB_PROTOCOL_IP6,
     102             :                       api_ip6nd_proxy_fib_table_walk, &ctx);
     103             :     }
     104             :   /* *INDENT-ON* */
     105             : 
     106           0 :   vec_sort_with_function (ctx.indices, fib_entry_cmp_for_sort);
     107             : 
     108           0 :   vec_foreach (feip, ctx.indices)
     109             :   {
     110           0 :     pfx = fib_entry_get_prefix (*feip);
     111             : 
     112           0 :     send_ip6nd_proxy_details (reg,
     113             :                               mp->context,
     114             :                               &pfx->fp_addr,
     115             :                               fib_entry_get_resolving_interface (*feip));
     116             :   }
     117             : 
     118           0 :   vec_free (ctx.indices);
     119             : }
     120             : 
     121             : static void
     122           2 : vl_api_ip6nd_proxy_enable_disable_t_handler (
     123             :   vl_api_ip6nd_proxy_enable_disable_t *mp)
     124             : {
     125             :   vl_api_ip6nd_proxy_enable_disable_reply_t *rmp;
     126           2 :   int rv = 0;
     127             : 
     128           2 :   VALIDATE_SW_IF_INDEX (mp);
     129             : 
     130           2 :   if (mp->is_enable)
     131           1 :     rv = ip6_nd_proxy_enable_disable (ntohl (mp->sw_if_index), 1);
     132             :   else
     133           1 :     rv = ip6_nd_proxy_enable_disable (ntohl (mp->sw_if_index), 0);
     134             : 
     135           2 :   BAD_SW_IF_INDEX_LABEL;
     136           2 :   REPLY_MACRO (VL_API_IP6ND_PROXY_ENABLE_DISABLE_REPLY);
     137             : }
     138             : 
     139             : static void
     140           4 : vl_api_ip6nd_proxy_add_del_t_handler (vl_api_ip6nd_proxy_add_del_t * mp)
     141             : {
     142             :   vl_api_ip6nd_proxy_add_del_reply_t *rmp;
     143             :   ip6_address_t ip6;
     144           4 :   int rv = 0;
     145             : 
     146           4 :   VALIDATE_SW_IF_INDEX (mp);
     147             : 
     148           4 :   ip6_address_decode (mp->ip, &ip6);
     149           4 :   if (mp->is_add)
     150           2 :     rv = ip6_nd_proxy_add (ntohl (mp->sw_if_index), &ip6);
     151             :   else
     152           2 :     rv = ip6_nd_proxy_del (ntohl (mp->sw_if_index), &ip6);
     153             : 
     154           4 :   BAD_SW_IF_INDEX_LABEL;
     155           4 :   REPLY_MACRO (VL_API_IP6ND_PROXY_ADD_DEL_REPLY);
     156             : }
     157             : 
     158             : static void
     159         185 :   vl_api_sw_interface_ip6nd_ra_config_t_handler
     160             :   (vl_api_sw_interface_ip6nd_ra_config_t * mp)
     161             : {
     162             :   vl_api_sw_interface_ip6nd_ra_config_reply_t *rmp;
     163         185 :   vlib_main_t *vm = vlib_get_main ();
     164         185 :   int rv = 0;
     165             :   u8 is_no, suppress, managed, other, ll_option, send_unicast, cease,
     166             :     default_router;
     167             : 
     168         185 :   is_no = mp->is_no == 1;
     169         185 :   suppress = mp->suppress == 1;
     170         185 :   managed = mp->managed == 1;
     171         185 :   other = mp->other == 1;
     172         185 :   ll_option = mp->ll_option == 1;
     173         185 :   send_unicast = mp->send_unicast == 1;
     174         185 :   cease = mp->cease == 1;
     175         185 :   default_router = mp->default_router == 1;
     176             : 
     177         185 :   VALIDATE_SW_IF_INDEX (mp);
     178             : 
     179         185 :   rv = ip6_ra_config (vm, ntohl (mp->sw_if_index),
     180             :                       suppress, managed, other,
     181             :                       ll_option, send_unicast, cease,
     182             :                       default_router, ntohl (mp->lifetime),
     183             :                       ntohl (mp->initial_count),
     184             :                       ntohl (mp->initial_interval),
     185             :                       ntohl (mp->max_interval),
     186             :                       ntohl (mp->min_interval), is_no);
     187             : 
     188         185 :   BAD_SW_IF_INDEX_LABEL;
     189             : 
     190         185 :   REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_CONFIG_REPLY);
     191             : }
     192             : 
     193             : static void
     194          13 :   vl_api_sw_interface_ip6nd_ra_prefix_t_handler
     195             :   (vl_api_sw_interface_ip6nd_ra_prefix_t * mp)
     196             : {
     197          13 :   vlib_main_t *vm = vlib_get_main ();
     198             :   vl_api_sw_interface_ip6nd_ra_prefix_reply_t *rmp;
     199             :   fib_prefix_t pfx;
     200          13 :   int rv = 0;
     201             :   u8 is_no, use_default, no_advertise, off_link, no_autoconfig, no_onlink;
     202             : 
     203          13 :   VALIDATE_SW_IF_INDEX (mp);
     204             : 
     205          13 :   ip_prefix_decode (&mp->prefix, &pfx);
     206          13 :   is_no = mp->is_no == 1;
     207          13 :   use_default = mp->use_default == 1;
     208          13 :   no_advertise = mp->no_advertise == 1;
     209          13 :   off_link = mp->off_link == 1;
     210          13 :   no_autoconfig = mp->no_autoconfig == 1;
     211          13 :   no_onlink = mp->no_onlink == 1;
     212             : 
     213          13 :   rv = ip6_ra_prefix (vm, ntohl (mp->sw_if_index),
     214             :                       &pfx.fp_addr.ip6,
     215          13 :                       pfx.fp_len, use_default,
     216             :                       ntohl (mp->val_lifetime),
     217             :                       ntohl (mp->pref_lifetime), no_advertise,
     218             :                       off_link, no_autoconfig, no_onlink, is_no);
     219             : 
     220          13 :   BAD_SW_IF_INDEX_LABEL;
     221          13 :   REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
     222             : }
     223             : 
     224             : static void
     225           2 : ip6_radv_prefix_encode (f64 now, const ip6_radv_prefix_t *in,
     226             :                         vl_api_ip6nd_ra_prefix_t *out)
     227             : {
     228           2 :   fib_prefix_t in_ip6_pfx = {
     229             :     .fp_addr = {
     230             :       .ip6 = in->prefix,
     231             :     },
     232           2 :     .fp_len = in->prefix_len,
     233             :     .fp_proto = FIB_PROTOCOL_IP6,
     234             :   };
     235             : 
     236           2 :   ip_prefix_encode (&in_ip6_pfx, &out->prefix);
     237             : 
     238           2 :   out->onlink_flag = in->adv_on_link_flag;
     239           2 :   out->autonomous_flag = in->adv_autonomous_flag;
     240           2 :   out->val_lifetime = htonl (in->adv_valid_lifetime_in_secs);
     241           2 :   out->pref_lifetime = htonl (in->adv_pref_lifetime_in_secs);
     242             : 
     243           2 :   if (in->adv_valid_lifetime_in_secs != ~0)
     244             :     {
     245           0 :       out->valid_lifetime_expires =
     246           0 :         clib_host_to_net_f64 (in->valid_lifetime_expires - now);
     247             :     }
     248             : 
     249           2 :   if (in->adv_pref_lifetime_in_secs != ~0)
     250             :     {
     251           0 :       out->pref_lifetime_expires =
     252           0 :         clib_host_to_net_f64 (in->pref_lifetime_expires - now);
     253             :     }
     254             : 
     255           2 :   out->decrement_lifetime_flag = in->decrement_lifetime_flag;
     256           2 :   out->no_advertise = (in->enabled == 0);
     257           2 : }
     258             : 
     259             : static void
     260           7 : send_sw_interface_ip6nd_ra_details (vl_api_registration_t *reg, u32 context,
     261             :                                     ip6_ra_t *radv_info)
     262             : {
     263           7 :   vl_api_sw_interface_ip6nd_ra_details_t *rmp = 0;
     264             :   vl_api_ip6nd_ra_prefix_t *api_radv_pfx;
     265           7 :   u32 n_prefixes = pool_elts (radv_info->adv_prefixes_pool);
     266             :   ip6_radv_prefix_t *radv_pfx;
     267           7 :   u32 msg_size = sizeof (*rmp) + n_prefixes * sizeof (*api_radv_pfx);
     268           7 :   vlib_main_t *vm = vlib_get_main ();
     269           7 :   f64 now = vlib_time_now (vm);
     270             : 
     271           7 :   rmp = vl_msg_api_alloc (msg_size);
     272           7 :   if (!rmp)
     273           0 :     return;
     274           7 :   clib_memset (rmp, 0, msg_size);
     275           7 :   rmp->_vl_msg_id =
     276           7 :     ntohs (VL_API_SW_INTERFACE_IP6ND_RA_DETAILS + REPLY_MSG_ID_BASE);
     277           7 :   rmp->context = context;
     278             : 
     279           7 :   rmp->sw_if_index = htonl (radv_info->sw_if_index);
     280           7 :   rmp->cur_hop_limit = radv_info->curr_hop_limit;
     281           7 :   rmp->adv_managed_flag = radv_info->adv_managed_flag;
     282           7 :   rmp->adv_other_flag = radv_info->adv_other_flag;
     283           7 :   rmp->adv_router_lifetime = htons (radv_info->adv_router_lifetime_in_sec);
     284           7 :   rmp->adv_neighbor_reachable_time =
     285           7 :     htonl (radv_info->adv_neighbor_reachable_time_in_msec);
     286           7 :   rmp->adv_retransmit_interval = htonl (
     287             :     radv_info->adv_time_in_msec_between_retransmitted_neighbor_solicitations);
     288           7 :   rmp->adv_link_mtu = htonl (radv_info->adv_link_mtu);
     289           7 :   rmp->send_radv = radv_info->send_radv;
     290           7 :   rmp->cease_radv = radv_info->cease_radv;
     291           7 :   rmp->send_unicast = radv_info->send_unicast;
     292           7 :   rmp->adv_link_layer_address = radv_info->adv_link_layer_address;
     293           7 :   rmp->max_radv_interval = clib_host_to_net_f64 (radv_info->max_radv_interval);
     294           7 :   rmp->min_radv_interval = clib_host_to_net_f64 (radv_info->min_radv_interval);
     295             : 
     296           7 :   if (radv_info->last_radv_time > 0.0)
     297             :     {
     298           0 :       rmp->last_radv_time =
     299           0 :         clib_host_to_net_f64 (now - radv_info->last_radv_time);
     300             :     }
     301             : 
     302           7 :   if ((radv_info->next_multicast_time - radv_info->last_multicast_time) > 0.0)
     303             :     {
     304           1 :       rmp->last_multicast_time =
     305           1 :         clib_host_to_net_f64 (now - radv_info->last_multicast_time);
     306           1 :       rmp->next_multicast_time =
     307           1 :         clib_host_to_net_f64 (radv_info->next_multicast_time - now);
     308             :     }
     309             : 
     310           7 :   rmp->initial_adverts_count = htonl (radv_info->initial_adverts_count);
     311           7 :   rmp->initial_adverts_interval =
     312           7 :     clib_host_to_net_f64 (radv_info->initial_adverts_interval);
     313           7 :   rmp->initial_adverts_sent = (radv_info->initial_adverts_sent == 0);
     314           7 :   rmp->n_advertisements_sent = htonl (radv_info->n_advertisements_sent);
     315           7 :   rmp->n_solicitations_rcvd = htonl (radv_info->n_solicitations_rcvd);
     316           7 :   rmp->n_solicitations_dropped = htonl (radv_info->n_solicitations_dropped);
     317           7 :   rmp->n_prefixes = htonl (n_prefixes);
     318             : 
     319           7 :   api_radv_pfx = rmp->prefixes;
     320           9 :   pool_foreach (radv_pfx, radv_info->adv_prefixes_pool)
     321             :     {
     322           2 :       ip6_radv_prefix_encode (now, radv_pfx, api_radv_pfx);
     323             : 
     324           2 :       api_radv_pfx++;
     325             :     }
     326             : 
     327           7 :   vl_api_send_msg (reg, (u8 *) rmp);
     328             : }
     329             : 
     330             : typedef struct
     331             : {
     332             :   u32 *sw_if_indices;
     333             : } api_dump_ip6_ra_itf_walk_ctx_t;
     334             : 
     335             : static walk_rc_t
     336           5 : api_dump_ip6_ra_itf_walk_fn (u32 sw_if_index, void *arg)
     337             : {
     338           5 :   api_dump_ip6_ra_itf_walk_ctx_t *ctx = arg;
     339             : 
     340           5 :   vec_add1 (ctx->sw_if_indices, sw_if_index);
     341             : 
     342           5 :   return (WALK_CONTINUE);
     343             : }
     344             : 
     345             : static void
     346           3 : vl_api_sw_interface_ip6nd_ra_dump_t_handler (
     347             :   vl_api_sw_interface_ip6nd_ra_dump_t *mp)
     348             : {
     349             :   vl_api_registration_t *reg;
     350             :   u32 sw_if_index;
     351             :   ip6_ra_t *radv_info;
     352             : 
     353           3 :   reg = vl_api_client_index_to_registration (mp->client_index);
     354           3 :   if (!reg)
     355           0 :     return;
     356             : 
     357           3 :   sw_if_index = ntohl (mp->sw_if_index);
     358             : 
     359           3 :   if (sw_if_index == INDEX_INVALID)
     360             :     {
     361             :       /* dump all interfaces */
     362             : 
     363           1 :       api_dump_ip6_ra_itf_walk_ctx_t ctx = {
     364             :         .sw_if_indices = NULL,
     365             :       };
     366             :       u32 *sw_if_i;
     367             : 
     368           1 :       ip6_ra_itf_walk (api_dump_ip6_ra_itf_walk_fn, &ctx);
     369             : 
     370           6 :       vec_foreach (sw_if_i, ctx.sw_if_indices)
     371             :         {
     372           5 :           radv_info = ip6_ra_get_itf (*sw_if_i);
     373           5 :           if (radv_info != NULL)
     374             :             {
     375           5 :               send_sw_interface_ip6nd_ra_details (reg, mp->context, radv_info);
     376             :             }
     377             :         }
     378             : 
     379           1 :       vec_free (ctx.sw_if_indices);
     380             :     }
     381             :   else
     382             :     {
     383             :       /* dump a single interface */
     384             : 
     385           2 :       radv_info = ip6_ra_get_itf (sw_if_index);
     386           2 :       if (radv_info != NULL)
     387             :         {
     388           2 :           send_sw_interface_ip6nd_ra_details (reg, mp->context, radv_info);
     389             :         }
     390             :     }
     391             : }
     392             : 
     393             : static void
     394           1 :   vl_api_ip6nd_send_router_solicitation_t_handler
     395             :   (vl_api_ip6nd_send_router_solicitation_t * mp)
     396             : {
     397             :   vl_api_ip6nd_send_router_solicitation_reply_t *rmp;
     398             :   icmp6_send_router_solicitation_params_t params;
     399           1 :   vlib_main_t *vm = vlib_get_main ();
     400           1 :   int rv = 0;
     401             : 
     402           1 :   VALIDATE_SW_IF_INDEX (mp);
     403             : 
     404           1 :   BAD_SW_IF_INDEX_LABEL;
     405           1 :   REPLY_MACRO (VL_API_IP6ND_SEND_ROUTER_SOLICITATION_REPLY);
     406             : 
     407           1 :   if (rv != 0)
     408           0 :     return;
     409             : 
     410           1 :   params.irt = ntohl (mp->irt);
     411           1 :   params.mrt = ntohl (mp->mrt);
     412           1 :   params.mrc = ntohl (mp->mrc);
     413           1 :   params.mrd = ntohl (mp->mrd);
     414             : 
     415           1 :   icmp6_send_router_solicitation (vm, ntohl (mp->sw_if_index), mp->stop,
     416             :                                   &params);
     417             : }
     418             : 
     419             : static void
     420           1 : ip6_ra_handle_report (const ip6_ra_report_t * rap)
     421             : {
     422             :   /* *INDENT-OFF* */
     423             :   vpe_client_registration_t *rp;
     424             : 
     425           2 :   pool_foreach (rp, vpe_api_main.ip6_ra_events_registrations)
     426             :    {
     427             :     vl_api_registration_t *vl_reg;
     428             : 
     429           1 :     vl_reg = vl_api_client_index_to_registration (rp->client_index);
     430             : 
     431           1 :     if (vl_reg && vl_api_can_send_msg (vl_reg))
     432             :       {
     433             :         vl_api_ip6_ra_prefix_info_t *prefix;
     434             :         vl_api_ip6_ra_event_t *event;
     435             : 
     436           0 :         u32 event_size = (sizeof (vl_api_ip6_ra_event_t) +
     437           1 :                           vec_len (rap->prefixes) *
     438             :                           sizeof (vl_api_ip6_ra_prefix_info_t));
     439           1 :         event = vl_msg_api_alloc_zero (event_size);
     440             : 
     441           1 :         event->_vl_msg_id = htons (VL_API_IP6_RA_EVENT + REPLY_MSG_ID_BASE);
     442           1 :         event->client_index = rp->client_index;
     443           1 :         event->pid = rp->client_pid;
     444           1 :         event->sw_if_index = clib_host_to_net_u32 (rap->sw_if_index);
     445             : 
     446           1 :         ip6_address_encode (&rap->router_address,
     447           1 :                             event->router_addr);
     448             : 
     449           1 :         event->current_hop_limit = rap->current_hop_limit;
     450           1 :         event->flags = rap->flags;
     451           1 :         event->router_lifetime_in_sec =
     452           1 :           clib_host_to_net_u16 (rap->router_lifetime_in_sec);
     453           1 :         event->neighbor_reachable_time_in_msec =
     454           1 :           clib_host_to_net_u32 (rap->neighbor_reachable_time_in_msec);
     455           1 :         event->time_in_msec_between_retransmitted_neighbor_solicitations =
     456           1 :           clib_host_to_net_u32 (rap->time_in_msec_between_retransmitted_neighbor_solicitations);
     457           1 :         event->n_prefixes = clib_host_to_net_u32 (vec_len (rap->prefixes));
     458             : 
     459           1 :         prefix = event->prefixes;
     460             :           // (typeof (prefix)) event->prefixes;
     461             :         u32 j;
     462           3 :         for (j = 0; j < vec_len (rap->prefixes); j++)
     463             :           {
     464           2 :             ra_report_prefix_info_t *info = &rap->prefixes[j];
     465           2 :             ip_prefix_encode(&info->prefix, &prefix->prefix);
     466           2 :             prefix->flags = info->flags;
     467           2 :             prefix->valid_time = clib_host_to_net_u32 (info->valid_time);
     468           2 :             prefix->preferred_time =
     469           2 :               clib_host_to_net_u32 (info->preferred_time);
     470           2 :             prefix++;
     471             :           }
     472             : 
     473           1 :         vl_api_send_msg (vl_reg, (u8 *) event);
     474             :       }
     475             :   }
     476             :   /* *INDENT-ON* */
     477           1 : }
     478             : 
     479             : static void
     480           1 : vl_api_want_ip6_ra_events_t_handler (vl_api_want_ip6_ra_events_t * mp)
     481             : {
     482           1 :   vpe_api_main_t *am = &vpe_api_main;
     483             :   vl_api_want_ip6_ra_events_reply_t *rmp;
     484           1 :   int rv = 0, had_reg, have_reg;
     485             : 
     486           1 :   had_reg = hash_elts (am->ip6_ra_events_registration_hash);
     487           1 :   uword *p = hash_get (am->ip6_ra_events_registration_hash, mp->client_index);
     488             :   vpe_client_registration_t *rp;
     489           1 :   if (p)
     490             :     {
     491           0 :       if (mp->enable)
     492             :         {
     493           0 :           clib_warning ("pid %d: already enabled...", ntohl (mp->pid));
     494           0 :           rv = VNET_API_ERROR_INVALID_REGISTRATION;
     495           0 :           goto reply;
     496             :         }
     497             :       else
     498             :         {
     499           0 :           rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
     500           0 :           pool_put (am->ip6_ra_events_registrations, rp);
     501           0 :           hash_unset (am->ip6_ra_events_registration_hash, mp->client_index);
     502           0 :           goto reply;
     503             :         }
     504             :     }
     505           1 :   if (mp->enable == 0)
     506             :     {
     507           0 :       clib_warning ("pid %d: already disabled...", ntohl (mp->pid));
     508           0 :       rv = VNET_API_ERROR_INVALID_REGISTRATION;
     509           0 :       goto reply;
     510             :     }
     511           1 :   pool_get (am->ip6_ra_events_registrations, rp);
     512           1 :   rp->client_index = mp->client_index;
     513           1 :   rp->client_pid = ntohl (mp->pid);
     514           1 :   hash_set (am->ip6_ra_events_registration_hash, rp->client_index,
     515             :             rp - am->ip6_ra_events_registrations);
     516             : 
     517           1 : reply:
     518           1 :   have_reg = hash_elts (am->ip6_ra_events_registration_hash);
     519             : 
     520           1 :   if (!had_reg && have_reg)
     521           1 :     ip6_ra_report_register (ip6_ra_handle_report);
     522           0 :   else if (had_reg && !have_reg)
     523           0 :     ip6_ra_report_unregister (ip6_ra_handle_report);
     524             : 
     525           1 :   REPLY_MACRO (VL_API_WANT_IP6_RA_EVENTS_REPLY);
     526             : }
     527             : 
     528             : static clib_error_t *
     529        1207 : want_ip6_ra_events_reaper (u32 client_index)
     530             : {
     531        1207 :   vpe_api_main_t *am = &vpe_api_main;
     532             :   vpe_client_registration_t *rp;
     533             :   uword *p;
     534             : 
     535        1207 :   p = hash_get (am->ip6_ra_events_registration_hash, client_index);
     536             : 
     537        1207 :   if (p)
     538             :     {
     539           0 :       rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
     540           0 :       pool_put (am->ip6_ra_events_registrations, rp);
     541           0 :       hash_unset (am->ip6_ra_events_registration_hash, client_index);
     542             :     }
     543        1207 :   return (NULL);
     544             : }
     545             : 
     546         559 : VL_MSG_API_REAPER_FUNCTION (want_ip6_ra_events_reaper);
     547             : 
     548             : #include <vnet/ip6-nd/ip6_nd.api.c>
     549             : 
     550             : static clib_error_t *
     551         559 : ip6_nd_api_init (vlib_main_t * vm)
     552             : {
     553             :   /* Ask for a correctly-sized block of API message decode slots */
     554         559 :   ip6_nd_base_msg_id = setup_message_id_table ();
     555             : 
     556         559 :   return 0;
     557             : }
     558             : 
     559       95759 : VLIB_INIT_FUNCTION (ip6_nd_api_init);
     560             : 
     561             : /*
     562             :  * fd.io coding-style-patch-verification: ON
     563             :  *
     564             :  * Local Variables:
     565             :  * eval: (c-set-style "gnu")
     566             :  * End:
     567             :  */

Generated by: LCOV version 1.14