2 *------------------------------------------------------------------
3 * ip_api.c - vnet ip api
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:
10 * http://www.apache.org/licenses/LICENSE-2.0
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 *------------------------------------------------------------------
22 #include <vnet/ip6-nd/ip6_nd.h>
23 #include <vnet/ip6-nd/ip6_ra.h>
25 #include <vnet/fib/fib_table.h>
26 #include <vnet/ip/ip_types_api.h>
28 #include <vpp/app/version.h>
30 #include <vlibapi/api.h>
31 #include <vlibmemory/api.h>
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>
39 * Base message ID fot the plugin
41 static u32 ip6_nd_base_msg_id;
42 #define REPLY_MSG_ID_BASE ip6_nd_base_msg_id
44 #include <vlibapi/api_helper_macros.h>
47 send_ip6nd_proxy_details (vl_api_registration_t * reg,
49 const ip46_address_t * addr, u32 sw_if_index)
51 vl_api_ip6nd_proxy_details_t *mp;
53 mp = vl_msg_api_alloc (sizeof (*mp));
54 clib_memset (mp, 0, sizeof (*mp));
55 mp->_vl_msg_id = ntohs (VL_API_IP6ND_PROXY_DETAILS);
56 mp->context = context;
57 mp->sw_if_index = htonl (sw_if_index);
59 ip6_address_encode (&addr->ip6, mp->ip);
61 vl_api_send_msg (reg, (u8 *) mp);
64 typedef struct api_ip6nd_proxy_fib_table_walk_ctx_t_
67 } api_ip6nd_proxy_fib_table_walk_ctx_t;
69 static fib_table_walk_rc_t
70 api_ip6nd_proxy_fib_table_walk (fib_node_index_t fei, void *arg)
72 api_ip6nd_proxy_fib_table_walk_ctx_t *ctx = arg;
74 if (fib_entry_is_sourced (fei, FIB_SOURCE_IP6_ND_PROXY))
76 vec_add1 (ctx->indices, fei);
79 return (FIB_TABLE_WALK_CONTINUE);
83 vl_api_ip6nd_proxy_dump_t_handler (vl_api_ip6nd_proxy_dump_t * mp)
85 ip6_main_t *im6 = &ip6_main;
86 fib_table_t *fib_table;
87 api_ip6nd_proxy_fib_table_walk_ctx_t ctx = {
90 fib_node_index_t *feip;
91 const fib_prefix_t *pfx;
92 vl_api_registration_t *reg;
94 reg = vl_api_client_index_to_registration (mp->client_index);
99 pool_foreach (fib_table, im6->fibs,
101 fib_table_walk(fib_table->ft_index,
103 api_ip6nd_proxy_fib_table_walk,
108 vec_sort_with_function (ctx.indices, fib_entry_cmp_for_sort);
110 vec_foreach (feip, ctx.indices)
112 pfx = fib_entry_get_prefix (*feip);
114 send_ip6nd_proxy_details (reg,
117 fib_entry_get_resolving_interface (*feip));
120 vec_free (ctx.indices);
124 vl_api_ip6nd_proxy_add_del_t_handler (vl_api_ip6nd_proxy_add_del_t * mp)
126 vl_api_ip6nd_proxy_add_del_reply_t *rmp;
130 VALIDATE_SW_IF_INDEX (mp);
132 ip6_address_decode (mp->ip, &ip6);
134 rv = ip6_nd_proxy_add (ntohl (mp->sw_if_index), &ip6);
136 rv = ip6_nd_proxy_del (ntohl (mp->sw_if_index), &ip6);
138 BAD_SW_IF_INDEX_LABEL;
139 REPLY_MACRO (VL_API_IP6ND_PROXY_ADD_DEL_REPLY);
143 vl_api_sw_interface_ip6nd_ra_config_t_handler
144 (vl_api_sw_interface_ip6nd_ra_config_t * mp)
146 vl_api_sw_interface_ip6nd_ra_config_reply_t *rmp;
147 vlib_main_t *vm = vlib_get_main ();
149 u8 is_no, suppress, managed, other, ll_option, send_unicast, cease,
152 is_no = mp->is_no == 1;
153 suppress = mp->suppress == 1;
154 managed = mp->managed == 1;
155 other = mp->other == 1;
156 ll_option = mp->ll_option == 1;
157 send_unicast = mp->send_unicast == 1;
158 cease = mp->cease == 1;
159 default_router = mp->default_router == 1;
161 VALIDATE_SW_IF_INDEX (mp);
163 rv = ip6_ra_config (vm, ntohl (mp->sw_if_index),
164 suppress, managed, other,
165 ll_option, send_unicast, cease,
166 default_router, ntohl (mp->lifetime),
167 ntohl (mp->initial_count),
168 ntohl (mp->initial_interval),
169 ntohl (mp->max_interval),
170 ntohl (mp->min_interval), is_no);
172 BAD_SW_IF_INDEX_LABEL;
174 REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_CONFIG_REPLY);
178 vl_api_sw_interface_ip6nd_ra_prefix_t_handler
179 (vl_api_sw_interface_ip6nd_ra_prefix_t * mp)
181 vlib_main_t *vm = vlib_get_main ();
182 vl_api_sw_interface_ip6nd_ra_prefix_reply_t *rmp;
185 u8 is_no, use_default, no_advertise, off_link, no_autoconfig, no_onlink;
187 VALIDATE_SW_IF_INDEX (mp);
189 ip_prefix_decode (&mp->prefix, &pfx);
190 is_no = mp->is_no == 1;
191 use_default = mp->use_default == 1;
192 no_advertise = mp->no_advertise == 1;
193 off_link = mp->off_link == 1;
194 no_autoconfig = mp->no_autoconfig == 1;
195 no_onlink = mp->no_onlink == 1;
197 rv = ip6_ra_prefix (vm, ntohl (mp->sw_if_index),
199 pfx.fp_len, use_default,
200 ntohl (mp->val_lifetime),
201 ntohl (mp->pref_lifetime), no_advertise,
202 off_link, no_autoconfig, no_onlink, is_no);
204 BAD_SW_IF_INDEX_LABEL;
205 REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
209 vl_api_ip6nd_send_router_solicitation_t_handler
210 (vl_api_ip6nd_send_router_solicitation_t * mp)
212 vl_api_ip6nd_send_router_solicitation_reply_t *rmp;
213 icmp6_send_router_solicitation_params_t params;
214 vlib_main_t *vm = vlib_get_main ();
217 VALIDATE_SW_IF_INDEX (mp);
219 BAD_SW_IF_INDEX_LABEL;
220 REPLY_MACRO (VL_API_IP6ND_SEND_ROUTER_SOLICITATION_REPLY);
225 params.irt = ntohl (mp->irt);
226 params.mrt = ntohl (mp->mrt);
227 params.mrc = ntohl (mp->mrc);
228 params.mrd = ntohl (mp->mrd);
230 icmp6_send_router_solicitation (vm, ntohl (mp->sw_if_index), mp->stop,
235 ip6_ra_handle_report (const ip6_ra_report_t * rap)
238 vpe_client_registration_t *rp;
240 pool_foreach(rp, vpe_api_main.ip6_ra_events_registrations,
242 vl_api_registration_t *vl_reg;
244 vl_reg = vl_api_client_index_to_registration (rp->client_index);
246 if (vl_reg && vl_api_can_send_msg (vl_reg))
248 vl_api_ip6_ra_prefix_info_t *prefix;
249 vl_api_ip6_ra_event_t *event;
251 u32 event_size = (sizeof (vl_api_ip6_ra_event_t) +
252 vec_len (rap->prefixes) *
253 sizeof (vl_api_ip6_ra_prefix_info_t));
254 event = vl_msg_api_alloc_zero (event_size);
256 event->_vl_msg_id = htons (VL_API_IP6_RA_EVENT + REPLY_MSG_ID_BASE);
257 event->client_index = rp->client_index;
258 event->pid = rp->client_pid;
259 event->sw_if_index = clib_host_to_net_u32 (rap->sw_if_index);
261 ip6_address_encode (&rap->router_address,
264 event->current_hop_limit = rap->current_hop_limit;
265 event->flags = rap->flags;
266 event->router_lifetime_in_sec =
267 clib_host_to_net_u16 (rap->router_lifetime_in_sec);
268 event->neighbor_reachable_time_in_msec =
269 clib_host_to_net_u32 (rap->neighbor_reachable_time_in_msec);
270 event->time_in_msec_between_retransmitted_neighbor_solicitations =
271 clib_host_to_net_u32 (rap->time_in_msec_between_retransmitted_neighbor_solicitations);
272 event->n_prefixes = clib_host_to_net_u32 (vec_len (rap->prefixes));
274 prefix = event->prefixes;
275 // (typeof (prefix)) event->prefixes;
277 for (j = 0; j < vec_len (rap->prefixes); j++)
279 ra_report_prefix_info_t *info = &rap->prefixes[j];
280 ip_prefix_encode(&info->prefix, &prefix->prefix);
281 prefix->flags = info->flags;
282 prefix->valid_time = clib_host_to_net_u32 (info->valid_time);
283 prefix->preferred_time =
284 clib_host_to_net_u32 (info->preferred_time);
288 vl_api_send_msg (vl_reg, (u8 *) event);
295 vl_api_want_ip6_ra_events_t_handler (vl_api_want_ip6_ra_events_t * mp)
297 vpe_api_main_t *am = &vpe_api_main;
298 vl_api_want_ip6_ra_events_reply_t *rmp;
299 int rv = 0, had_reg, have_reg;
301 had_reg = hash_elts (am->ip6_ra_events_registration_hash);
302 uword *p = hash_get (am->ip6_ra_events_registration_hash, mp->client_index);
303 vpe_client_registration_t *rp;
308 clib_warning ("pid %d: already enabled...", ntohl (mp->pid));
309 rv = VNET_API_ERROR_INVALID_REGISTRATION;
314 rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
315 pool_put (am->ip6_ra_events_registrations, rp);
316 hash_unset (am->ip6_ra_events_registration_hash, mp->client_index);
322 clib_warning ("pid %d: already disabled...", ntohl (mp->pid));
323 rv = VNET_API_ERROR_INVALID_REGISTRATION;
326 pool_get (am->ip6_ra_events_registrations, rp);
327 rp->client_index = mp->client_index;
328 rp->client_pid = ntohl (mp->pid);
329 hash_set (am->ip6_ra_events_registration_hash, rp->client_index,
330 rp - am->ip6_ra_events_registrations);
333 have_reg = hash_elts (am->ip6_ra_events_registration_hash);
335 if (!had_reg && have_reg)
336 ip6_ra_report_register (ip6_ra_handle_report);
337 else if (had_reg && !have_reg)
338 ip6_ra_report_unregister (ip6_ra_handle_report);
340 REPLY_MACRO (VL_API_WANT_IP6_RA_EVENTS_REPLY);
343 static clib_error_t *
344 want_ip6_ra_events_reaper (u32 client_index)
346 vpe_api_main_t *am = &vpe_api_main;
347 vpe_client_registration_t *rp;
350 p = hash_get (am->ip6_ra_events_registration_hash, client_index);
354 rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
355 pool_put (am->ip6_ra_events_registrations, rp);
356 hash_unset (am->ip6_ra_events_registration_hash, client_index);
361 VL_MSG_API_REAPER_FUNCTION (want_ip6_ra_events_reaper);
363 #include <vnet/ip6-nd/ip6_nd.api.c>
365 static clib_error_t *
366 ip6_nd_api_init (vlib_main_t * vm)
368 /* Ask for a correctly-sized block of API message decode slots */
369 ip6_nd_base_msg_id = setup_message_id_table ();
374 VLIB_INIT_FUNCTION (ip6_nd_api_init);
377 * fd.io coding-style-patch-verification: ON
380 * eval: (c-set-style "gnu")