FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
rd_cp.c
Go to the documentation of this file.
1 /*
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 
16 #include <vnet/ip6-nd/ip6_ra.h>
17 
18 #include <vnet/ip/ip6.h>
19 #include <vnet/ip/ip6_link.h>
20 #include <vnet/ethernet/ethernet.h>
21 #include <vnet/fib/fib_table.h>
22 #include <signal.h>
23 #include <math.h>
24 
25 typedef struct
26 {
32 
33 typedef struct
34 {
39 
40 typedef struct
41 {
45 
46 typedef struct
47 {
50 
54 
55  /* binary API client */
58 
59  /* logging */
61 
62  /* convenience */
66 } rd_cp_main_t;
67 
69 
70 enum
71 {
73 };
74 
75 #define vl_api_ip6_nd_address_autoconfig_t_print vl_noop_handler
76 
77 static void
79 {
80  rd_cp_main_t *rm = &rd_cp_main;
82 
83  if (start)
84  {
85  params.irt = 1;
86  params.mrt = 120;
87  }
88 
89  icmp6_send_router_solicitation (rm->vlib_main, sw_if_index, !start,
90  &params);
91 }
92 
93 static void interrupt_process (void);
94 
95 static int
97  const ip6_address_t * address, f64 due_time)
98 {
99  rd_cp_main_t *rm = &rd_cp_main;
100  slaac_address_t *slaac_address;
101  clib_error_t *rv = 0;
102 
103  pool_get_zero (rm->slaac_address_pool, slaac_address);
104 
105  slaac_address->sw_if_index = sw_if_index;
106  slaac_address->address_length = address_length;
107  slaac_address->address = *address;
108  slaac_address->due_time = due_time;
109 
110  rv =
111  ip6_add_del_interface_address (vm, sw_if_index, &slaac_address->address,
112  address_length, 0);
113 
114  return rv != 0;
115 }
116 
117 static void
119  const ip6_address_t * next_hop_address, f64 due_time)
120 {
121  rd_cp_main_t *rm = &rd_cp_main;
122  default_route_t *default_route;
123 
124  pool_get_zero (rm->default_route_pool, default_route);
125 
126  default_route->sw_if_index = sw_if_index;
127  default_route->router_address = *next_hop_address;
128  default_route->due_time = due_time;
129 
130  {
132  default_route->
133  sw_if_index);
134  fib_prefix_t pfx = {
136  };
137  ip46_address_t nh = {
138  .ip6 = default_route->router_address,
139  };
140  fib_table_entry_update_one_path (fib_index, &pfx,
144  &nh,
145  default_route->sw_if_index,
147  }
148 }
149 
150 static int
152 {
153  rd_cp_main_t *rm = &rd_cp_main;
154  clib_error_t *rv = 0;
155 
156  rv = ip6_add_del_interface_address (vm, slaac_address->sw_if_index,
157  &slaac_address->address,
158  slaac_address->address_length, 1);
159 
160  pool_put (rm->slaac_address_pool, slaac_address);
161 
162  return rv != 0;
163 }
164 
165 static void
167 {
168  rd_cp_main_t *rm = &rd_cp_main;
169 
170  {
172  default_route->
173  sw_if_index);
174  fib_prefix_t pfx = {
176  };
177  ip46_address_t nh = {
178  .ip6 = default_route->router_address,
179  };
180  fib_table_entry_path_remove (fib_index, &pfx,
183  &nh,
184  default_route->sw_if_index,
186  }
187 
188  pool_put (rm->default_route_pool, default_route);
189 }
190 
191 static u32
193 {
194  rd_cp_main_t *rm = &rd_cp_main;
196  ethernet_interface_t *eth_if = 0;
197 
198  if (!vnet_sw_interface_is_api_valid (rm->vnet_main, sw_if_index))
199  {
200  vlib_log_warn (rm->log_class, "Invalid sw_if_index");
201  return 1;
202  }
203 
204  si = vnet_get_sup_sw_interface (rm->vnet_main, sw_if_index);
207 
208  if (!eth_if)
209  {
210  vlib_log_warn (rm->log_class, "Failed to get hardware interface");
211  return 1;
212  }
213 
214  clib_memcpy_fast (mac, eth_if->address, 6);
215 
216  return 0;
217 }
218 
219 static u8
221 {
222  if (len >= 64)
223  {
224  if (prefix1->as_u64[0] != prefix2->as_u64[0])
225  return 0;
226  if (len == 64)
227  return 1;
228  return prefix1->as_u64[1] >> (128 - len) ==
229  prefix2->as_u64[1] >> (128 - len);
230  }
231  return prefix1->as_u64[0] >> (64 - len) == prefix2->as_u64[0] >> (64 - len);
232 }
233 
234 #define PREFIX_FLAG_A (1 << 6)
235 #define PREFIX_FLAG_L (1 << 7)
236 
237 static void
239 {
240  rd_cp_main_t *rm = &rd_cp_main;
241  vlib_main_t *vm = rm->vlib_main;
242  interface_config_t *if_config;
243  default_route_t *default_route;
244  slaac_address_t *slaac_address;
246  u16 router_lifetime_in_sec;
247  u32 n_prefixes;
249  u8 mac[6];
250  f64 current_time;
251  u32 i;
252 
253  current_time = vlib_time_now (vm);
254 
255  sw_if_index = r->sw_if_index;
256 
257  if (sw_if_index >= vec_len (rm->config_by_sw_if_index))
258  return;
259  if_config = &rm->config_by_sw_if_index[sw_if_index];
260 
261  if (if_config->install_default_routes)
262  {
263  router_lifetime_in_sec = r->router_lifetime_in_sec;
264  u8 route_already_present = 0;
265  /* *INDENT-OFF* */
266  pool_foreach (default_route, rm->default_route_pool,
267  ({
268  if (default_route->sw_if_index != sw_if_index)
269  ;
270  else if (0 != memcmp (&default_route->router_address,
271  &r->router_address, 16))
272  ;
273  else
274  {
275  route_already_present = 1;
276  goto default_route_pool_foreach_out;
277  }
278  }));
279  /* *INDENT-ON* */
280  default_route_pool_foreach_out:
281 
282  if (!route_already_present)
283  {
284  if (router_lifetime_in_sec != 0)
285  add_default_route (vm, sw_if_index, &r->router_address,
286  current_time + router_lifetime_in_sec);
287  }
288  else
289  {
290  if (router_lifetime_in_sec != 0)
291  default_route->due_time = current_time + router_lifetime_in_sec;
292  else
293  remove_default_route (vm, default_route);
294  }
295  }
296 
298  {
299  vlib_log_warn (rm->log_class, "Error getting MAC address");
300  return;
301  }
302 
303  if (!if_config->enabled)
304  return;
305 
306  n_prefixes = vec_len (r->prefixes);
307  for (i = 0; i < n_prefixes; i++)
308  {
309  ip6_address_t *dst_address;
310  u8 prefix_length;
311  u32 valid_time;
313  f64 due_time;
314 
315  prefix = &r->prefixes[i];
316 
317  if (!(prefix->flags & PREFIX_FLAG_A))
318  continue;
319 
320  dst_address = &prefix->prefix.fp_addr.ip6;
321  prefix_length = prefix->prefix.fp_len;
322 
323  if (ip6_address_is_link_local_unicast (dst_address))
324  continue;
325 
326  valid_time = prefix->valid_time;
327  preferred_time = prefix->preferred_time;
328 
329  if (preferred_time > valid_time)
330  continue;
331 
332  if (prefix_length != 64)
333  continue;
334 
335  u8 address_already_present = 0;
336  /* *INDENT-OFF* */
337  pool_foreach (slaac_address, rm->slaac_address_pool,
338  ({
339  if (slaac_address->sw_if_index != sw_if_index)
340  ;
341  else if (slaac_address->address_length != prefix_length)
342  ;
343  else if (!ip6_prefixes_equal (&slaac_address->address, dst_address,
344  prefix_length))
345  ;
346  else
347  {
348  address_already_present = 1;
349  goto slaac_address_pool_foreach_out;
350  }
351  }));
352  /* *INDENT-ON* */
353  slaac_address_pool_foreach_out:
354 
355  if (address_already_present)
356  {
357  f64 remaining_life_time = slaac_address->due_time - current_time;
358  if (valid_time > 2 * 60 * 60 || valid_time > remaining_life_time)
359  slaac_address->due_time = current_time + valid_time;
360  else if (remaining_life_time > 2 * 60 * 60)
361  slaac_address->due_time = current_time + 2 * 60 * 60;
362  continue;
363  }
364 
365  if (valid_time == 0)
366  continue;
367 
368  due_time = current_time + valid_time;
369 
371  addr.as_u64[0] = dst_address->as_u64[0];
372  /* Invert the "u" bit */
373  addr.as_u8[8] = mac[0] ^ (1 << 1);
374  addr.as_u8[9] = mac[1];
375  addr.as_u8[10] = mac[2];
376  addr.as_u8[11] = 0xFF;
377  addr.as_u8[12] = 0xFE;
378  addr.as_u8[13] = mac[3];
379  addr.as_u8[14] = mac[4];
380  addr.as_u8[15] = mac[5];
381 
382  add_slaac_address (vm, sw_if_index, prefix_length, &addr, due_time);
383  }
384 
386 
387  return;
388 }
389 
390 static uword
392 {
393  uword *event_data = 0;
394  rd_cp_main_t *rm = &rd_cp_main;
395  slaac_address_t *slaac_address;
396  default_route_t *default_route;
397  f64 sleep_time = 1e9;
398  f64 current_time;
399  f64 due_time;
400 
401  while (1)
402  {
403  vlib_process_wait_for_event_or_clock (vm, sleep_time);
404  vlib_process_get_events (vm, &event_data);
405 
406  vec_reset_length (event_data);
407 
408  current_time = vlib_time_now (vm);
409  do
410  {
411  due_time = current_time + 1e9;
412  u32 index;
413  /*
414  * we do not use pool_foreach() to iterate over pool elements here
415  * as we are removing elements inside the loop body
416  */
417  /* *INDENT-OFF* */
419  ({
420  slaac_address = pool_elt_at_index(rm->slaac_address_pool, index);
421  if (slaac_address->due_time > current_time)
422  {
423  if (slaac_address->due_time < due_time)
424  due_time = slaac_address->due_time;
425  }
426  else
427  {
428  u32 sw_if_index = slaac_address->sw_if_index;
429  remove_slaac_address (vm, slaac_address);
430  /* make sure ip6 stays enabled */
431  ip6_link_enable (sw_if_index);
432  }
433  }));
435  ({
436  default_route = pool_elt_at_index(rm->default_route_pool, index);
437  if (default_route->due_time > current_time)
438  {
439  if (default_route->due_time < due_time)
440  due_time = default_route->due_time;
441  }
442  else
443  remove_default_route (vm, default_route);
444  }));
445  /* *INDENT-ON* */
446  current_time = vlib_time_now (vm);
447  }
448  while (due_time < current_time);
449 
450  sleep_time = due_time - current_time;
451  }
452 
453  return 0;
454 }
455 
456 /* *INDENT-OFF* */
458  .function = rd_cp_process,
459  .type = VLIB_NODE_TYPE_PROCESS,
460  .name = "rd-cp-process",
461 };
462 /* *INDENT-ON* */
463 
464 static void
466 {
467  rd_cp_main_t *rm = &rd_cp_main;
468  vlib_main_t *vm = rm->vlib_main;
469 
472 }
473 
474 int
476  u8 enable, u8 install_default_routes)
477 {
478  rd_cp_main_t *rm = &rd_cp_main;
479  vlib_main_t *vm = rm->vlib_main;
480  vnet_main_t *vnm = rm->vnet_main;
481  interface_config_t *if_config;
482  interface_config_t empty_config = { 0, 0 };
483  slaac_address_t *slaac_address;
484  default_route_t *default_route;
485 
486  if (!enable)
487  install_default_routes = 0;
488 
489  if (!vnet_sw_interface_is_api_valid (vnm, sw_if_index))
490  {
491  vlib_log_warn (rm->log_class, "Invalid sw_if_index");
492  return 1;
493  }
494 
495  if (!rm->enabled)
496  {
497  /* process kickoff */
499  rm->enabled = 1;
500  }
501 
503  empty_config);
504  if_config = &rm->config_by_sw_if_index[sw_if_index];
505 
506  if (!if_config->enabled && enable)
507  ip6_link_enable (sw_if_index);
508 
509  if ((!if_config->enabled && enable)
510  || (!if_config->install_default_routes && install_default_routes))
511  router_solicitation_start_stop (sw_if_index, 1);
512  else if (if_config->enabled && !enable)
513  router_solicitation_start_stop (sw_if_index, 0);
514 
515  if (if_config->enabled && !enable)
516  {
517  /* *INDENT-OFF* */
518  pool_foreach (slaac_address, rm->slaac_address_pool,
519  ({
520  remove_slaac_address (vm, slaac_address);
521  }));
522  /* *INDENT-ON* */
523  }
524  if (if_config->install_default_routes && !install_default_routes)
525  {
526  /* *INDENT-OFF* */
527  pool_foreach (default_route, rm->default_route_pool,
528  ({
529  remove_default_route (vm, default_route);
530  }));
531  /* *INDENT-ON* */
532  }
533 
534  if_config->enabled = enable;
535  if_config->install_default_routes = install_default_routes;
536 
537  return 0;
538 }
539 
540 static clib_error_t *
542  unformat_input_t * input, vlib_cli_command_t * cmd)
543 {
544  rd_cp_main_t *rm = &rd_cp_main;
545  vnet_main_t *vnm = rm->vnet_main;
546  clib_error_t *error = 0;
547  u32 sw_if_index = ~0;
548  u8 enable = 1;
549  u8 default_route = 0;
550 
552  {
553  if (unformat
554  (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
555  ;
556  if (unformat (input, "default-route"))
557  default_route = 1;
558  if (unformat (input, "disable"))
559  enable = 0;
560  else
561  break;
562  }
563 
564  if (sw_if_index != ~0)
565  {
566  if (rd_cp_set_address_autoconfig (sw_if_index, enable, default_route) !=
567  0)
568  error = clib_error_return (0, "Invalid sw_if_index");
569  }
570  else
571  error = clib_error_return (0, "Missing sw_if_index");
572 
573  return error;
574 }
575 
576 /*?
577  * This command is used to enable ND address autoconfiguration
578  * on particular interface including setting up default routes.
579  *
580  * @cliexpar
581  * @parblock
582  * Example of how to enable ND address autoconfiguration:
583  * @cliexcmd{ip6 nd address autoconfig GigabitEthernet2/0/0}
584  * Example of how to enable ND address autoconfiguration
585  * with setting up default routes:
586  * @cliexcmd{ip6 nd address autoconfig GigabitEthernet2/0/0 default-route}
587  * Example of how to disable ND address autoconfiguration:
588  * @cliexcmd{ip6 nd address autoconfig GigabitEthernet2/0/0 disable}
589  * @endparblock
590 ?*/
591 /* *INDENT-OFF* */
592 VLIB_CLI_COMMAND (ip6_nd_address_autoconfig_command, static) = {
593  .path = "ip6 nd address autoconfig",
594  .short_help = "ip6 nd address autoconfig <interface> [default-route|disable]",
595  .function = ip6_nd_address_autoconfig,
596 };
597 /* *INDENT-ON* */
598 
599 static clib_error_t *
601 {
602  rd_cp_main_t *rm = &rd_cp_main;
603 
604  rm->vlib_main = vm;
605  rm->vnet_main = vnet_get_main ();
606  rm->node_index = rd_cp_process_node.index;
607 
608  rm->log_class = vlib_log_register_class ("rd_cp", 0);
609 
611 
612  return (NULL);
613 }
614 
616 
617 /*
618  * fd.io coding-style-patch-verification: ON
619  *
620  * Local Variables:
621  * eval: (c-set-style "gnu")
622  * End:
623  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:176
void ip6_ra_report_register(ip6_ra_report_notify_t fn)
Definition: ip6_ra.c:167
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
#define PREFIX_FLAG_A
Definition: rd_cp.c:234
#define vlib_log_warn(...)
Definition: log.h:103
static u8 ip6_prefixes_equal(ip6_address_t *prefix1, ip6_address_t *prefix2, u8 len)
Definition: rd_cp.c:220
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:673
vl_api_mac_address_t mac
Definition: l2.api:491
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:240
vl_api_fib_path_nh_t nh
Definition: fib_types.api:126
u8 as_u8[16]
Definition: ip6_packet.h:48
u64 as_u64[2]
Definition: ip6_packet.h:51
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
#define NULL
Definition: clib.h:58
u16 router_lifetime_in_sec
Definition: ip6_ra.h:67
slaac_address_t * slaac_address_pool
Definition: rd_cp.c:52
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:279
u32 fib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
Definition: fib_table.c:989
vlib_main_t * vlib_main
Definition: rd_cp.c:63
static void ip6_ra_report_handler(const ip6_ra_report_t *r)
Definition: rd_cp.c:238
ip6_address_t address
Definition: rd_cp.c:29
u8 install_default_routes
Definition: rd_cp.c:43
void icmp6_send_router_solicitation(vlib_main_t *vm, u32 sw_if_index, u8 stop, const icmp6_send_router_solicitation_params_t *params)
Definition: ip6_ra.c:1303
int i
unformat_function_t unformat_vnet_sw_interface
ip6_address_t router_address
Definition: rd_cp.c:36
vl_api_prefix_t prefix
Definition: ip.api:144
vhost_vring_addr_t addr
Definition: vhost_user.h:147
unsigned char u8
Definition: types.h:56
static clib_error_t * rd_cp_init(vlib_main_t *vm)
Definition: rd_cp.c:600
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
fib_node_index_t fib_table_entry_update_one_path(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags)
Update the entry to have just one path.
Definition: fib_table.c:805
ethernet_main_t ethernet_main
Definition: init.c:45
u32 vlib_log_class_t
Definition: vlib.h:51
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:498
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
static int add_slaac_address(vlib_main_t *vm, u32 sw_if_index, u8 address_length, const ip6_address_t *address, f64 due_time)
Definition: rd_cp.c:96
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:516
static vnet_sw_interface_t * vnet_get_sup_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
Aggregate type for a prefix.
Definition: fib_types.h:203
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned int u32
Definition: types.h:88
ip6_address_t router_address
Definition: ip6_ra.h:63
vnet_main_t * vnet_main
Definition: rd_cp.c:64
Definition: fib_entry.h:112
static void remove_default_route(vlib_main_t *vm, default_route_t *default_route)
Definition: rd_cp.c:166
static uword rd_cp_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: rd_cp.c:391
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:934
f64 due_time
Definition: rd_cp.c:37
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:287
u8 events_on
Definition: rd_cp.c:49
vlib_main_t * vm
Definition: in2out_ed.c:1810
u8 address_length
Definition: rd_cp.c:28
u8 len
Definition: ip_types.api:91
vlib_log_class_t log_class
Definition: rd_cp.c:60
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u32 valid_time
Definition: dhcp.api:312
u8 enabled
Definition: rd_cp.c:48
int rd_cp_set_address_autoconfig(u32 sw_if_index, u8 enable, u8 install_default_routes)
Definition: rd_cp.c:475
vlib_node_registration_t rd_cp_process_node
(constructor) VLIB_REGISTER_NODE (rd_cp_process_node)
Definition: rd_cp.c:457
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
interface_config_t * config_by_sw_if_index
Definition: rd_cp.c:51
manual_print typedef address
Definition: ip_types.api:84
rd_cp_main_t rd_cp_main
Definition: rd_cp.c:68
u32 my_client_index
Definition: rd_cp.c:57
default_route_t * default_route_pool
Definition: rd_cp.c:53
From the control plane API.
Definition: fib_source.h:72
static uword ip6_address_is_link_local_unicast(const ip6_address_t *a)
Definition: ip6_packet.h:250
void fib_table_entry_path_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_route_path_flags_t path_flags)
remove one path to an entry (aka route) in the FIB.
Definition: fib_table.c:722
static uword vnet_sw_interface_is_api_valid(vnet_main_t *vnm, u32 sw_if_index)
ethernet_interface_t * ethernet_get_interface(ethernet_main_t *em, u32 hw_if_index)
Definition: interface.c:940
static int remove_slaac_address(vlib_main_t *vm, slaac_address_t *slaac_address)
Definition: rd_cp.c:151
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u64 uword
Definition: types.h:112
static void interrupt_process(void)
Definition: rd_cp.c:465
static void router_solicitation_start_stop(u32 sw_if_index, u8 start)
Definition: rd_cp.c:78
u32 node_index
Definition: rd_cp.c:65
vnet_sw_interface_type_t type
Definition: interface.h:718
static u32 get_interface_mac_address(u32 sw_if_index, u8 mac[])
Definition: rd_cp.c:192
u32 preferred_time
Definition: dhcp.api:313
u32 sw_if_index
Definition: rd_cp.c:35
clib_error_t * ip6_add_del_interface_address(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *address, u32 address_length, u32 is_del)
Definition: ip6_forward.c:290
f64 due_time
Definition: rd_cp.c:30
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:543
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:487
u32 sw_if_index
Definition: rd_cp.c:27
u8 api_connected
Definition: rd_cp.c:56
static clib_error_t * ip6_nd_address_autoconfig(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: rd_cp.c:541
u32 sw_if_index
Definition: ip6_ra.h:64
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
static void add_default_route(vlib_main_t *vm, u32 sw_if_index, const ip6_address_t *next_hop_address, f64 due_time)
Definition: rd_cp.c:118