blob: c9c387e07c0be34505bf95f02d8616da0d022f20 [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
Juraj Slobodac65770d2018-05-15 11:43:56 +020074 /* logging */
75 vlib_log_class_t log_class;
76
Juraj Slobodac0374232018-02-01 15:18:49 +010077 /* convenience */
78 vlib_main_t *vlib_main;
79 vnet_main_t *vnet_main;
80 api_main_t *api_main;
81 u32 node_index;
82} rd_cp_main_t;
83
84rd_cp_main_t rd_cp_main;
85
86enum
87{
88 RD_CP_EVENT_INTERRUPT,
89};
90
91#define vl_api_ip6_nd_address_autoconfig_t_print vl_noop_handler
92
93static void
Juraj Slobodac0374232018-02-01 15:18:49 +010094router_solicitation_start_stop (u32 sw_if_index, u8 start)
95{
96 rd_cp_main_t *rm = &rd_cp_main;
Juraj Sloboda52574522018-05-03 10:03:50 +020097 icmp6_send_router_solicitation_params_t params = { 0, };
Juraj Slobodac0374232018-02-01 15:18:49 +010098
Juraj Slobodac0374232018-02-01 15:18:49 +010099 if (start)
100 {
Juraj Sloboda52574522018-05-03 10:03:50 +0200101 params.irt = 1;
102 params.mrt = 120;
Juraj Slobodac0374232018-02-01 15:18:49 +0100103 }
Juraj Slobodac0374232018-02-01 15:18:49 +0100104
Juraj Sloboda52574522018-05-03 10:03:50 +0200105 icmp6_send_router_solicitation (rm->vlib_main, sw_if_index, !start,
106 &params);
Juraj Slobodac0374232018-02-01 15:18:49 +0100107}
108
109static void interrupt_process (void);
110
111static int
112add_slaac_address (vlib_main_t * vm, u32 sw_if_index, u8 address_length,
113 ip6_address_t * address, f64 due_time)
114{
115 rd_cp_main_t *rm = &rd_cp_main;
116 slaac_address_t *slaac_address;
Juraj Sloboda52574522018-05-03 10:03:50 +0200117 clib_error_t *rv = 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100118
119 pool_get (rm->slaac_address_pool, slaac_address);
120
121 slaac_address->sw_if_index = sw_if_index;
122 slaac_address->address_length = address_length;
123 slaac_address->address = *address;
124 slaac_address->due_time = due_time;
125
Juraj Sloboda52574522018-05-03 10:03:50 +0200126 rv =
127 ip6_add_del_interface_address (vm, sw_if_index, &slaac_address->address,
128 address_length, 0);
Juraj Slobodac0374232018-02-01 15:18:49 +0100129
Juraj Sloboda52574522018-05-03 10:03:50 +0200130 return rv != 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100131}
132
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200133static void
Juraj Slobodac0374232018-02-01 15:18:49 +0100134add_default_route (vlib_main_t * vm, u32 sw_if_index,
135 ip6_address_t * next_hop_address, f64 due_time)
136{
137 rd_cp_main_t *rm = &rd_cp_main;
138 default_route_t *default_route;
Juraj Slobodac0374232018-02-01 15:18:49 +0100139
140 pool_get (rm->default_route_pool, default_route);
141
142 default_route->sw_if_index = sw_if_index;
143 default_route->router_address = *next_hop_address;
144 default_route->due_time = due_time;
145
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200146 {
147 u32 fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6,
148 default_route->
149 sw_if_index);
150 fib_prefix_t pfx = {
151 .fp_proto = FIB_PROTOCOL_IP6,
152 };
153 ip46_address_t nh = {
154 .ip6 = default_route->router_address,
155 };
156 fib_table_entry_update_one_path (fib_index, &pfx,
157 FIB_SOURCE_API,
158 FIB_ENTRY_FLAG_NONE,
159 DPO_PROTO_IP6,
160 &nh,
161 default_route->sw_if_index,
162 0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
163 }
Juraj Slobodac0374232018-02-01 15:18:49 +0100164}
165
Juraj Slobodac0374232018-02-01 15:18:49 +0100166static int
167remove_slaac_address (vlib_main_t * vm, slaac_address_t * slaac_address)
168{
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200169 rd_cp_main_t *rm = &rd_cp_main;
Juraj Sloboda52574522018-05-03 10:03:50 +0200170 clib_error_t *rv = 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100171
Juraj Sloboda52574522018-05-03 10:03:50 +0200172 rv = ip6_add_del_interface_address (vm, slaac_address->sw_if_index,
173 &slaac_address->address,
174 slaac_address->address_length, 1);
Juraj Slobodac0374232018-02-01 15:18:49 +0100175
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200176 pool_put (rm->slaac_address_pool, slaac_address);
177
Juraj Sloboda52574522018-05-03 10:03:50 +0200178 return rv != 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100179}
180
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200181static void
Juraj Slobodac0374232018-02-01 15:18:49 +0100182remove_default_route (vlib_main_t * vm, default_route_t * default_route)
183{
184 rd_cp_main_t *rm = &rd_cp_main;
Juraj Slobodac0374232018-02-01 15:18:49 +0100185
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200186 {
187 u32 fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6,
188 default_route->
189 sw_if_index);
190 fib_prefix_t pfx = {
191 .fp_proto = FIB_PROTOCOL_IP6,
192 };
193 ip46_address_t nh = {
194 .ip6 = default_route->router_address,
195 };
196 fib_table_entry_path_remove (fib_index, &pfx,
197 FIB_SOURCE_API,
198 DPO_PROTO_IP6,
199 &nh,
200 default_route->sw_if_index,
201 0, 1, FIB_ROUTE_PATH_FLAG_NONE);
202 }
Juraj Slobodac0374232018-02-01 15:18:49 +0100203
Juraj Sloboda0012fcc2018-05-17 12:05:27 +0200204 pool_put (rm->default_route_pool, default_route);
Juraj Slobodac0374232018-02-01 15:18:49 +0100205}
206
207static u32
208get_interface_mac_address (u32 sw_if_index, u8 mac[])
209{
210 rd_cp_main_t *rm = &rd_cp_main;
Juraj Sloboda52574522018-05-03 10:03:50 +0200211 vnet_sw_interface_t *si;
212 ethernet_interface_t *eth_if = 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100213
Juraj Sloboda52574522018-05-03 10:03:50 +0200214 if (!vnet_sw_interface_is_api_valid (rm->vnet_main, sw_if_index))
215 {
Juraj Slobodac65770d2018-05-15 11:43:56 +0200216 vlib_log_warn (rm->log_class, "Invalid sw_if_index");
Juraj Sloboda52574522018-05-03 10:03:50 +0200217 return 1;
218 }
Juraj Slobodac0374232018-02-01 15:18:49 +0100219
Juraj Sloboda52574522018-05-03 10:03:50 +0200220 si = vnet_get_sup_sw_interface (rm->vnet_main, sw_if_index);
221 if (si->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
222 eth_if = ethernet_get_interface (&ethernet_main, si->hw_if_index);
Juraj Slobodac0374232018-02-01 15:18:49 +0100223
Juraj Slobodac65770d2018-05-15 11:43:56 +0200224 if (!eth_if)
225 {
226 vlib_log_warn (rm->log_class, "Failed to get hardware interface");
227 return 1;
228 }
229
Dave Barach178cf492018-11-13 16:34:13 -0500230 clib_memcpy_fast (mac, eth_if->address, 6);
Juraj Slobodac0374232018-02-01 15:18:49 +0100231
Juraj Sloboda52574522018-05-03 10:03:50 +0200232 return 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100233}
234
235static u32
236ip6_enable (u32 sw_if_index)
237{
238 rd_cp_main_t *rm = &rd_cp_main;
Juraj Sloboda52574522018-05-03 10:03:50 +0200239 clib_error_t *rv;
Juraj Slobodac0374232018-02-01 15:18:49 +0100240
Juraj Sloboda52574522018-05-03 10:03:50 +0200241 rv = enable_ip6_interface (rm->vlib_main, sw_if_index);
Juraj Slobodac0374232018-02-01 15:18:49 +0100242
Juraj Sloboda52574522018-05-03 10:03:50 +0200243 return rv != 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100244}
245
246static u8
247ip6_prefixes_equal (ip6_address_t * prefix1, ip6_address_t * prefix2, u8 len)
248{
249 if (len >= 64)
250 {
251 if (prefix1->as_u64[0] != prefix2->as_u64[0])
252 return 0;
253 if (len == 64)
254 return 1;
255 return prefix1->as_u64[1] >> (128 - len) ==
256 prefix2->as_u64[1] >> (128 - len);
257 }
258 return prefix1->as_u64[0] >> (64 - len) == prefix2->as_u64[0] >> (64 - len);
259}
260
261#define PREFIX_FLAG_A (1 << 6)
262#define PREFIX_FLAG_L (1 << 7)
263
Juraj Sloboda52574522018-05-03 10:03:50 +0200264static clib_error_t *
265ip6_ra_report_handler (void *data)
Juraj Slobodac0374232018-02-01 15:18:49 +0100266{
267 rd_cp_main_t *rm = &rd_cp_main;
268 vlib_main_t *vm = rm->vlib_main;
Juraj Sloboda52574522018-05-03 10:03:50 +0200269 clib_error_t *error = 0;
270 ra_report_t *r = data;
Juraj Slobodac0374232018-02-01 15:18:49 +0100271 interface_config_t *if_config;
272 default_route_t *default_route;
273 slaac_address_t *slaac_address;
274 u32 sw_if_index;
275 u16 router_lifetime_in_sec;
276 u32 n_prefixes;
Juraj Sloboda52574522018-05-03 10:03:50 +0200277 ra_report_prefix_info_t *prefix;
Juraj Slobodac0374232018-02-01 15:18:49 +0100278 u8 mac[6];
279 f64 current_time;
280 u32 i;
281
282 current_time = vlib_time_now (vm);
283
Juraj Sloboda52574522018-05-03 10:03:50 +0200284 sw_if_index = r->sw_if_index;
Juraj Slobodac0374232018-02-01 15:18:49 +0100285
Juraj Sloboda52574522018-05-03 10:03:50 +0200286 if (sw_if_index >= vec_len (rm->config_by_sw_if_index))
287 return 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100288 if_config = &rm->config_by_sw_if_index[sw_if_index];
289
290 if (if_config->install_default_routes)
291 {
Juraj Sloboda52574522018-05-03 10:03:50 +0200292 router_lifetime_in_sec = r->router_lifetime_in_sec;
Juraj Slobodac0374232018-02-01 15:18:49 +0100293 u8 route_already_present = 0;
294 /* *INDENT-OFF* */
295 pool_foreach (default_route, rm->default_route_pool,
296 ({
297 if (default_route->sw_if_index != sw_if_index)
298 ;
299 else if (0 != memcmp (&default_route->router_address,
Neale Ranns37029302018-08-10 05:30:06 -0700300 &r->router_address, 16))
Juraj Slobodac0374232018-02-01 15:18:49 +0100301 ;
302 else
303 {
304 route_already_present = 1;
305 goto default_route_pool_foreach_out;
306 }
307 }));
308 /* *INDENT-ON* */
309 default_route_pool_foreach_out:
310
311 if (!route_already_present)
312 {
313 if (router_lifetime_in_sec != 0)
Neale Ranns37029302018-08-10 05:30:06 -0700314 add_default_route (vm, sw_if_index, &r->router_address,
Juraj Slobodac0374232018-02-01 15:18:49 +0100315 current_time + router_lifetime_in_sec);
316 }
317 else
318 {
319 if (router_lifetime_in_sec != 0)
320 default_route->due_time = current_time + router_lifetime_in_sec;
321 else
322 remove_default_route (vm, default_route);
323 }
324 }
325
326 if (get_interface_mac_address (sw_if_index, mac) != 0)
327 {
Juraj Slobodac65770d2018-05-15 11:43:56 +0200328 vlib_log_warn (rm->log_class, "Error getting MAC address");
Juraj Sloboda52574522018-05-03 10:03:50 +0200329 return clib_error_return (0, "Error getting MAC address");
Juraj Slobodac0374232018-02-01 15:18:49 +0100330 }
331
332 if (!if_config->enabled)
Juraj Sloboda52574522018-05-03 10:03:50 +0200333 return 0;
Juraj Slobodac0374232018-02-01 15:18:49 +0100334
Juraj Sloboda52574522018-05-03 10:03:50 +0200335 n_prefixes = vec_len (r->prefixes);
Juraj Slobodac0374232018-02-01 15:18:49 +0100336 for (i = 0; i < n_prefixes; i++)
337 {
338 ip6_address_t *dst_address;
339 u8 prefix_length;
340 u32 valid_time;
341 u32 preferred_time;
342 f64 due_time;
343
Juraj Sloboda52574522018-05-03 10:03:50 +0200344 prefix = &r->prefixes[i];
Juraj Slobodac0374232018-02-01 15:18:49 +0100345
346 if (!(prefix->flags & PREFIX_FLAG_A))
347 continue;
348
Neale Ranns37029302018-08-10 05:30:06 -0700349 dst_address = &prefix->prefix.fp_addr.ip6;
350 prefix_length = prefix->prefix.fp_len;
Juraj Slobodac0374232018-02-01 15:18:49 +0100351
352 if (ip6_address_is_link_local_unicast (dst_address))
353 continue;
354
Juraj Sloboda52574522018-05-03 10:03:50 +0200355 valid_time = prefix->valid_time;
356 preferred_time = prefix->preferred_time;
Juraj Slobodac0374232018-02-01 15:18:49 +0100357
358 if (preferred_time > valid_time)
359 continue;
360
361 if (prefix_length != 64)
362 continue;
363
364 u8 address_already_present = 0;
365 /* *INDENT-OFF* */
366 pool_foreach (slaac_address, rm->slaac_address_pool,
367 ({
368 if (slaac_address->sw_if_index != sw_if_index)
369 ;
370 else if (slaac_address->address_length != prefix_length)
371 ;
372 else if (!ip6_prefixes_equal (&slaac_address->address, dst_address,
373 prefix_length))
374 ;
375 else
376 {
377 address_already_present = 1;
378 goto slaac_address_pool_foreach_out;
379 }
380 }));
381 /* *INDENT-ON* */
382 slaac_address_pool_foreach_out:
383
384 if (address_already_present)
385 {
386 f64 remaining_life_time = slaac_address->due_time - current_time;
387 if (valid_time > 2 * 60 * 60 || valid_time > remaining_life_time)
388 slaac_address->due_time = current_time + valid_time;
389 else if (remaining_life_time > 2 * 60 * 60)
390 slaac_address->due_time = current_time + 2 * 60 * 60;
391 continue;
392 }
393
394 if (valid_time == 0)
395 continue;
396
397 due_time = current_time + valid_time;
398
399 ip6_address_t addr;
400 addr.as_u64[0] = dst_address->as_u64[0];
401 /* Invert the "u" bit */
402 addr.as_u8[8] = mac[0] ^ (1 << 1);
403 addr.as_u8[9] = mac[1];
404 addr.as_u8[10] = mac[2];
405 addr.as_u8[11] = 0xFF;
406 addr.as_u8[12] = 0xFE;
407 addr.as_u8[13] = mac[3];
408 addr.as_u8[14] = mac[4];
409 addr.as_u8[15] = mac[5];
410
411 add_slaac_address (vm, sw_if_index, prefix_length, &addr, due_time);
412 }
413
414 interrupt_process ();
Juraj Sloboda52574522018-05-03 10:03:50 +0200415
416 return error;
Juraj Slobodac0374232018-02-01 15:18:49 +0100417}
418
Juraj Sloboda52574522018-05-03 10:03:50 +0200419VNET_IP6_NEIGHBOR_RA_FUNCTION (ip6_ra_report_handler);
420
Juraj Slobodac0374232018-02-01 15:18:49 +0100421static uword
422rd_cp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
423{
Juraj Slobodac0374232018-02-01 15:18:49 +0100424 uword *event_data = 0;
425 rd_cp_main_t *rm = &rd_cp_main;
426 slaac_address_t *slaac_address;
427 default_route_t *default_route;
428 f64 sleep_time = 1e9;
Juraj Slobodac0374232018-02-01 15:18:49 +0100429 f64 current_time;
430 f64 due_time;
431
432 while (1)
433 {
Juraj Sloboda52574522018-05-03 10:03:50 +0200434 vlib_process_wait_for_event_or_clock (vm, sleep_time);
435 vlib_process_get_events (vm, &event_data);
Juraj Slobodac0374232018-02-01 15:18:49 +0100436
437 vec_reset_length (event_data);
438
439 current_time = vlib_time_now (vm);
440 do
441 {
442 due_time = current_time + 1e9;
Benoît Ganne79c9d362019-09-30 10:55:33 +0200443 u32 index;
444 /*
445 * we do not use pool_foreach() to iterate over pool elements here
446 * as we are removing elements inside the loop body
447 */
Juraj Slobodac0374232018-02-01 15:18:49 +0100448 /* *INDENT-OFF* */
Benoît Ganne79c9d362019-09-30 10:55:33 +0200449 pool_foreach_index (index, rm->slaac_address_pool,
Juraj Slobodac0374232018-02-01 15:18:49 +0100450 ({
Benoît Ganne79c9d362019-09-30 10:55:33 +0200451 slaac_address = pool_elt_at_index(rm->slaac_address_pool, index);
Juraj Slobodac0374232018-02-01 15:18:49 +0100452 if (slaac_address->due_time > current_time)
453 {
454 if (slaac_address->due_time < due_time)
455 due_time = slaac_address->due_time;
456 }
457 else
458 {
Benoît Ganne79c9d362019-09-30 10:55:33 +0200459 u32 sw_if_index = slaac_address->sw_if_index;
Juraj Slobodac0374232018-02-01 15:18:49 +0100460 remove_slaac_address (vm, slaac_address);
461 /* make sure ip6 stays enabled */
Benoît Ganne79c9d362019-09-30 10:55:33 +0200462 ip6_enable (sw_if_index);
Juraj Slobodac0374232018-02-01 15:18:49 +0100463 }
464 }));
Benoît Ganne79c9d362019-09-30 10:55:33 +0200465 pool_foreach_index (index, rm->default_route_pool,
Juraj Slobodac0374232018-02-01 15:18:49 +0100466 ({
Benoît Ganne79c9d362019-09-30 10:55:33 +0200467 default_route = pool_elt_at_index(rm->default_route_pool, index);
Juraj Slobodac0374232018-02-01 15:18:49 +0100468 if (default_route->due_time > current_time)
469 {
470 if (default_route->due_time < due_time)
471 due_time = default_route->due_time;
472 }
473 else
474 remove_default_route (vm, default_route);
475 }));
476 /* *INDENT-ON* */
477 current_time = vlib_time_now (vm);
478 }
479 while (due_time < current_time);
480
481 sleep_time = due_time - current_time;
482 }
483
484 return 0;
485}
486
487/* *INDENT-OFF* */
488VLIB_REGISTER_NODE (rd_cp_process_node) = {
489 .function = rd_cp_process,
490 .type = VLIB_NODE_TYPE_PROCESS,
491 .name = "rd-cp-process",
492};
493/* *INDENT-ON* */
494
495static void
496interrupt_process (void)
497{
498 rd_cp_main_t *rm = &rd_cp_main;
499 vlib_main_t *vm = rm->vlib_main;
500
501 vlib_process_signal_event (vm, rd_cp_process_node.index,
502 RD_CP_EVENT_INTERRUPT, 0);
503}
504
505static int
Juraj Slobodac0374232018-02-01 15:18:49 +0100506set_address_autoconfig (u32 sw_if_index, u8 enable, u8 install_default_routes)
507{
508 rd_cp_main_t *rm = &rd_cp_main;
509 vlib_main_t *vm = rm->vlib_main;
510 vnet_main_t *vnm = rm->vnet_main;
511 interface_config_t *if_config;
512 interface_config_t empty_config = { 0, 0 };
513 slaac_address_t *slaac_address;
514 default_route_t *default_route;
515
516 if (!enable)
517 install_default_routes = 0;
518
Juraj Slobodac0374232018-02-01 15:18:49 +0100519 if (!vnet_sw_interface_is_api_valid (vnm, sw_if_index))
520 {
Juraj Slobodac65770d2018-05-15 11:43:56 +0200521 vlib_log_warn (rm->log_class, "Invalid sw_if_index");
Juraj Slobodac0374232018-02-01 15:18:49 +0100522 return 1;
523 }
524
525 if (!rm->enabled)
526 {
Juraj Slobodac0374232018-02-01 15:18:49 +0100527 /* process kickoff */
528 interrupt_process ();
Juraj Slobodac0374232018-02-01 15:18:49 +0100529 rm->enabled = 1;
530 }
531
532 vec_validate_init_empty (rm->config_by_sw_if_index, sw_if_index,
533 empty_config);
534 if_config = &rm->config_by_sw_if_index[sw_if_index];
535
536 if (!if_config->enabled && enable)
537 ip6_enable (sw_if_index);
538
539 if ((!if_config->enabled && enable)
540 || (!if_config->install_default_routes && install_default_routes))
541 router_solicitation_start_stop (sw_if_index, 1);
542 else if (if_config->enabled && !enable)
543 router_solicitation_start_stop (sw_if_index, 0);
544
545 if (if_config->enabled && !enable)
546 {
547 /* *INDENT-OFF* */
548 pool_foreach (slaac_address, rm->slaac_address_pool,
549 ({
550 remove_slaac_address (vm, slaac_address);
551 }));
552 /* *INDENT-ON* */
553 }
554 if (if_config->install_default_routes && !install_default_routes)
555 {
556 /* *INDENT-OFF* */
557 pool_foreach (default_route, rm->default_route_pool,
558 ({
559 remove_default_route (vm, default_route);
560 }));
561 /* *INDENT-ON* */
562 }
563
564 if_config->enabled = enable;
565 if_config->install_default_routes = install_default_routes;
566
567 return 0;
568}
569
570static clib_error_t *
571ip6_nd_address_autoconfig (vlib_main_t * vm,
572 unformat_input_t * input, vlib_cli_command_t * cmd)
573{
574 rd_cp_main_t *rm = &rd_cp_main;
575 vnet_main_t *vnm = rm->vnet_main;
576 clib_error_t *error = 0;
577 u32 sw_if_index = ~0;
578 u8 enable = 1;
579 u8 default_route = 0;
580
581 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
582 {
583 if (unformat
584 (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
585 ;
586 if (unformat (input, "default-route"))
587 default_route = 1;
588 if (unformat (input, "disable"))
589 enable = 0;
590 else
591 break;
592 }
593
594 if (sw_if_index != ~0)
595 {
596 if (set_address_autoconfig (sw_if_index, enable, default_route) != 0)
597 error = clib_error_return (0, "Invalid sw_if_index");
598 }
599 else
600 error = clib_error_return (0, "Missing sw_if_index");
601
602 return error;
603}
604
605/*?
606 * This command is used to enable ND address autoconfiguration
607 * on particular interface including setting up default routes.
608 *
609 * @cliexpar
610 * @parblock
611 * Example of how to enable ND address autoconfiguration:
612 * @cliexcmd{ip6 nd address autoconfig GigabitEthernet2/0/0}
613 * Example of how to enable ND address autoconfiguration
614 * with setting up default routes:
615 * @cliexcmd{ip6 nd address autoconfig GigabitEthernet2/0/0 default-route}
616 * Example of how to disable ND address autoconfiguration:
617 * @cliexcmd{ip6 nd address autoconfig GigabitEthernet2/0/0 disable}
618 * @endparblock
619?*/
620/* *INDENT-OFF* */
621VLIB_CLI_COMMAND (ip6_nd_address_autoconfig_command, static) = {
622 .path = "ip6 nd address autoconfig",
623 .short_help = "ip6 nd address autoconfig <interface> [default-route|disable]",
624 .function = ip6_nd_address_autoconfig,
625};
626/* *INDENT-ON* */
627
628static void
629vl_api_ip6_nd_address_autoconfig_t_handler (vl_api_ip6_nd_address_autoconfig_t
630 * mp)
631{
632 vl_api_ip6_nd_address_autoconfig_reply_t *rmp;
633 u32 sw_if_index;
634 int rv = 0;
635
636 VALIDATE_SW_IF_INDEX (mp);
637
638 sw_if_index = ntohl (mp->sw_if_index);
639
640 rv =
641 set_address_autoconfig (sw_if_index, mp->enable,
642 mp->install_default_routes);
643
644 BAD_SW_IF_INDEX_LABEL;
645
Neale Rannsbe01e632019-10-10 12:59:02 -0700646 REPLY_MACRO (VL_API_IP6_ND_ADDRESS_AUTOCONFIG_REPLY);
Juraj Slobodac0374232018-02-01 15:18:49 +0100647}
648
649#define vl_msg_name_crc_list
650#include <vnet/ip/rd_cp.api.h>
651#undef vl_msg_name_crc_list
652
653static void
654setup_message_id_table (api_main_t * am)
655{
656#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
657 foreach_vl_msg_name_crc_rd_cp;
658#undef _
659}
660
661static clib_error_t *
662rd_cp_init (vlib_main_t * vm)
663{
664 rd_cp_main_t *rm = &rd_cp_main;
Dave Barach39d69112019-11-27 11:42:13 -0500665 api_main_t *am = vlibapi_get_main ();
Juraj Slobodac0374232018-02-01 15:18:49 +0100666
667 rm->vlib_main = vm;
668 rm->vnet_main = vnet_get_main ();
669 rm->api_main = am;
670 rm->node_index = rd_cp_process_node.index;
671
Juraj Slobodac65770d2018-05-15 11:43:56 +0200672 rm->log_class = vlib_log_register_class ("rd_cp", 0);
673
Juraj Slobodac0374232018-02-01 15:18:49 +0100674#define _(N,n) \
675 vl_msg_api_set_handlers(VL_API_##N, #n, \
676 vl_api_##n##_t_handler, \
677 vl_noop_handler, \
678 vl_api_##n##_t_endian, \
679 vl_api_##n##_t_print, \
680 sizeof(vl_api_##n##_t), 0/* do NOT trace! */);
681 foreach_rd_cp_msg;
682#undef _
683
Juraj Slobodac0374232018-02-01 15:18:49 +0100684 /*
685 * Set up the (msg_name, crc, message-id) table
686 */
687 setup_message_id_table (am);
688
689 return 0;
690}
691
692VLIB_INIT_FUNCTION (rd_cp_init);
693
694/*
695 * fd.io coding-style-patch-verification: ON
696 *
697 * Local Variables:
698 * eval: (c-set-style "gnu")
699 * End:
700 */