blob: 6520a61f691a8f2339818f440d67b96fa53e8577 [file] [log] [blame]
Neale Rannscbe25aa2019-09-30 10:53:31 +00001/*
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 */
41static 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
46static void
47send_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 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);
58
59 ip6_address_encode (&addr->ip6, mp->ip);
60
61 vl_api_send_msg (reg, (u8 *) mp);
62}
63
64typedef struct api_ip6nd_proxy_fib_table_walk_ctx_t_
65{
66 u32 *indices;
67} api_ip6nd_proxy_fib_table_walk_ctx_t;
68
69static fib_table_walk_rc_t
70api_ip6nd_proxy_fib_table_walk (fib_node_index_t fei, void *arg)
71{
72 api_ip6nd_proxy_fib_table_walk_ctx_t *ctx = arg;
73
74 if (fib_entry_is_sourced (fei, FIB_SOURCE_IP6_ND_PROXY))
75 {
76 vec_add1 (ctx->indices, fei);
77 }
78
79 return (FIB_TABLE_WALK_CONTINUE);
80}
81
82static void
83vl_api_ip6nd_proxy_dump_t_handler (vl_api_ip6nd_proxy_dump_t * mp)
84{
85 ip6_main_t *im6 = &ip6_main;
Neale Rannsd6953332021-08-10 07:39:18 +000086 u32 fib_index;
Neale Rannscbe25aa2019-09-30 10:53:31 +000087 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 reg = vl_api_client_index_to_registration (mp->client_index);
95 if (!reg)
96 return;
97
98 /* *INDENT-OFF* */
Neale Rannsd6953332021-08-10 07:39:18 +000099 pool_foreach_index (fib_index, im6->fibs)
100 {
101 fib_table_walk (fib_index, FIB_PROTOCOL_IP6,
102 api_ip6nd_proxy_fib_table_walk, &ctx);
103 }
Neale Rannscbe25aa2019-09-30 10:53:31 +0000104 /* *INDENT-ON* */
105
106 vec_sort_with_function (ctx.indices, fib_entry_cmp_for_sort);
107
108 vec_foreach (feip, ctx.indices)
109 {
110 pfx = fib_entry_get_prefix (*feip);
111
112 send_ip6nd_proxy_details (reg,
113 mp->context,
114 &pfx->fp_addr,
115 fib_entry_get_resolving_interface (*feip));
116 }
117
118 vec_free (ctx.indices);
119}
120
121static void
Mohsin Kazmicebb4772021-04-07 19:50:35 +0200122vl_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 int rv = 0;
127
128 VALIDATE_SW_IF_INDEX (mp);
129
130 if (mp->is_enable)
131 rv = ip6_nd_proxy_enable_disable (ntohl (mp->sw_if_index), 1);
132 else
133 rv = ip6_nd_proxy_enable_disable (ntohl (mp->sw_if_index), 0);
134
135 BAD_SW_IF_INDEX_LABEL;
136 REPLY_MACRO (VL_API_IP6ND_PROXY_ENABLE_DISABLE_REPLY);
137}
138
139static void
Neale Rannscbe25aa2019-09-30 10:53:31 +0000140vl_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 int rv = 0;
145
146 VALIDATE_SW_IF_INDEX (mp);
147
148 ip6_address_decode (mp->ip, &ip6);
149 if (mp->is_add)
150 rv = ip6_nd_proxy_add (ntohl (mp->sw_if_index), &ip6);
151 else
152 rv = ip6_nd_proxy_del (ntohl (mp->sw_if_index), &ip6);
153
154 BAD_SW_IF_INDEX_LABEL;
155 REPLY_MACRO (VL_API_IP6ND_PROXY_ADD_DEL_REPLY);
156}
157
158static void
159 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 vlib_main_t *vm = vlib_get_main ();
164 int rv = 0;
165 u8 is_no, suppress, managed, other, ll_option, send_unicast, cease,
166 default_router;
167
168 is_no = mp->is_no == 1;
169 suppress = mp->suppress == 1;
170 managed = mp->managed == 1;
171 other = mp->other == 1;
172 ll_option = mp->ll_option == 1;
173 send_unicast = mp->send_unicast == 1;
174 cease = mp->cease == 1;
175 default_router = mp->default_router == 1;
176
177 VALIDATE_SW_IF_INDEX (mp);
178
179 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 BAD_SW_IF_INDEX_LABEL;
189
190 REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_CONFIG_REPLY);
191}
192
193static void
194 vl_api_sw_interface_ip6nd_ra_prefix_t_handler
195 (vl_api_sw_interface_ip6nd_ra_prefix_t * mp)
196{
197 vlib_main_t *vm = vlib_get_main ();
198 vl_api_sw_interface_ip6nd_ra_prefix_reply_t *rmp;
199 fib_prefix_t pfx;
200 int rv = 0;
201 u8 is_no, use_default, no_advertise, off_link, no_autoconfig, no_onlink;
202
203 VALIDATE_SW_IF_INDEX (mp);
204
205 ip_prefix_decode (&mp->prefix, &pfx);
206 is_no = mp->is_no == 1;
207 use_default = mp->use_default == 1;
208 no_advertise = mp->no_advertise == 1;
209 off_link = mp->off_link == 1;
210 no_autoconfig = mp->no_autoconfig == 1;
211 no_onlink = mp->no_onlink == 1;
212
213 rv = ip6_ra_prefix (vm, ntohl (mp->sw_if_index),
214 &pfx.fp_addr.ip6,
215 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 BAD_SW_IF_INDEX_LABEL;
221 REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
222}
223
224static void
225 vl_api_ip6nd_send_router_solicitation_t_handler
226 (vl_api_ip6nd_send_router_solicitation_t * mp)
227{
228 vl_api_ip6nd_send_router_solicitation_reply_t *rmp;
229 icmp6_send_router_solicitation_params_t params;
230 vlib_main_t *vm = vlib_get_main ();
231 int rv = 0;
232
233 VALIDATE_SW_IF_INDEX (mp);
234
235 BAD_SW_IF_INDEX_LABEL;
236 REPLY_MACRO (VL_API_IP6ND_SEND_ROUTER_SOLICITATION_REPLY);
237
238 if (rv != 0)
239 return;
240
241 params.irt = ntohl (mp->irt);
242 params.mrt = ntohl (mp->mrt);
243 params.mrc = ntohl (mp->mrc);
244 params.mrd = ntohl (mp->mrd);
245
246 icmp6_send_router_solicitation (vm, ntohl (mp->sw_if_index), mp->stop,
247 &params);
248}
249
250static void
251ip6_ra_handle_report (const ip6_ra_report_t * rap)
252{
253 /* *INDENT-OFF* */
254 vpe_client_registration_t *rp;
255
Damjan Marionb2c31b62020-12-13 21:47:40 +0100256 pool_foreach (rp, vpe_api_main.ip6_ra_events_registrations)
257 {
Neale Rannscbe25aa2019-09-30 10:53:31 +0000258 vl_api_registration_t *vl_reg;
259
260 vl_reg = vl_api_client_index_to_registration (rp->client_index);
261
262 if (vl_reg && vl_api_can_send_msg (vl_reg))
263 {
264 vl_api_ip6_ra_prefix_info_t *prefix;
265 vl_api_ip6_ra_event_t *event;
266
267 u32 event_size = (sizeof (vl_api_ip6_ra_event_t) +
268 vec_len (rap->prefixes) *
269 sizeof (vl_api_ip6_ra_prefix_info_t));
270 event = vl_msg_api_alloc_zero (event_size);
271
272 event->_vl_msg_id = htons (VL_API_IP6_RA_EVENT + REPLY_MSG_ID_BASE);
273 event->client_index = rp->client_index;
274 event->pid = rp->client_pid;
275 event->sw_if_index = clib_host_to_net_u32 (rap->sw_if_index);
276
277 ip6_address_encode (&rap->router_address,
278 event->router_addr);
279
280 event->current_hop_limit = rap->current_hop_limit;
281 event->flags = rap->flags;
282 event->router_lifetime_in_sec =
283 clib_host_to_net_u16 (rap->router_lifetime_in_sec);
284 event->neighbor_reachable_time_in_msec =
285 clib_host_to_net_u32 (rap->neighbor_reachable_time_in_msec);
286 event->time_in_msec_between_retransmitted_neighbor_solicitations =
287 clib_host_to_net_u32 (rap->time_in_msec_between_retransmitted_neighbor_solicitations);
288 event->n_prefixes = clib_host_to_net_u32 (vec_len (rap->prefixes));
289
290 prefix = event->prefixes;
291 // (typeof (prefix)) event->prefixes;
292 u32 j;
293 for (j = 0; j < vec_len (rap->prefixes); j++)
294 {
295 ra_report_prefix_info_t *info = &rap->prefixes[j];
296 ip_prefix_encode(&info->prefix, &prefix->prefix);
297 prefix->flags = info->flags;
298 prefix->valid_time = clib_host_to_net_u32 (info->valid_time);
299 prefix->preferred_time =
300 clib_host_to_net_u32 (info->preferred_time);
301 prefix++;
302 }
303
304 vl_api_send_msg (vl_reg, (u8 *) event);
305 }
Damjan Marionb2c31b62020-12-13 21:47:40 +0100306 }
Neale Rannscbe25aa2019-09-30 10:53:31 +0000307 /* *INDENT-ON* */
308}
309
310static void
311vl_api_want_ip6_ra_events_t_handler (vl_api_want_ip6_ra_events_t * mp)
312{
313 vpe_api_main_t *am = &vpe_api_main;
314 vl_api_want_ip6_ra_events_reply_t *rmp;
315 int rv = 0, had_reg, have_reg;
316
317 had_reg = hash_elts (am->ip6_ra_events_registration_hash);
318 uword *p = hash_get (am->ip6_ra_events_registration_hash, mp->client_index);
319 vpe_client_registration_t *rp;
320 if (p)
321 {
322 if (mp->enable)
323 {
324 clib_warning ("pid %d: already enabled...", ntohl (mp->pid));
325 rv = VNET_API_ERROR_INVALID_REGISTRATION;
326 goto reply;
327 }
328 else
329 {
330 rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
331 pool_put (am->ip6_ra_events_registrations, rp);
332 hash_unset (am->ip6_ra_events_registration_hash, mp->client_index);
333 goto reply;
334 }
335 }
336 if (mp->enable == 0)
337 {
338 clib_warning ("pid %d: already disabled...", ntohl (mp->pid));
339 rv = VNET_API_ERROR_INVALID_REGISTRATION;
340 goto reply;
341 }
342 pool_get (am->ip6_ra_events_registrations, rp);
343 rp->client_index = mp->client_index;
344 rp->client_pid = ntohl (mp->pid);
345 hash_set (am->ip6_ra_events_registration_hash, rp->client_index,
346 rp - am->ip6_ra_events_registrations);
347
348reply:
349 have_reg = hash_elts (am->ip6_ra_events_registration_hash);
350
351 if (!had_reg && have_reg)
352 ip6_ra_report_register (ip6_ra_handle_report);
353 else if (had_reg && !have_reg)
354 ip6_ra_report_unregister (ip6_ra_handle_report);
355
356 REPLY_MACRO (VL_API_WANT_IP6_RA_EVENTS_REPLY);
357}
358
359static clib_error_t *
360want_ip6_ra_events_reaper (u32 client_index)
361{
362 vpe_api_main_t *am = &vpe_api_main;
363 vpe_client_registration_t *rp;
364 uword *p;
365
366 p = hash_get (am->ip6_ra_events_registration_hash, client_index);
367
368 if (p)
369 {
370 rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
371 pool_put (am->ip6_ra_events_registrations, rp);
372 hash_unset (am->ip6_ra_events_registration_hash, client_index);
373 }
374 return (NULL);
375}
376
377VL_MSG_API_REAPER_FUNCTION (want_ip6_ra_events_reaper);
378
379#include <vnet/ip6-nd/ip6_nd.api.c>
380
381static clib_error_t *
382ip6_nd_api_init (vlib_main_t * vm)
383{
384 /* Ask for a correctly-sized block of API message decode slots */
385 ip6_nd_base_msg_id = setup_message_id_table ();
386
387 return 0;
388}
389
390VLIB_INIT_FUNCTION (ip6_nd_api_init);
391
392/*
393 * fd.io coding-style-patch-verification: ON
394 *
395 * Local Variables:
396 * eval: (c-set-style "gnu")
397 * End:
398 */