blob: 21e45519da1e9dc6bd204e0178a88cd08ed85eb5 [file] [log] [blame]
Juraj Sloboda0012fcc2018-05-17 12:05:27 +02001/*
2 * Copyright (c) 2018 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
Juraj Slobodac0374232018-02-01 15:18:49 +010016#include <vnet/vnet.h>
17#include <vlibmemory/api.h>
18#include <vnet/vnet_msg_enum.h>
19#include <vnet/ip/ip6.h>
Juraj Sloboda52574522018-05-03 10:03:50 +020020#include <vnet/ethernet/ethernet.h>
21#include <vnet/ip/ip6_neighbor.h>
Juraj Sloboda0012fcc2018-05-17 12:05:27 +020022#include <vnet/fib/fib_table.h>
Juraj Slobodac0374232018-02-01 15:18:49 +010023#include <signal.h>
24#include <math.h>
25
26#define vl_typedefs /* define message structures */
27#include <vnet/vnet_all_api_h.h>
28#undef vl_typedefs
29
30#define vl_endianfun /* define message structures */
31#include <vnet/vnet_all_api_h.h>
32#undef vl_endianfun
33
34#include <vlibapi/api_helper_macros.h>
35
36#define foreach_rd_cp_msg \
37_(IP6_ND_ADDRESS_AUTOCONFIG, ip6_nd_address_autoconfig)
38
Juraj Slobodac0374232018-02-01 15:18:49 +010039typedef struct
40{
41 u32 sw_if_index;
42 u8 address_length;
43 ip6_address_t address;
44 f64 due_time;
45} slaac_address_t;
46
47typedef struct
48{
49 u32 sw_if_index;
50 ip6_address_t router_address;
51 f64 due_time;
52} default_route_t;
53
54typedef struct
55{
56 u8 enabled;
57 u8 install_default_routes;
58} interface_config_t;
59
60typedef struct
61{
62 u8 enabled;
63 u8 events_on;
64
65 interface_config_t *config_by_sw_if_index;
66 slaac_address_t *slaac_address_pool;
67 default_route_t *default_route_pool;
68
69 /* binary API client */
70 u8 api_connected;
71 svm_queue_t *vl_input_queue;
72 u32 my_client_index;
Juraj Slobodac0374232018-02-01 15:18:49 +010073
74 /* convenience */
75 vlib_main_t *vlib_main;
76 vnet_main_t *vnet_main;
77 api_main_t *api_main;
78 u32 node_index;
79} rd_cp_main_t;
80
81rd_cp_main_t rd_cp_main;
82
83enum
84{
85 RD_CP_EVENT_INTERRUPT,
86};
87
88#define vl_api_ip6_nd_address_autoconfig_t_print vl_noop_handler
89
90static void
Juraj Slobodac0374232018-02-01 15:18:49 +010091router_solicitation_start_stop (u32 sw_if_index, u8 start)
92{
93 rd_cp_main_t *rm = &rd_cp_main;
Juraj Sloboda52574522018-05-03 10:03:50 +020094 icmp6_send_router_solicitation_params_t params = { 0, };
Juraj Slobodac0374232018-02-01 15:18:49 +010095
Juraj Slobodac0374232018-02-01 15:18:49 +010096 if (start)
97 {
Juraj Sloboda52574522018-05-03 10:03:50 +020098 params.irt = 1;
99 params.mrt = 120;
Juraj Slobodac0374232018-02-01 15:18:49 +0100100 }
Juraj Slobodac0374232018-02-01 15:18:49 +0100101
Juraj Sloboda52574522018-05-03 10:03:50 +0200102 icmp6_send_router_solicitation (rm->vlib_main, sw_if_index, !start,
103 &params);
Juraj Slobodac0374232018-02-01 15:18:49 +0100104}
105
106static void interrupt_process (void);
107
108static int
109add_slaac_address (vlib_main_t * vm, u32 sw_if_index, u8 address_length,
110 ip6_address_t * address, f64 due_time)
111{
112 rd_cp_main_t *rm = &rd_cp_main;
113 slaac_address_t *slaac_address;
Juraj Sloboda52574522018-05-03 10:03:50 +0200114 clib_error_t *rv = 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100115
116 pool_get (rm->slaac_address_pool, slaac_address);
117
118 slaac_address->sw_if_index = sw_if_index;
119 slaac_address->address_length = address_length;
120 slaac_address->address = *address;
121 slaac_address->due_time = due_time;
122
Juraj Sloboda52574522018-05-03 10:03:50 +0200123 rv =
124 ip6_add_del_interface_address (vm, sw_if_index, &slaac_address->address,
125 address_length, 0);
Juraj Slobodac0374232018-02-01 15:18:49 +0100126
Juraj Sloboda52574522018-05-03 10:03:50 +0200127 return rv != 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100128}
129
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200130static void
Juraj Slobodac0374232018-02-01 15:18:49 +0100131add_default_route (vlib_main_t * vm, u32 sw_if_index,
132 ip6_address_t * next_hop_address, f64 due_time)
133{
134 rd_cp_main_t *rm = &rd_cp_main;
135 default_route_t *default_route;
Juraj Slobodac0374232018-02-01 15:18:49 +0100136
137 pool_get (rm->default_route_pool, default_route);
138
139 default_route->sw_if_index = sw_if_index;
140 default_route->router_address = *next_hop_address;
141 default_route->due_time = due_time;
142
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200143 {
144 u32 fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6,
145 default_route->
146 sw_if_index);
147 fib_prefix_t pfx = {
148 .fp_proto = FIB_PROTOCOL_IP6,
149 };
150 ip46_address_t nh = {
151 .ip6 = default_route->router_address,
152 };
153 fib_table_entry_update_one_path (fib_index, &pfx,
154 FIB_SOURCE_API,
155 FIB_ENTRY_FLAG_NONE,
156 DPO_PROTO_IP6,
157 &nh,
158 default_route->sw_if_index,
159 0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
160 }
Juraj Slobodac0374232018-02-01 15:18:49 +0100161}
162
Juraj Slobodac0374232018-02-01 15:18:49 +0100163static int
164remove_slaac_address (vlib_main_t * vm, slaac_address_t * slaac_address)
165{
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200166 rd_cp_main_t *rm = &rd_cp_main;
Juraj Sloboda52574522018-05-03 10:03:50 +0200167 clib_error_t *rv = 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100168
Juraj Sloboda52574522018-05-03 10:03:50 +0200169 rv = ip6_add_del_interface_address (vm, slaac_address->sw_if_index,
170 &slaac_address->address,
171 slaac_address->address_length, 1);
Juraj Slobodac0374232018-02-01 15:18:49 +0100172
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200173 pool_put (rm->slaac_address_pool, slaac_address);
174
Juraj Sloboda52574522018-05-03 10:03:50 +0200175 return rv != 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100176}
177
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200178static void
Juraj Slobodac0374232018-02-01 15:18:49 +0100179remove_default_route (vlib_main_t * vm, default_route_t * default_route)
180{
181 rd_cp_main_t *rm = &rd_cp_main;
Juraj Slobodac0374232018-02-01 15:18:49 +0100182
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200183 {
184 u32 fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6,
185 default_route->
186 sw_if_index);
187 fib_prefix_t pfx = {
188 .fp_proto = FIB_PROTOCOL_IP6,
189 };
190 ip46_address_t nh = {
191 .ip6 = default_route->router_address,
192 };
193 fib_table_entry_path_remove (fib_index, &pfx,
194 FIB_SOURCE_API,
195 DPO_PROTO_IP6,
196 &nh,
197 default_route->sw_if_index,
198 0, 1, FIB_ROUTE_PATH_FLAG_NONE);
199 }
Juraj Slobodac0374232018-02-01 15:18:49 +0100200
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200201 pool_put (rm->default_route_pool, default_route);
Juraj Slobodac0374232018-02-01 15:18:49 +0100202}
203
204static u32
205get_interface_mac_address (u32 sw_if_index, u8 mac[])
206{
207 rd_cp_main_t *rm = &rd_cp_main;
Juraj Sloboda52574522018-05-03 10:03:50 +0200208 vnet_sw_interface_t *si;
209 ethernet_interface_t *eth_if = 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100210
Juraj Sloboda52574522018-05-03 10:03:50 +0200211 if (!vnet_sw_interface_is_api_valid (rm->vnet_main, sw_if_index))
212 {
213 clib_warning ("Invalid sw_if_index");
214 return 1;
215 }
Juraj Slobodac0374232018-02-01 15:18:49 +0100216
Juraj Sloboda52574522018-05-03 10:03:50 +0200217 si = vnet_get_sup_sw_interface (rm->vnet_main, sw_if_index);
218 if (si->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
219 eth_if = ethernet_get_interface (&ethernet_main, si->hw_if_index);
Juraj Slobodac0374232018-02-01 15:18:49 +0100220
Juraj Sloboda52574522018-05-03 10:03:50 +0200221 clib_memcpy (mac, eth_if->address, 6);
Juraj Slobodac0374232018-02-01 15:18:49 +0100222
Juraj Sloboda52574522018-05-03 10:03:50 +0200223 return 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100224}
225
226static u32
227ip6_enable (u32 sw_if_index)
228{
229 rd_cp_main_t *rm = &rd_cp_main;
Juraj Sloboda52574522018-05-03 10:03:50 +0200230 clib_error_t *rv;
Juraj Slobodac0374232018-02-01 15:18:49 +0100231
Juraj Sloboda52574522018-05-03 10:03:50 +0200232 rv = enable_ip6_interface (rm->vlib_main, sw_if_index);
Juraj Slobodac0374232018-02-01 15:18:49 +0100233
Juraj Sloboda52574522018-05-03 10:03:50 +0200234 return rv != 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100235}
236
237static u8
238ip6_prefixes_equal (ip6_address_t * prefix1, ip6_address_t * prefix2, u8 len)
239{
240 if (len >= 64)
241 {
242 if (prefix1->as_u64[0] != prefix2->as_u64[0])
243 return 0;
244 if (len == 64)
245 return 1;
246 return prefix1->as_u64[1] >> (128 - len) ==
247 prefix2->as_u64[1] >> (128 - len);
248 }
249 return prefix1->as_u64[0] >> (64 - len) == prefix2->as_u64[0] >> (64 - len);
250}
251
252#define PREFIX_FLAG_A (1 << 6)
253#define PREFIX_FLAG_L (1 << 7)
254
Juraj Sloboda52574522018-05-03 10:03:50 +0200255static clib_error_t *
256ip6_ra_report_handler (void *data)
Juraj Slobodac0374232018-02-01 15:18:49 +0100257{
258 rd_cp_main_t *rm = &rd_cp_main;
259 vlib_main_t *vm = rm->vlib_main;
Juraj Sloboda52574522018-05-03 10:03:50 +0200260 clib_error_t *error = 0;
261 ra_report_t *r = data;
Juraj Slobodac0374232018-02-01 15:18:49 +0100262 interface_config_t *if_config;
263 default_route_t *default_route;
264 slaac_address_t *slaac_address;
265 u32 sw_if_index;
266 u16 router_lifetime_in_sec;
267 u32 n_prefixes;
Juraj Sloboda52574522018-05-03 10:03:50 +0200268 ra_report_prefix_info_t *prefix;
Juraj Slobodac0374232018-02-01 15:18:49 +0100269 u8 mac[6];
270 f64 current_time;
271 u32 i;
272
273 current_time = vlib_time_now (vm);
274
Juraj Sloboda52574522018-05-03 10:03:50 +0200275 sw_if_index = r->sw_if_index;
Juraj Slobodac0374232018-02-01 15:18:49 +0100276
Juraj Sloboda52574522018-05-03 10:03:50 +0200277 if (sw_if_index >= vec_len (rm->config_by_sw_if_index))
278 return 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100279 if_config = &rm->config_by_sw_if_index[sw_if_index];
280
281 if (if_config->install_default_routes)
282 {
Juraj Sloboda52574522018-05-03 10:03:50 +0200283 router_lifetime_in_sec = r->router_lifetime_in_sec;
Juraj Slobodac0374232018-02-01 15:18:49 +0100284 u8 route_already_present = 0;
285 /* *INDENT-OFF* */
286 pool_foreach (default_route, rm->default_route_pool,
287 ({
288 if (default_route->sw_if_index != sw_if_index)
289 ;
290 else if (0 != memcmp (&default_route->router_address,
Juraj Sloboda52574522018-05-03 10:03:50 +0200291 r->router_address, 16))
Juraj Slobodac0374232018-02-01 15:18:49 +0100292 ;
293 else
294 {
295 route_already_present = 1;
296 goto default_route_pool_foreach_out;
297 }
298 }));
299 /* *INDENT-ON* */
300 default_route_pool_foreach_out:
301
302 if (!route_already_present)
303 {
304 if (router_lifetime_in_sec != 0)
Juraj Sloboda52574522018-05-03 10:03:50 +0200305 add_default_route (vm, sw_if_index, (void *) r->router_address,
Juraj Slobodac0374232018-02-01 15:18:49 +0100306 current_time + router_lifetime_in_sec);
307 }
308 else
309 {
310 if (router_lifetime_in_sec != 0)
311 default_route->due_time = current_time + router_lifetime_in_sec;
312 else
313 remove_default_route (vm, default_route);
314 }
315 }
316
317 if (get_interface_mac_address (sw_if_index, mac) != 0)
318 {
319 clib_warning ("Error getting MAC address");
Juraj Sloboda52574522018-05-03 10:03:50 +0200320 return clib_error_return (0, "Error getting MAC address");
Juraj Slobodac0374232018-02-01 15:18:49 +0100321 }
322
323 if (!if_config->enabled)
Juraj Sloboda52574522018-05-03 10:03:50 +0200324 return 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100325
Juraj Sloboda52574522018-05-03 10:03:50 +0200326 n_prefixes = vec_len (r->prefixes);
Juraj Slobodac0374232018-02-01 15:18:49 +0100327 for (i = 0; i < n_prefixes; i++)
328 {
329 ip6_address_t *dst_address;
330 u8 prefix_length;
331 u32 valid_time;
332 u32 preferred_time;
333 f64 due_time;
334
Juraj Sloboda52574522018-05-03 10:03:50 +0200335 prefix = &r->prefixes[i];
Juraj Slobodac0374232018-02-01 15:18:49 +0100336
337 if (!(prefix->flags & PREFIX_FLAG_A))
338 continue;
339
Juraj Sloboda52574522018-05-03 10:03:50 +0200340 dst_address = &prefix->dst_address;
Juraj Slobodac0374232018-02-01 15:18:49 +0100341 prefix_length = prefix->dst_address_length;
342
343 if (ip6_address_is_link_local_unicast (dst_address))
344 continue;
345
Juraj Sloboda52574522018-05-03 10:03:50 +0200346 valid_time = prefix->valid_time;
347 preferred_time = prefix->preferred_time;
Juraj Slobodac0374232018-02-01 15:18:49 +0100348
349 if (preferred_time > valid_time)
350 continue;
351
352 if (prefix_length != 64)
353 continue;
354
355 u8 address_already_present = 0;
356 /* *INDENT-OFF* */
357 pool_foreach (slaac_address, rm->slaac_address_pool,
358 ({
359 if (slaac_address->sw_if_index != sw_if_index)
360 ;
361 else if (slaac_address->address_length != prefix_length)
362 ;
363 else if (!ip6_prefixes_equal (&slaac_address->address, dst_address,
364 prefix_length))
365 ;
366 else
367 {
368 address_already_present = 1;
369 goto slaac_address_pool_foreach_out;
370 }
371 }));
372 /* *INDENT-ON* */
373 slaac_address_pool_foreach_out:
374
375 if (address_already_present)
376 {
377 f64 remaining_life_time = slaac_address->due_time - current_time;
378 if (valid_time > 2 * 60 * 60 || valid_time > remaining_life_time)
379 slaac_address->due_time = current_time + valid_time;
380 else if (remaining_life_time > 2 * 60 * 60)
381 slaac_address->due_time = current_time + 2 * 60 * 60;
382 continue;
383 }
384
385 if (valid_time == 0)
386 continue;
387
388 due_time = current_time + valid_time;
389
390 ip6_address_t addr;
391 addr.as_u64[0] = dst_address->as_u64[0];
392 /* Invert the "u" bit */
393 addr.as_u8[8] = mac[0] ^ (1 << 1);
394 addr.as_u8[9] = mac[1];
395 addr.as_u8[10] = mac[2];
396 addr.as_u8[11] = 0xFF;
397 addr.as_u8[12] = 0xFE;
398 addr.as_u8[13] = mac[3];
399 addr.as_u8[14] = mac[4];
400 addr.as_u8[15] = mac[5];
401
402 add_slaac_address (vm, sw_if_index, prefix_length, &addr, due_time);
403 }
404
405 interrupt_process ();
Juraj Sloboda52574522018-05-03 10:03:50 +0200406
407 return error;
Juraj Slobodac0374232018-02-01 15:18:49 +0100408}
409
Juraj Sloboda52574522018-05-03 10:03:50 +0200410VNET_IP6_NEIGHBOR_RA_FUNCTION (ip6_ra_report_handler);
411
Juraj Slobodac0374232018-02-01 15:18:49 +0100412static uword
413rd_cp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
414{
Juraj Slobodac0374232018-02-01 15:18:49 +0100415 uword *event_data = 0;
416 rd_cp_main_t *rm = &rd_cp_main;
417 slaac_address_t *slaac_address;
418 default_route_t *default_route;
419 f64 sleep_time = 1e9;
Juraj Slobodac0374232018-02-01 15:18:49 +0100420 f64 current_time;
421 f64 due_time;
422
423 while (1)
424 {
Juraj Sloboda52574522018-05-03 10:03:50 +0200425 vlib_process_wait_for_event_or_clock (vm, sleep_time);
426 vlib_process_get_events (vm, &event_data);
Juraj Slobodac0374232018-02-01 15:18:49 +0100427
428 vec_reset_length (event_data);
429
430 current_time = vlib_time_now (vm);
431 do
432 {
433 due_time = current_time + 1e9;
434 /* *INDENT-OFF* */
435 pool_foreach (slaac_address, rm->slaac_address_pool,
436 ({
437 if (slaac_address->due_time > current_time)
438 {
439 if (slaac_address->due_time < due_time)
440 due_time = slaac_address->due_time;
441 }
442 else
443 {
444 remove_slaac_address (vm, slaac_address);
445 /* make sure ip6 stays enabled */
446 ip6_enable (slaac_address->sw_if_index);
447 }
448 }));
449 pool_foreach (default_route, rm->default_route_pool,
450 ({
451 if (default_route->due_time > current_time)
452 {
453 if (default_route->due_time < due_time)
454 due_time = default_route->due_time;
455 }
456 else
457 remove_default_route (vm, default_route);
458 }));
459 /* *INDENT-ON* */
460 current_time = vlib_time_now (vm);
461 }
462 while (due_time < current_time);
463
464 sleep_time = due_time - current_time;
465 }
466
467 return 0;
468}
469
470/* *INDENT-OFF* */
471VLIB_REGISTER_NODE (rd_cp_process_node) = {
472 .function = rd_cp_process,
473 .type = VLIB_NODE_TYPE_PROCESS,
474 .name = "rd-cp-process",
475};
476/* *INDENT-ON* */
477
478static void
479interrupt_process (void)
480{
481 rd_cp_main_t *rm = &rd_cp_main;
482 vlib_main_t *vm = rm->vlib_main;
483
484 vlib_process_signal_event (vm, rd_cp_process_node.index,
485 RD_CP_EVENT_INTERRUPT, 0);
486}
487
488static int
Juraj Slobodac0374232018-02-01 15:18:49 +0100489set_address_autoconfig (u32 sw_if_index, u8 enable, u8 install_default_routes)
490{
491 rd_cp_main_t *rm = &rd_cp_main;
492 vlib_main_t *vm = rm->vlib_main;
493 vnet_main_t *vnm = rm->vnet_main;
494 interface_config_t *if_config;
495 interface_config_t empty_config = { 0, 0 };
496 slaac_address_t *slaac_address;
497 default_route_t *default_route;
498
499 if (!enable)
500 install_default_routes = 0;
501
Juraj Slobodac0374232018-02-01 15:18:49 +0100502 if (!vnet_sw_interface_is_api_valid (vnm, sw_if_index))
503 {
504 clib_warning ("Invalid sw_if_index");
505 return 1;
506 }
507
508 if (!rm->enabled)
509 {
Juraj Slobodac0374232018-02-01 15:18:49 +0100510 /* process kickoff */
511 interrupt_process ();
Juraj Slobodac0374232018-02-01 15:18:49 +0100512 rm->enabled = 1;
513 }
514
515 vec_validate_init_empty (rm->config_by_sw_if_index, sw_if_index,
516 empty_config);
517 if_config = &rm->config_by_sw_if_index[sw_if_index];
518
519 if (!if_config->enabled && enable)
520 ip6_enable (sw_if_index);
521
522 if ((!if_config->enabled && enable)
523 || (!if_config->install_default_routes && install_default_routes))
524 router_solicitation_start_stop (sw_if_index, 1);
525 else if (if_config->enabled && !enable)
526 router_solicitation_start_stop (sw_if_index, 0);
527
528 if (if_config->enabled && !enable)
529 {
530 /* *INDENT-OFF* */
531 pool_foreach (slaac_address, rm->slaac_address_pool,
532 ({
533 remove_slaac_address (vm, slaac_address);
534 }));
535 /* *INDENT-ON* */
536 }
537 if (if_config->install_default_routes && !install_default_routes)
538 {
539 /* *INDENT-OFF* */
540 pool_foreach (default_route, rm->default_route_pool,
541 ({
542 remove_default_route (vm, default_route);
543 }));
544 /* *INDENT-ON* */
545 }
546
547 if_config->enabled = enable;
548 if_config->install_default_routes = install_default_routes;
549
550 return 0;
551}
552
553static clib_error_t *
554ip6_nd_address_autoconfig (vlib_main_t * vm,
555 unformat_input_t * input, vlib_cli_command_t * cmd)
556{
557 rd_cp_main_t *rm = &rd_cp_main;
558 vnet_main_t *vnm = rm->vnet_main;
559 clib_error_t *error = 0;
560 u32 sw_if_index = ~0;
561 u8 enable = 1;
562 u8 default_route = 0;
563
564 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
565 {
566 if (unformat
567 (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
568 ;
569 if (unformat (input, "default-route"))
570 default_route = 1;
571 if (unformat (input, "disable"))
572 enable = 0;
573 else
574 break;
575 }
576
577 if (sw_if_index != ~0)
578 {
579 if (set_address_autoconfig (sw_if_index, enable, default_route) != 0)
580 error = clib_error_return (0, "Invalid sw_if_index");
581 }
582 else
583 error = clib_error_return (0, "Missing sw_if_index");
584
585 return error;
586}
587
588/*?
589 * This command is used to enable ND address autoconfiguration
590 * on particular interface including setting up default routes.
591 *
592 * @cliexpar
593 * @parblock
594 * Example of how to enable ND address autoconfiguration:
595 * @cliexcmd{ip6 nd address autoconfig GigabitEthernet2/0/0}
596 * Example of how to enable ND address autoconfiguration
597 * with setting up default routes:
598 * @cliexcmd{ip6 nd address autoconfig GigabitEthernet2/0/0 default-route}
599 * Example of how to disable ND address autoconfiguration:
600 * @cliexcmd{ip6 nd address autoconfig GigabitEthernet2/0/0 disable}
601 * @endparblock
602?*/
603/* *INDENT-OFF* */
604VLIB_CLI_COMMAND (ip6_nd_address_autoconfig_command, static) = {
605 .path = "ip6 nd address autoconfig",
606 .short_help = "ip6 nd address autoconfig <interface> [default-route|disable]",
607 .function = ip6_nd_address_autoconfig,
608};
609/* *INDENT-ON* */
610
611static void
612vl_api_ip6_nd_address_autoconfig_t_handler (vl_api_ip6_nd_address_autoconfig_t
613 * mp)
614{
615 vl_api_ip6_nd_address_autoconfig_reply_t *rmp;
616 u32 sw_if_index;
617 int rv = 0;
618
619 VALIDATE_SW_IF_INDEX (mp);
620
621 sw_if_index = ntohl (mp->sw_if_index);
622
623 rv =
624 set_address_autoconfig (sw_if_index, mp->enable,
625 mp->install_default_routes);
626
627 BAD_SW_IF_INDEX_LABEL;
628
629 REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
630}
631
632#define vl_msg_name_crc_list
633#include <vnet/ip/rd_cp.api.h>
634#undef vl_msg_name_crc_list
635
636static void
637setup_message_id_table (api_main_t * am)
638{
639#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
640 foreach_vl_msg_name_crc_rd_cp;
641#undef _
642}
643
644static clib_error_t *
645rd_cp_init (vlib_main_t * vm)
646{
647 rd_cp_main_t *rm = &rd_cp_main;
648 api_main_t *am = &api_main;
649
650 rm->vlib_main = vm;
651 rm->vnet_main = vnet_get_main ();
652 rm->api_main = am;
653 rm->node_index = rd_cp_process_node.index;
654
655#define _(N,n) \
656 vl_msg_api_set_handlers(VL_API_##N, #n, \
657 vl_api_##n##_t_handler, \
658 vl_noop_handler, \
659 vl_api_##n##_t_endian, \
660 vl_api_##n##_t_print, \
661 sizeof(vl_api_##n##_t), 0/* do NOT trace! */);
662 foreach_rd_cp_msg;
663#undef _
664
Juraj Slobodac0374232018-02-01 15:18:49 +0100665 /*
666 * Set up the (msg_name, crc, message-id) table
667 */
668 setup_message_id_table (am);
669
670 return 0;
671}
672
673VLIB_INIT_FUNCTION (rd_cp_init);
674
675/*
676 * fd.io coding-style-patch-verification: ON
677 *
678 * Local Variables:
679 * eval: (c-set-style "gnu")
680 * End:
681 */