FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
ip6_ra.c
Go to the documentation of this file.
1 /*
2  * ip/ip6_neighbor.c: IP6 neighbor handling
3  *
4  * Copyright (c) 2010 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vnet/ip6-nd/ip6_ra.h>
19 
20 #include <vnet/ip/ip.h>
22 
23 #include <vnet/fib/ip6_fib.h>
24 #include <vnet/ip/ip6_link.h>
25 
26 /**
27  * @file
28  * @brief IPv6 Router Advertisements.
29  *
30  * The files contains the API and CLI code for managing IPv6 RAs
31  */
32 
33 /* *INDENT-OFF* */
34 /* Router solicitation packet format for ethernet. */
35 typedef CLIB_PACKED (struct
36 {
38  icmp6_neighbor_discovery_header_t neighbor;
39  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t
40  link_layer_option;
41 }) icmp6_router_solicitation_header_t;
42 
43 /* router advertisement packet format for ethernet. */
44 typedef CLIB_PACKED (struct
45 {
47  icmp6_router_advertisement_header_t router;
48  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t
49  link_layer_option;
50  icmp6_neighbor_discovery_mtu_option_t mtu_option;
51  icmp6_neighbor_discovery_prefix_information_option_t
52  prefix[0];
54 /* *INDENT-ON* */
55 
56 #define DEF_MAX_RADV_INTERVAL 200
57 #define DEF_MIN_RADV_INTERVAL .75 * DEF_MAX_RADV_INTERVAL
58 #define DEF_CURR_HOP_LIMIT 64
59 #define DEF_DEF_RTR_LIFETIME 3 * DEF_MAX_RADV_INTERVAL
60 #define MAX_DEF_RTR_LIFETIME 9000
61 
62 #define MAX_INITIAL_RTR_ADVERT_INTERVAL 16 /* seconds */
63 #define MAX_INITIAL_RTR_ADVERTISEMENTS 3 /*transmissions */
64 #define MIN_DELAY_BETWEEN_RAS 3 /* seconds */
65 #define MAX_DELAY_BETWEEN_RAS 1800 /* seconds */
66 #define MAX_RA_DELAY_TIME .5 /* seconds */
67 
68 /* advertised prefix option */
69 typedef struct
70 {
71  /* basic advertised information */
72  ip6_address_t prefix;
78 
79  /* advertised values are computed from these times if decrementing */
82 
83  /* local information */
84  int enabled;
87 
88 #define MIN_ADV_VALID_LIFETIME 7203 /* seconds */
89 #define DEF_ADV_VALID_LIFETIME 2592000
90 #define DEF_ADV_PREF_LIFETIME 604800
91 
92  /* extensions are added here, mobile, DNS etc.. */
94 
95 typedef struct ip6_ra_t_
96 {
97  /* advertised config information, zero means unspecified */
104 
105  /* mtu option */
107 
108  /* local information */
110  int send_radv; /* radv on/off on this interface - set by config */
111  int cease_radv; /* we are ceasing to send - set byf config */
117 
118  /* prefix option */
120 
121  /* Hash table mapping address to index in interface advertised prefix pool. */
123 
129 
133 
134 
138 
139  /* stats */
143 
144  /* router solicitations sending state */
145  u8 keep_sending_rs; /* when true then next fields are valid */
152 
154 
155 } ip6_ra_t;
156 
159 
160 
161 /* vector of registered RA report listeners */
163 
164 static int ip6_ra_publish (ip6_ra_report_t * r);
165 
166 void
168 {
170  vec_foreach (listener, ip6_ra_listeners)
171  {
172  if (*listener == fn)
173  return;
174  }
175 
176  vec_add1 (ip6_ra_listeners, fn);
177 }
178 
179 void
181 {
182  u32 ii;
183 
184  vec_foreach_index (ii, ip6_ra_listeners)
185  {
186  if (ip6_ra_listeners[ii] == fn)
187  {
188  vec_del1 (ip6_ra_listeners, ii);
189  break;
190  }
191  }
192 }
193 
194 static inline ip6_ra_t *
196 {
197  index_t rai;
198 
199  rai = ip6_link_delegate_get (sw_if_index, ip6_ra_delegate_id);
200 
201  if (INDEX_INVALID != rai)
202  return (pool_elt_at_index (ip6_ra_pool, rai));
203 
204  return (NULL);
205 }
206 
207 /* for "syslogging" - use elog for now */
208 #define foreach_log_level \
209  _ (DEBUG, "DEBUG") \
210  _ (INFO, "INFORMATION") \
211  _ (NOTICE, "NOTICE") \
212  _ (WARNING, "WARNING") \
213  _ (ERR, "ERROR") \
214  _ (CRIT, "CRITICAL") \
215  _ (ALERT, "ALERT") \
216  _ (EMERG, "EMERGENCY")
217 
218 typedef enum
219 {
220 #define _(f,s) LOG_##f,
222 #undef _
223 } log_level_t;
224 
225 static char *log_level_strings[] = {
226 #define _(f,s) s,
228 #undef _
229 };
230 
231 static int logmask = 1 << LOG_DEBUG;
232 
233 static void
234 ip6_neighbor_syslog (vlib_main_t * vm, int priority, char *fmt, ...)
235 {
236  /* just use elog for now */
237  u8 *what;
238  va_list va;
239 
240  if ((priority > LOG_EMERG) || !(logmask & (1 << priority)))
241  return;
242 
243  va_start (va, fmt);
244  if (fmt)
245  {
246  what = va_format (0, fmt, &va);
247 
248  ELOG_TYPE_DECLARE (e) =
249  {
250  .format = "ip6 nd: (%s): %s",.format_args = "T4T4",};
251  struct
252  {
253  u32 s[2];
254  } *ed;
255  ed = ELOG_DATA (&vm->elog_main, e);
256  ed->s[0] = elog_string (&vm->elog_main, log_level_strings[priority]);
257  ed->s[1] = elog_string (&vm->elog_main, (char *) what);
258  }
259  va_end (va);
260  return;
261 }
262 
263 /* ipv6 neighbor discovery - router advertisements */
264 typedef enum
265 {
271 
275 {
276  vnet_main_t *vnm = vnet_get_main ();
277  ip6_main_t *im = &ip6_main;
278  uword n_packets = frame->n_vectors;
279  u32 *from, *to_next;
280  u32 n_left_from, n_left_to_next, next_index;
282  int bogus_length;
283 
285 
286  vlib_node_runtime_t *error_node =
288 
289  from = vlib_frame_vector_args (frame);
290  n_left_from = n_packets;
291  next_index = node->cached_next_index;
292 
293  if (node->flags & VLIB_NODE_FLAG_TRACE)
294  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
295  /* stride */ 1,
296  sizeof (icmp6_input_trace_t));
297 
298  /* source may append his LL address */
299  option_type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address;
300 
301  while (n_left_from > 0)
302  {
303  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
304 
305  while (n_left_from > 0 && n_left_to_next > 0)
306  {
307  vlib_buffer_t *p0;
308  ip6_header_t *ip0;
309  ip6_ra_t *radv_info = NULL;
310 
311  icmp6_neighbor_discovery_header_t *h0;
312  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *o0;
313 
314  u32 bi0, options_len0, sw_if_index0, next0, error0;
315  u32 is_solicitation = 1, is_dropped = 0;
316  u32 is_unspecified, is_link_local;
317 
318  bi0 = to_next[0] = from[0];
319 
320  from += 1;
321  to_next += 1;
322  n_left_from -= 1;
323  n_left_to_next -= 1;
324 
325  p0 = vlib_get_buffer (vm, bi0);
326  ip0 = vlib_buffer_get_current (p0);
327  h0 = ip6_next_header (ip0);
328  options_len0 =
329  clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]);
330  is_unspecified = ip6_address_is_unspecified (&ip0->src_address);
331  is_link_local =
333 
334  error0 = ICMP6_ERROR_NONE;
335  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
336 
337  /* check if solicitation (not from nd_timer node) */
339  is_solicitation = 0;
340 
341  /* Check that source address is unspecified, link-local or else on-link. */
342  if (!is_unspecified && !is_link_local)
343  {
344  u32 src_adj_index0 = ip6_src_lookup_for_packet (im, p0, ip0);
345 
346  if (ADJ_INDEX_INVALID != src_adj_index0)
347  {
348  ip_adjacency_t *adj0 = adj_get (src_adj_index0);
349 
350  error0 = (adj0->rewrite_header.sw_if_index != sw_if_index0
351  ?
352  ICMP6_ERROR_ROUTER_SOLICITATION_SOURCE_NOT_ON_LINK
353  : error0);
354  }
355  else
356  {
357  error0 = ICMP6_ERROR_ROUTER_SOLICITATION_SOURCE_NOT_ON_LINK;
358  }
359  }
360 
361  /* check for source LL option and process */
362  o0 = (void *) (h0 + 1);
363  o0 = ((options_len0 == 8
364  && o0->header.type == option_type
365  && o0->header.n_data_u64s == 1) ? o0 : 0);
366 
367  /* if src address unspecified IGNORE any options */
368  if (PREDICT_TRUE (error0 == ICMP6_ERROR_NONE && o0 != 0 &&
369  !is_unspecified && !is_link_local))
370  {
371  ip_neighbor_learn_t learn = {
372  .type = IP46_TYPE_IP6,
373  .sw_if_index = sw_if_index0,
374  .ip.ip6 = ip0->src_address,
375  };
376  memcpy (&learn.mac, o0->ethernet_address, sizeof (learn.mac));
377  ip_neighbor_learn_dp (&learn);
378  }
379 
380  /* default is to drop */
382 
383  if (error0 == ICMP6_ERROR_NONE)
384  {
385  vnet_sw_interface_t *sw_if0;
386  ethernet_interface_t *eth_if0;
387  u32 adj_index0;
388 
389  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index0);
391  eth_if0 =
393 
394  /* only support ethernet interface type for now */
395  error0 =
396  (!eth_if0) ? ICMP6_ERROR_ROUTER_SOLICITATION_UNSUPPORTED_INTF
397  : error0;
398 
399  if (error0 == ICMP6_ERROR_NONE)
400  {
401  /* adjust the sizeof the buffer to just include the ipv6 header */
402  p0->current_length -=
403  (options_len0 +
404  sizeof (icmp6_neighbor_discovery_header_t));
405 
406  radv_info = ip6_ra_get_itf (sw_if_index0);
407 
408  error0 = ((!radv_info) ?
409  ICMP6_ERROR_ROUTER_SOLICITATION_RADV_NOT_CONFIG :
410  error0);
411 
412  if (error0 == ICMP6_ERROR_NONE)
413  {
414  f64 now = vlib_time_now (vm);
415 
416  /* for solicited adverts - need to rate limit */
417  if (is_solicitation)
418  {
419  if (0 != radv_info->last_radv_time &&
420  (now - radv_info->last_radv_time) <
422  is_dropped = 1;
423  else
424  radv_info->last_radv_time = now;
425  }
426 
427  /* send now */
428  icmp6_router_advertisement_header_t rh;
429 
430  rh.icmp.type = ICMP6_router_advertisement;
431  rh.icmp.code = 0;
432  rh.icmp.checksum = 0;
433 
434  rh.current_hop_limit = radv_info->curr_hop_limit;
435  rh.router_lifetime_in_sec =
436  clib_host_to_net_u16
437  (radv_info->adv_router_lifetime_in_sec);
438  rh.
439  time_in_msec_between_retransmitted_neighbor_solicitations
440  =
441  clib_host_to_net_u32 (radv_info->
443  rh.neighbor_reachable_time_in_msec =
444  clib_host_to_net_u32 (radv_info->
446 
447  rh.flags =
448  (radv_info->adv_managed_flag) ?
450  0;
451  rh.flags |=
452  ((radv_info->adv_other_flag) ?
454  0);
455 
456 
457  u16 payload_length =
458  sizeof (icmp6_router_advertisement_header_t);
459 
461  (vm, &bi0, (void *) &rh,
462  sizeof (icmp6_router_advertisement_header_t)))
463  {
464  /* buffer allocation failed, drop the pkt */
465  error0 = ICMP6_ERROR_ALLOC_FAILURE;
466  goto drop0;
467  }
468 
469  if (radv_info->adv_link_layer_address)
470  {
471  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t
472  h;
473 
474  h.header.type =
475  ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address;
476  h.header.n_data_u64s = 1;
477 
478  /* copy ll address */
479  clib_memcpy (&h.ethernet_address[0],
480  eth_if0->address, 6);
481 
483  (vm, &bi0, (void *) &h,
484  sizeof
485  (icmp6_neighbor_discovery_ethernet_link_layer_address_option_t)))
486  {
487  error0 = ICMP6_ERROR_ALLOC_FAILURE;
488  goto drop0;
489  }
490 
491  payload_length +=
492  sizeof
493  (icmp6_neighbor_discovery_ethernet_link_layer_address_option_t);
494  }
495 
496  /* add MTU option */
497  if (radv_info->adv_link_mtu)
498  {
499  icmp6_neighbor_discovery_mtu_option_t h;
500 
501  h.unused = 0;
502  h.mtu =
503  clib_host_to_net_u32 (radv_info->adv_link_mtu);
504  h.header.type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_mtu;
505  h.header.n_data_u64s = 1;
506 
507  payload_length +=
508  sizeof (icmp6_neighbor_discovery_mtu_option_t);
509 
511  (vm, &bi0, (void *) &h,
512  sizeof
513  (icmp6_neighbor_discovery_mtu_option_t)))
514  {
515  error0 = ICMP6_ERROR_ALLOC_FAILURE;
516  goto drop0;
517  }
518  }
519 
520  /* add advertised prefix options */
521  ip6_radv_prefix_t *pr_info;
522 
523  /* *INDENT-OFF* */
524  pool_foreach (pr_info, radv_info->adv_prefixes_pool,
525  ({
526  if(pr_info->enabled &&
527  (!pr_info->decrement_lifetime_flag
528  || (pr_info->pref_lifetime_expires >0)))
529  {
530  /* advertise this prefix */
531  icmp6_neighbor_discovery_prefix_information_option_t h;
532 
533  h.header.type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_prefix_information;
534  h.header.n_data_u64s = (sizeof(icmp6_neighbor_discovery_prefix_information_option_t) >> 3);
535 
536  h.dst_address_length = pr_info->prefix_len;
537 
538  h.flags = (pr_info->adv_on_link_flag) ? ICMP6_NEIGHBOR_DISCOVERY_PREFIX_INFORMATION_FLAG_ON_LINK : 0;
539  h.flags |= (pr_info->adv_autonomous_flag) ? ICMP6_NEIGHBOR_DISCOVERY_PREFIX_INFORMATION_AUTO : 0;
540 
541  if(radv_info->cease_radv && pr_info->deprecated_prefix_flag)
542  {
543  h.valid_time = clib_host_to_net_u32(MIN_ADV_VALID_LIFETIME);
544  h.preferred_time = 0;
545  }
546  else
547  {
548  if(pr_info->decrement_lifetime_flag)
549  {
550  pr_info->adv_valid_lifetime_in_secs = ((pr_info->valid_lifetime_expires > now)) ?
551  (pr_info->valid_lifetime_expires - now) : 0;
552 
553  pr_info->adv_pref_lifetime_in_secs = ((pr_info->pref_lifetime_expires > now)) ?
554  (pr_info->pref_lifetime_expires - now) : 0;
555  }
556 
557  h.valid_time = clib_host_to_net_u32(pr_info->adv_valid_lifetime_in_secs);
558  h.preferred_time = clib_host_to_net_u32(pr_info->adv_pref_lifetime_in_secs) ;
559  }
560  h.unused = 0;
561 
562  /* Handy for debugging, but too noisy... */
563  if (0 && CLIB_DEBUG > 0)
564  clib_warning
565  ("send RA for prefix %U/%d "
566  "sw_if_index %d valid %u preferred %u",
567  format_ip6_address, &pr_info->prefix,
568  pr_info->prefix_len, sw_if_index0,
569  clib_net_to_host_u32 (h.valid_time),
570  clib_net_to_host_u32 (h.preferred_time));
571 
572  if (h.valid_time == 0)
573  clib_warning ("BUG: send RA with valid_time 0");
574 
575  clib_memcpy(&h.dst_address, &pr_info->prefix, sizeof(ip6_address_t));
576 
577  payload_length += sizeof( icmp6_neighbor_discovery_prefix_information_option_t);
578 
579  if (vlib_buffer_add_data
580  (vm, &bi0, (void *)&h,
581  sizeof(icmp6_neighbor_discovery_prefix_information_option_t)))
582  {
583  error0 = ICMP6_ERROR_ALLOC_FAILURE;
584  goto drop0;
585  }
586 
587  }
588  }));
589  /* *INDENT-ON* */
590 
591  /* add additional options before here */
592 
593  /* finish building the router advertisement... */
594  if (!is_unspecified && radv_info->send_unicast)
595  {
596  ip0->dst_address = ip0->src_address;
597  }
598  else
599  {
600  /* target address is all-nodes mcast addr */
602  (&ip0->dst_address,
603  IP6_MULTICAST_SCOPE_link_local,
604  IP6_MULTICAST_GROUP_ID_all_hosts);
605  }
606 
607  /* source address MUST be the link-local address */
610  (radv_info->sw_if_index));
611 
612  ip0->hop_limit = 255;
613  ip0->payload_length =
614  clib_host_to_net_u16 (payload_length);
615 
616  icmp6_router_advertisement_header_t *rh0 =
617  (icmp6_router_advertisement_header_t *) (ip0 + 1);
618  rh0->icmp.checksum =
620  &bogus_length);
621  ASSERT (bogus_length == 0);
622 
623  /* setup output if and adjacency */
624  vnet_buffer (p0)->sw_if_index[VLIB_RX] =
626 
627  if (is_solicitation)
628  {
629  ethernet_header_t *eth0;
630  /* Reuse current MAC header, copy SMAC to DMAC and
631  * interface MAC to SMAC */
632  vlib_buffer_reset (p0);
633  eth0 = vlib_buffer_get_current (p0);
634  clib_memcpy (eth0->dst_address, eth0->src_address,
635  6);
636  clib_memcpy (eth0->src_address, eth_if0->address,
637  6);
638  next0 =
639  is_dropped ? next0 :
641  vnet_buffer (p0)->sw_if_index[VLIB_TX] =
642  sw_if_index0;
643  }
644  else
645  {
646  adj_index0 = ip6_link_get_mcast_adj (sw_if_index0);
647  if (adj_index0 == INDEX_INVALID)
648  error0 = ICMP6_ERROR_DST_LOOKUP_MISS;
649  else
650  {
651  next0 =
652  is_dropped ? next0 :
654  vnet_buffer (p0)->ip.adj_index[VLIB_TX] =
655  adj_index0;
656  }
657  }
658  p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
659 
660  radv_info->n_solicitations_dropped += is_dropped;
661  radv_info->n_solicitations_rcvd += is_solicitation;
662 
663  if ((error0 == ICMP6_ERROR_NONE) && !is_dropped)
664  {
665  radv_info->n_advertisements_sent++;
666  n_advertisements_sent++;
667  }
668  }
669  }
670  }
671 
672  drop0:
673  p0->error = error_node->errors[error0];
674 
675  if (error0 != ICMP6_ERROR_NONE)
676  vlib_error_count (vm, error_node->node_index, error0, 1);
677 
678  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
679  to_next, n_left_to_next,
680  bi0, next0);
681 
682  }
683 
684  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
685  }
686 
687  /* Account for router advertisements sent. */
688  vlib_error_count (vm, error_node->node_index,
689  ICMP6_ERROR_ROUTER_ADVERTISEMENTS_TX,
691 
692  return frame->n_vectors;
693 }
694 
695 /* *INDENT-OFF* */
697 {
698  .function = icmp6_router_solicitation,
699  .name = "icmp6-router-solicitation",
700 
701  .vector_size = sizeof (u32),
702 
703  .format_trace = format_icmp6_input_trace,
704 
705  .n_next_nodes = ICMP6_ROUTER_SOLICITATION_N_NEXT,
706  .next_nodes = {
708  [ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_RW] = "ip6-rewrite-mcast",
709  [ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_TX] = "interface-output",
710  },
711 };
712 /* *INDENT-ON* */
713 
714  /* validate advertised info for consistancy (see RFC-4861 section 6.2.7) - log any inconsistencies, packet will always be dropped */
718 {
719  vnet_main_t *vnm = vnet_get_main ();
720  uword n_packets = frame->n_vectors;
721  u32 *from, *to_next;
722  u32 n_left_from, n_left_to_next, next_index;
723  u32 n_advertisements_rcvd = 0;
724 
725  vlib_node_runtime_t *error_node =
727 
728  from = vlib_frame_vector_args (frame);
729  n_left_from = n_packets;
730  next_index = node->cached_next_index;
731 
732  if (node->flags & VLIB_NODE_FLAG_TRACE)
733  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
734  /* stride */ 1,
735  sizeof (icmp6_input_trace_t));
736 
737  while (n_left_from > 0)
738  {
739  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
740 
741  while (n_left_from > 0 && n_left_to_next > 0)
742  {
743  vlib_buffer_t *p0;
744  ip6_header_t *ip0;
745  ip6_ra_t *radv_info = 0;
746  icmp6_router_advertisement_header_t *h0;
747  u32 bi0, options_len0, sw_if_index0, next0, error0;
748 
749  bi0 = to_next[0] = from[0];
750 
751  from += 1;
752  to_next += 1;
753  n_left_from -= 1;
754  n_left_to_next -= 1;
755 
756  p0 = vlib_get_buffer (vm, bi0);
757  ip0 = vlib_buffer_get_current (p0);
758  h0 = ip6_next_header (ip0);
759  options_len0 =
760  clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]);
761 
762  error0 = ICMP6_ERROR_NONE;
763  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
764 
765  /* Check that source address is link-local */
766  error0 = (!ip6_address_is_link_local_unicast (&ip0->src_address)) ?
767  ICMP6_ERROR_ROUTER_ADVERTISEMENT_SOURCE_NOT_LINK_LOCAL : error0;
768 
769  /* default is to drop */
771 
772  n_advertisements_rcvd++;
773 
774  if (error0 == ICMP6_ERROR_NONE)
775  {
776  vnet_sw_interface_t *sw_if0;
777  ethernet_interface_t *eth_if0;
778 
779  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index0);
781  eth_if0 =
783 
784  /* only support ethernet interface type for now */
785  error0 =
786  (!eth_if0) ? ICMP6_ERROR_ROUTER_SOLICITATION_UNSUPPORTED_INTF
787  : error0;
788 
789  if (error0 == ICMP6_ERROR_NONE)
790  {
791  /* look up the radv_t information for this interface */
792  radv_info = ip6_ra_get_itf (sw_if_index0);
793 
794  error0 = ((!radv_info) ?
795  ICMP6_ERROR_ROUTER_SOLICITATION_RADV_NOT_CONFIG :
796  error0);
797 
798  if (error0 == ICMP6_ERROR_NONE)
799  {
800  radv_info->keep_sending_rs = 0;
801 
802  ip6_ra_report_t r;
803 
804  r.sw_if_index = sw_if_index0;
805  memcpy (&r.router_address, &ip0->src_address, 16);
806  r.current_hop_limit = h0->current_hop_limit;
807  r.flags = h0->flags;
809  clib_net_to_host_u16 (h0->router_lifetime_in_sec);
811  clib_net_to_host_u32
812  (h0->neighbor_reachable_time_in_msec);
813  r.time_in_msec_between_retransmitted_neighbor_solicitations = clib_net_to_host_u32 (h0->time_in_msec_between_retransmitted_neighbor_solicitations);
814  r.prefixes = 0;
815 
816  /* validate advertised information */
817  if ((h0->current_hop_limit && radv_info->curr_hop_limit)
818  && (h0->current_hop_limit !=
819  radv_info->curr_hop_limit))
820  {
821  ip6_neighbor_syslog (vm, LOG_WARNING,
822  "our AdvCurHopLimit on %U doesn't agree with %U",
824  vnm, sw_if_index0,
826  &ip0->src_address);
827  }
828 
829  if ((h0->flags &
831  != radv_info->adv_managed_flag)
832  {
833  ip6_neighbor_syslog (vm, LOG_WARNING,
834  "our AdvManagedFlag on %U doesn't agree with %U",
836  vnm, sw_if_index0,
838  &ip0->src_address);
839  }
840 
841  if ((h0->flags &
843  != radv_info->adv_other_flag)
844  {
845  ip6_neighbor_syslog (vm, LOG_WARNING,
846  "our AdvOtherConfigFlag on %U doesn't agree with %U",
848  vnm, sw_if_index0,
850  &ip0->src_address);
851  }
852 
853  if ((h0->
854  time_in_msec_between_retransmitted_neighbor_solicitations
855  && radv_info->
857  && (h0->
858  time_in_msec_between_retransmitted_neighbor_solicitations
859  !=
860  clib_host_to_net_u32 (radv_info->
862  {
863  ip6_neighbor_syslog (vm, LOG_WARNING,
864  "our AdvRetransTimer on %U doesn't agree with %U",
866  vnm, sw_if_index0,
868  &ip0->src_address);
869  }
870 
871  if ((h0->neighbor_reachable_time_in_msec &&
873  (h0->neighbor_reachable_time_in_msec !=
874  clib_host_to_net_u32
876  {
877  ip6_neighbor_syslog (vm, LOG_WARNING,
878  "our AdvReachableTime on %U doesn't agree with %U",
880  vnm, sw_if_index0,
882  &ip0->src_address);
883  }
884 
885  /* check for MTU or prefix options or .. */
886  u8 *opt_hdr = (u8 *) (h0 + 1);
887  while (options_len0 > 0)
888  {
889  icmp6_neighbor_discovery_option_header_t *o0 =
890  (icmp6_neighbor_discovery_option_header_t *)
891  opt_hdr;
892  int opt_len = o0->n_data_u64s << 3;
894  o0->type;
895 
896  if (options_len0 < 2)
897  {
898  ip6_neighbor_syslog (vm, LOG_ERR,
899  "malformed RA packet on %U from %U",
901  vnm, sw_if_index0,
903  &ip0->src_address);
904  break;
905  }
906 
907  if (opt_len == 0)
908  {
909  ip6_neighbor_syslog (vm, LOG_ERR,
910  " zero length option in RA on %U from %U",
912  vnm, sw_if_index0,
914  &ip0->src_address);
915  break;
916  }
917  else if (opt_len > options_len0)
918  {
919  ip6_neighbor_syslog (vm, LOG_ERR,
920  "option length in RA packet greater than total length on %U from %U",
922  vnm, sw_if_index0,
924  &ip0->src_address);
925  break;
926  }
927 
928  options_len0 -= opt_len;
929  opt_hdr += opt_len;
930 
931  switch (option_type)
932  {
933  case ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address:
934  {
935  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t
936  * h =
937  (icmp6_neighbor_discovery_ethernet_link_layer_address_option_t
938  *) (o0);
939 
940  if (opt_len < sizeof (*h))
941  break;
942 
943  memcpy (r.slla, h->ethernet_address, 6);
944  }
945  break;
946 
947  case ICMP6_NEIGHBOR_DISCOVERY_OPTION_mtu:
948  {
949  icmp6_neighbor_discovery_mtu_option_t *h =
950  (icmp6_neighbor_discovery_mtu_option_t
951  *) (o0);
952 
953  if (opt_len < sizeof (*h))
954  break;
955 
956  r.mtu = clib_net_to_host_u32 (h->mtu);
957 
958  if ((h->mtu && radv_info->adv_link_mtu) &&
959  (h->mtu !=
960  clib_host_to_net_u32
961  (radv_info->adv_link_mtu)))
962  {
963  ip6_neighbor_syslog (vm, LOG_WARNING,
964  "our AdvLinkMTU on %U doesn't agree with %U",
966  vnm, sw_if_index0,
968  &ip0->src_address);
969  }
970  }
971  break;
972 
973  case ICMP6_NEIGHBOR_DISCOVERY_OPTION_prefix_information:
974  {
975  icmp6_neighbor_discovery_prefix_information_option_t
976  * h =
977  (icmp6_neighbor_discovery_prefix_information_option_t
978  *) (o0);
979 
980  /* validate advertised prefix options */
981  ip6_radv_prefix_t *pr_info;
982  u32 preferred, valid;
983 
984  if (opt_len < sizeof (*h))
985  break;
986 
988  vec_len (r.prefixes));
991  vec_len (r.prefixes) - 1);
992 
993  preferred =
994  clib_net_to_host_u32 (h->preferred_time);
995  valid = clib_net_to_host_u32 (h->valid_time);
996 
997  prefix->preferred_time = preferred;
998  prefix->valid_time = valid;
999  prefix->flags = h->flags & 0xc0;
1000  prefix->prefix.fp_len = h->dst_address_length;
1001  prefix->prefix.fp_addr.ip6 = h->dst_address;
1002  prefix->prefix.fp_proto = FIB_PROTOCOL_IP6;
1003 
1004  /* look for matching prefix - if we our advertising it, it better be consistant */
1005  /* *INDENT-OFF* */
1006  pool_foreach (pr_info, radv_info->adv_prefixes_pool,
1007  ({
1008 
1009  ip6_address_t mask;
1010  ip6_address_mask_from_width(&mask, pr_info->prefix_len);
1011 
1012  if(pr_info->enabled &&
1013  (pr_info->prefix_len == h->dst_address_length) &&
1014  ip6_address_is_equal_masked (&pr_info->prefix, &h->dst_address, &mask))
1015  {
1016  /* found it */
1017  if(!pr_info->decrement_lifetime_flag &&
1018  valid != pr_info->adv_valid_lifetime_in_secs)
1019  {
1020  ip6_neighbor_syslog(vm, LOG_WARNING,
1021  "our ADV validlifetime on %U for %U does not agree with %U",
1022  format_vnet_sw_if_index_name, vnm, sw_if_index0,format_ip6_address, &pr_info->prefix,
1023  format_ip6_address, &h->dst_address);
1024  }
1025  if(!pr_info->decrement_lifetime_flag &&
1026  preferred != pr_info->adv_pref_lifetime_in_secs)
1027  {
1028  ip6_neighbor_syslog(vm, LOG_WARNING,
1029  "our ADV preferredlifetime on %U for %U does not agree with %U",
1030  format_vnet_sw_if_index_name, vnm, sw_if_index0,format_ip6_address, &pr_info->prefix,
1031  format_ip6_address, &h->dst_address);
1032  }
1033  }
1034  break;
1035  }));
1036  /* *INDENT-ON* */
1037  break;
1038  }
1039  default:
1040  /* skip this one */
1041  break;
1042  }
1043  }
1044  ip6_ra_publish (&r);
1045  }
1046  }
1047  }
1048 
1049  p0->error = error_node->errors[error0];
1050 
1051  if (error0 != ICMP6_ERROR_NONE)
1052  vlib_error_count (vm, error_node->node_index, error0, 1);
1053 
1054  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1055  to_next, n_left_to_next,
1056  bi0, next0);
1057  }
1058 
1059  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1060  }
1061 
1062  /* Account for router advertisements received. */
1063  vlib_error_count (vm, error_node->node_index,
1064  ICMP6_ERROR_ROUTER_ADVERTISEMENTS_RX,
1065  n_advertisements_rcvd);
1066 
1067  return frame->n_vectors;
1068 }
1069 
1070 /* *INDENT-OFF* */
1072 {
1073  .function = icmp6_router_advertisement,
1074  .name = "icmp6-router-advertisement",
1075 
1076  .vector_size = sizeof (u32),
1077 
1078  .format_trace = format_icmp6_input_trace,
1079 
1080  .n_next_nodes = 1,
1081  .next_nodes = {
1082  [0] = "ip6-drop",
1083  },
1084 };
1085 /* *INDENT-ON* */
1086 
1087 static inline f64
1089 {
1090  static u32 seed = 0;
1091  static u8 seed_set = 0;
1092  if (!seed_set)
1093  {
1094  seed = random_default_seed ();
1095  seed_set = 1;
1096  }
1097  return random_f64 (&seed) * (to - from) + from;
1098 }
1099 
1100 static inline u8
1102 {
1103  vnet_main_t *vnm = vnet_get_main ();
1104  vnet_hw_interface_t *hw_if = vnet_get_sup_hw_interface (vnm, sw_if_index);
1105  if (!hw_if->hw_address)
1106  return 1;
1107  clib_memcpy (address, hw_if->hw_address, 6);
1108  return 0;
1109 }
1110 
1111 static inline vlib_buffer_t *
1113 {
1114  u32 bi0;
1115  vlib_buffer_t *p0;
1116  icmp6_router_solicitation_header_t *rh;
1117  u16 payload_length;
1118  int bogus_length;
1119  u32 sw_if_index;
1120 
1121  sw_if_index = radv_info->sw_if_index;
1122 
1123  if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1124  {
1125  clib_warning ("buffer allocation failure");
1126  return 0;
1127  }
1128 
1129  p0 = vlib_get_buffer (vm, bi0);
1131  p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
1132 
1133  vnet_buffer (p0)->sw_if_index[VLIB_RX] = sw_if_index;
1134  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index;
1135 
1136  vnet_buffer (p0)->ip.adj_index[VLIB_TX] =
1137  ip6_link_get_mcast_adj (sw_if_index);
1138 
1139  rh = vlib_buffer_get_current (p0);
1140  p0->current_length = sizeof (*rh);
1141 
1142  rh->neighbor.icmp.type = ICMP6_router_solicitation;
1143  rh->neighbor.icmp.code = 0;
1144  rh->neighbor.icmp.checksum = 0;
1145  rh->neighbor.reserved_must_be_zero = 0;
1146 
1147  rh->link_layer_option.header.type =
1148  ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address;
1149  if (0 != get_mac_address (sw_if_index,
1150  rh->link_layer_option.ethernet_address))
1151  {
1152  clib_warning ("interface with sw_if_index %u has no mac address",
1153  sw_if_index);
1154  vlib_buffer_free (vm, &bi0, 1);
1155  return 0;
1156  }
1157  rh->link_layer_option.header.n_data_u64s = 1;
1158 
1159  payload_length = sizeof (rh->neighbor) + sizeof (u64);
1160 
1161  rh->ip.ip_version_traffic_class_and_flow_label =
1162  clib_host_to_net_u32 (0x6 << 28);
1163  rh->ip.payload_length = clib_host_to_net_u16 (payload_length);
1164  rh->ip.protocol = IP_PROTOCOL_ICMP6;
1165  rh->ip.hop_limit = 255;
1166  ip6_address_copy (&rh->ip.src_address,
1168  /* set address ff02::2 */
1169  rh->ip.dst_address.as_u64[0] = clib_host_to_net_u64 (0xff02ULL << 48);
1170  rh->ip.dst_address.as_u64[1] = clib_host_to_net_u64 (2);
1171 
1172  rh->neighbor.icmp.checksum = ip6_tcp_udp_icmp_compute_checksum (vm, p0,
1173  &rh->ip,
1174  &bogus_length);
1175 
1176  return p0;
1177 }
1178 
1179 static inline void
1181 {
1182  u32 bi0;
1183 
1184  ra->keep_sending_rs = 0;
1185  if (ra->buffer)
1186  {
1187  bi0 = vlib_get_buffer_index (vm, ra->buffer);
1188  vlib_buffer_free (vm, &bi0, 1);
1189  ra->buffer = 0;
1190  }
1191 }
1192 
1193 static inline bool
1194 check_send_rs (vlib_main_t * vm, ip6_ra_t * radv_info, f64 current_time,
1195  f64 * due_time)
1196 {
1197  vlib_buffer_t *p0;
1198  vlib_frame_t *f;
1199  u32 *to_next;
1200  u32 next_index;
1201  vlib_buffer_t *c0;
1202  u32 ci0;
1203 
1205 
1206  if (!radv_info->keep_sending_rs)
1207  return false;
1208 
1209  params = &radv_info->params;
1210 
1211  if (radv_info->due_time > current_time)
1212  {
1213  *due_time = radv_info->due_time;
1214  return true;
1215  }
1216 
1217  p0 = radv_info->buffer;
1218 
1219  next_index = ip6_rewrite_mcast_node.index;
1220 
1221  c0 = vlib_buffer_copy (vm, p0);
1222  if (c0 == NULL)
1223  return radv_info->keep_sending_rs;
1224 
1225  ci0 = vlib_get_buffer_index (vm, c0);
1226 
1227  f = vlib_get_frame_to_node (vm, next_index);
1228  to_next = vlib_frame_vector_args (f);
1229  to_next[0] = ci0;
1230  f->n_vectors = 1;
1231  vlib_put_frame_to_node (vm, next_index, f);
1232 
1233  if (params->mrc != 0 && --radv_info->n_left == 0)
1234  stop_sending_rs (vm, radv_info);
1235  else
1236  {
1237  radv_info->sleep_interval =
1238  (2 + random_f64_from_to (-0.1, 0.1)) * radv_info->sleep_interval;
1239  if (radv_info->sleep_interval > params->mrt)
1240  radv_info->sleep_interval =
1241  (1 + random_f64_from_to (-0.1, 0.1)) * params->mrt;
1242 
1243  radv_info->due_time = current_time + radv_info->sleep_interval;
1244 
1245  if (params->mrd != 0
1246  && current_time > radv_info->start_time + params->mrd)
1247  stop_sending_rs (vm, radv_info);
1248  else
1249  *due_time = radv_info->due_time;
1250  }
1251 
1252  return radv_info->keep_sending_rs;
1253 }
1254 
1255 static uword
1257  vlib_frame_t * f0)
1258 {
1259  uword *event_data = NULL;
1260  f64 sleep_time = 1e9;
1261  ip6_ra_t *radv_info;
1262  f64 current_time;
1263  f64 due_time;
1264  f64 dt = 0;
1265 
1266  while (true)
1267  {
1268  vlib_process_wait_for_event_or_clock (vm, sleep_time);
1269  vlib_process_get_events (vm, &event_data);
1270  vec_reset_length (event_data);
1271 
1272  current_time = vlib_time_now (vm);
1273  do
1274  {
1275  due_time = current_time + 1e9;
1276  /* *INDENT-OFF* */
1277  pool_foreach (radv_info, ip6_ra_pool,
1278  ({
1279  if (check_send_rs (vm, radv_info, current_time, &dt)
1280  && (dt < due_time))
1281  due_time = dt;
1282  }));
1283  /* *INDENT-ON* */
1284  current_time = vlib_time_now (vm);
1285  }
1286  while (due_time < current_time);
1287 
1288  sleep_time = due_time - current_time;
1289  }
1290 
1291  return 0;
1292 }
1293 
1294 /* *INDENT-OFF* */
1296  .function = send_rs_process,
1297  .type = VLIB_NODE_TYPE_PROCESS,
1298  .name = "ip6-rs-process",
1299 };
1300 /* *INDENT-ON* */
1301 
1302 void
1305  * params)
1306 {
1307  ip6_ra_t *ra;
1308 
1309  ASSERT (~0 != sw_if_index);
1310 
1311  ra = ip6_ra_get_itf (sw_if_index);
1312 
1313  if (!ra)
1314  return;
1315 
1316  stop_sending_rs (vm, ra);
1317 
1318  if (!stop)
1319  {
1320  ra->keep_sending_rs = 1;
1321  ra->params = *params;
1322  ra->n_left = params->mrc;
1323  ra->start_time = vlib_time_now (vm);
1324  ra->sleep_interval = (1 + random_f64_from_to (-0.1, 0.1)) * params->irt;
1325  ra->due_time = 0; /* send first packet ASAP */
1326  ra->buffer = create_buffer_for_rs (vm, ra);
1327  if (!ra->buffer)
1328  ra->keep_sending_rs = 0;
1329  else
1331  }
1332 }
1333 
1334 static const ethernet_interface_t *
1336 {
1337  const vnet_sw_interface_t *sw;
1338 
1339  /* lookup radv container - ethernet interfaces only */
1340  sw = vnet_get_sup_sw_interface (vnet_get_main (), sw_if_index);
1343 
1344  return (NULL);
1345 }
1346 
1347 /**
1348  * @brief called when IP6 is enabled on an interface
1349  *create and initialize router advertisement parameters with default
1350  * values for this intfc
1351  */
1352 static void
1354 {
1355  const ethernet_interface_t *eth;
1356  ip6_ra_t *radv_info;
1357 
1358  eth = ip6_ra_get_eth_itf (sw_if_index);
1359 
1360  if (NULL == eth)
1361  return;
1362 
1363  ASSERT (INDEX_INVALID == ip6_link_delegate_get (sw_if_index,
1365 
1366  pool_get_zero (ip6_ra_pool, radv_info);
1367 
1368  radv_info->seed = (u32) clib_cpu_time_now ();
1369  random_u32 (&radv_info->seed);
1370 
1371  radv_info->sw_if_index = sw_if_index;
1374  radv_info->curr_hop_limit = DEF_CURR_HOP_LIMIT;
1376 
1377  /* send ll address source address option */
1378  radv_info->adv_link_layer_address = 1;
1379 
1383 
1385  radv_info->initial_adverts_sent = radv_info->initial_adverts_count - 1;
1387 
1388  /* deafult is to send */
1389  radv_info->send_radv = 1;
1390 
1391  /* fill in delegate for this interface that will be needed later */
1392  radv_info->adv_link_mtu =
1394 
1395  mhash_init (&radv_info->address_to_prefix_index, sizeof (uword),
1396  sizeof (ip6_address_t));
1397 
1399  radv_info - ip6_ra_pool);
1400 }
1401 
1402 static void
1404 {
1405  ip6_radv_prefix_t *p;
1406  ip6_ra_t *radv_info;
1407 
1408  radv_info = pool_elt_at_index (ip6_ra_pool, rai);
1409 
1410  /* clean up prefix and MDP pools */
1411  /* *INDENT-OFF* */
1412  pool_flush(p, radv_info->adv_prefixes_pool,
1413  ({
1414  mhash_unset (&radv_info->address_to_prefix_index, &p->prefix, 0);
1415  }));
1416  /* *INDENT-ON* */
1417 
1418  pool_free (radv_info->adv_prefixes_pool);
1419 
1420  mhash_free (&radv_info->address_to_prefix_index);
1421 
1422  pool_put (ip6_ra_pool, radv_info);
1423 }
1424 
1425 void
1426 ip6_ra_update_secondary_radv_info (ip6_address_t * address, u8 prefix_len,
1427  u32 primary_sw_if_index,
1429 {
1431  static u32 *radv_indices;
1432  ip6_ra_t *radv_info;
1433  int i;
1434  ip6_address_t mask;
1435  ip6_address_mask_from_width (&mask, prefix_len);
1436 
1437  vec_reset_length (radv_indices);
1438  /* *INDENT-OFF* */
1439  pool_foreach (radv_info, ip6_ra_pool,
1440  ({
1441  vec_add1 (radv_indices, radv_info - ip6_ra_pool);
1442  }));
1443  /* *INDENT-ON* */
1444 
1445  /*
1446  * If we have another customer for this prefix,
1447  * tell the RA code about it...
1448  */
1449  for (i = 0; i < vec_len (radv_indices); i++)
1450  {
1451  ip6_radv_prefix_t *this_prefix;
1452  radv_info = pool_elt_at_index (ip6_ra_pool, radv_indices[i]);
1453 
1454  /* We already took care of these timers... */
1455  if (radv_info->sw_if_index == primary_sw_if_index)
1456  continue;
1457 
1458  /* *INDENT-OFF* */
1459  pool_foreach (this_prefix, radv_info->adv_prefixes_pool,
1460  ({
1461  if (this_prefix->prefix_len == prefix_len
1462  && ip6_address_is_equal_masked (&this_prefix->prefix, address,
1463  &mask))
1464  {
1465  int rv = ip6_ra_prefix (vm,
1466  radv_info->sw_if_index,
1467  address,
1468  prefix_len,
1469  0 /* use_default */,
1470  valid_time,
1471  preferred_time,
1472  0 /* no_advertise */,
1473  0 /* off_link */,
1474  0 /* no_autoconfig */,
1475  0 /* no_onlink */,
1476  0 /* is_no */);
1477  if (rv != 0)
1478  clib_warning ("ip6_neighbor_ra_prefix returned %d", rv);
1479  }
1480  }));
1481  /* *INDENT-ON*/
1482  }
1483 }
1484 
1485 /* send a RA or update the timer info etc.. */
1486 static uword
1489 {
1490  vnet_main_t *vnm = vnet_get_main ();
1491  ip6_ra_t *radv_info;
1492  vlib_frame_t *f = 0;
1493  u32 n_this_frame = 0;
1494  u32 n_left_to_next = 0;
1495  u32 *to_next = 0;
1496  u32 bo0;
1497  icmp6_router_solicitation_header_t *h0;
1498  vlib_buffer_t *b0;
1499  f64 now = vlib_time_now (vm);
1500 
1501  /* Interface ip6 radv info list */
1502  /* *INDENT-OFF* */
1503  pool_foreach (radv_info, ip6_ra_pool,
1504  ({
1505  if( !vnet_sw_interface_is_admin_up (vnm, radv_info->sw_if_index))
1506  {
1507  radv_info->initial_adverts_sent = radv_info->initial_adverts_count-1;
1508  radv_info->next_multicast_time = now;
1509  radv_info->last_multicast_time = now;
1510  radv_info->last_radv_time = 0;
1511  continue;
1512  }
1513 
1514  /* is it time to send a multicast RA on this interface? */
1515  if(radv_info->send_radv && (now >= radv_info->next_multicast_time))
1516  {
1517  u32 n_to_alloc = 1;
1518  u32 n_allocated;
1519 
1520  f64 rfn = (radv_info->max_radv_interval - radv_info->min_radv_interval) *
1521  random_f64 (&radv_info->seed) + radv_info->min_radv_interval;
1522 
1523  /* multicast send - compute next multicast send time */
1524  if( radv_info->initial_adverts_sent > 0)
1525  {
1526  radv_info->initial_adverts_sent--;
1527  if(rfn > radv_info->initial_adverts_interval)
1528  rfn = radv_info->initial_adverts_interval;
1529 
1530  /* check to see if we are ceasing to send */
1531  if( radv_info->initial_adverts_sent == 0)
1532  if(radv_info->cease_radv)
1533  radv_info->send_radv = 0;
1534  }
1535 
1536  radv_info->next_multicast_time = rfn + now;
1537  radv_info->last_multicast_time = now;
1538 
1539  /* send advert now - build a "solicted" router advert with unspecified source address */
1540  n_allocated = vlib_buffer_alloc (vm, &bo0, n_to_alloc);
1541 
1542  if (PREDICT_FALSE(n_allocated == 0))
1543  {
1544  clib_warning ("buffer allocation failure");
1545  continue;
1546  }
1547  b0 = vlib_get_buffer (vm, bo0);
1548  b0->current_length = sizeof( icmp6_router_solicitation_header_t);
1549  b0->error = ICMP6_ERROR_NONE;
1550  vnet_buffer (b0)->sw_if_index[VLIB_RX] = radv_info->sw_if_index;
1551 
1552  h0 = vlib_buffer_get_current (b0);
1553 
1554  clib_memset (h0, 0, sizeof (icmp6_router_solicitation_header_t));
1555 
1556  h0->ip.ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0x6 << 28);
1557  h0->ip.payload_length = clib_host_to_net_u16 (sizeof (icmp6_router_solicitation_header_t)
1558  - STRUCT_OFFSET_OF (icmp6_router_solicitation_header_t, neighbor));
1559  h0->ip.protocol = IP_PROTOCOL_ICMP6;
1560  h0->ip.hop_limit = 255;
1561 
1562  /* set src/dst address as "unspecified" this marks this packet as internally generated rather than recieved */
1563  h0->ip.src_address.as_u64[0] = 0;
1564  h0->ip.src_address.as_u64[1] = 0;
1565 
1566  h0->ip.dst_address.as_u64[0] = 0;
1567  h0->ip.dst_address.as_u64[1] = 0;
1568 
1569  h0->neighbor.icmp.type = ICMP6_router_solicitation;
1570 
1571  if (PREDICT_FALSE(f == 0))
1572  {
1574  to_next = vlib_frame_vector_args (f);
1575  n_left_to_next = VLIB_FRAME_SIZE;
1576  n_this_frame = 0;
1577  }
1578 
1579  n_this_frame++;
1580  n_left_to_next--;
1581  to_next[0] = bo0;
1582  to_next += 1;
1583 
1584  if (PREDICT_FALSE(n_left_to_next == 0))
1585  {
1586  f->n_vectors = n_this_frame;
1588  f = 0;
1589  }
1590  }
1591  }));
1592  /* *INDENT-ON* */
1593 
1594  if (f)
1595  {
1596  ASSERT (n_this_frame);
1597  f->n_vectors = n_this_frame;
1599  }
1600  return 0;
1601 }
1602 
1603 static void
1605 {
1606  u32 ii;
1607 
1609 }
1610 
1611 static uword
1614 {
1615  ip6_ra_report_t *r, *rs;
1616  uword event_type;
1617 
1618  /* init code here */
1619 
1620  while (1)
1621  {
1622  vlib_process_wait_for_event_or_clock (vm, 1. /* seconds */ );
1623 
1624  rs = vlib_process_get_event_data (vm, &event_type);
1625 
1626  if (NULL == rs)
1627  {
1628  /* No events found: timer expired. */
1629  /* process interface list and send RAs as appropriate, update timer info */
1630  ip6_ra_process_timer_event (vm, node, frame);
1631  }
1632  else
1633  {
1634  vec_foreach (r, rs) ip6_ra_handle_report (r);
1635  vec_reset_length (rs);
1636  }
1637  }
1638  return frame->n_vectors;
1639 }
1640 
1642 {
1643 .function = ip6_ra_event_process,.name = "ip6-ra-process",.type =
1645 
1646 static void
1648 {
1650  ip6_ra_report_t *q;
1651 
1652  if (!vec_len (ip6_ra_listeners))
1653  return;
1654 
1656  ip6_ra_process_node.index,
1657  0, 1, sizeof *q);
1658  *q = *r;
1659 }
1660 
1661 static int
1663 {
1664  void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length);
1666  return 0;
1667 }
1668 
1669 /* API support functions */
1670 int
1672  u8 suppress, u8 managed, u8 other,
1673  u8 ll_option, u8 send_unicast, u8 cease,
1674  u8 use_lifetime, u32 lifetime,
1675  u32 initial_count, u32 initial_interval,
1676  u32 max_interval, u32 min_interval, u8 is_no)
1677 {
1678  ip6_ra_t *radv_info;
1679 
1680  /* look up the radv_t information for this interface */
1681  radv_info = ip6_ra_get_itf (sw_if_index);
1682 
1683  if (!radv_info)
1684  return (VNET_API_ERROR_IP6_NOT_ENABLED);
1685 
1686  if ((max_interval != 0) && (min_interval == 0))
1687  min_interval = .75 * max_interval;
1688 
1689  max_interval =
1690  (max_interval !=
1691  0) ? ((is_no) ? DEF_MAX_RADV_INTERVAL : max_interval) :
1692  radv_info->max_radv_interval;
1693  min_interval =
1694  (min_interval !=
1695  0) ? ((is_no) ? DEF_MIN_RADV_INTERVAL : min_interval) :
1696  radv_info->min_radv_interval;
1697  lifetime =
1698  (use_lifetime !=
1699  0) ? ((is_no) ? DEF_DEF_RTR_LIFETIME : lifetime) :
1700  radv_info->adv_router_lifetime_in_sec;
1701 
1702  if (lifetime)
1703  {
1704  if (lifetime > MAX_DEF_RTR_LIFETIME)
1705  lifetime = MAX_DEF_RTR_LIFETIME;
1706 
1707  if (lifetime <= max_interval)
1708  return VNET_API_ERROR_INVALID_VALUE;
1709  }
1710 
1711  if (min_interval != 0)
1712  {
1713  if ((min_interval > .75 * max_interval) || (min_interval < 3))
1714  return VNET_API_ERROR_INVALID_VALUE;
1715  }
1716 
1717  if ((initial_count > MAX_INITIAL_RTR_ADVERTISEMENTS) ||
1718  (initial_interval > MAX_INITIAL_RTR_ADVERT_INTERVAL))
1719  return VNET_API_ERROR_INVALID_VALUE;
1720 
1721  /*
1722  if "flag" is set and is_no is true then restore default value else set value corresponding to "flag"
1723  if "flag" is clear don't change corresponding value
1724  */
1725  radv_info->send_radv =
1726  (suppress != 0) ? ((is_no != 0) ? 1 : 0) : radv_info->send_radv;
1727  radv_info->adv_managed_flag =
1728  (managed != 0) ? ((is_no) ? 0 : 1) : radv_info->adv_managed_flag;
1729  radv_info->adv_other_flag =
1730  (other != 0) ? ((is_no) ? 0 : 1) : radv_info->adv_other_flag;
1731  radv_info->adv_link_layer_address =
1732  (ll_option != 0) ? ((is_no) ? 1 : 0) : radv_info->adv_link_layer_address;
1733  radv_info->send_unicast =
1734  (send_unicast != 0) ? ((is_no) ? 0 : 1) : radv_info->send_unicast;
1735  radv_info->cease_radv =
1736  (cease != 0) ? ((is_no) ? 0 : 1) : radv_info->cease_radv;
1737 
1738  radv_info->min_radv_interval = min_interval;
1739  radv_info->max_radv_interval = max_interval;
1740  radv_info->adv_router_lifetime_in_sec = lifetime;
1741 
1742  radv_info->initial_adverts_count =
1743  (initial_count !=
1744  0) ? ((is_no) ? MAX_INITIAL_RTR_ADVERTISEMENTS : initial_count) :
1745  radv_info->initial_adverts_count;
1746  radv_info->initial_adverts_interval =
1747  (initial_interval !=
1748  0) ? ((is_no) ? MAX_INITIAL_RTR_ADVERT_INTERVAL : initial_interval) :
1749  radv_info->initial_adverts_interval;
1750 
1751  /* restart */
1752  if ((cease != 0) && (is_no))
1753  radv_info->send_radv = 1;
1754 
1755  radv_info->initial_adverts_sent = radv_info->initial_adverts_count - 1;
1756  radv_info->next_multicast_time = vlib_time_now (vm);
1757  radv_info->last_multicast_time = vlib_time_now (vm);
1758  radv_info->last_radv_time = 0;
1759 
1760  return (0);
1761 }
1762 
1763 
1764 int
1766  ip6_address_t * prefix_addr, u8 prefix_len,
1767  u8 use_default, u32 val_lifetime, u32 pref_lifetime,
1768  u8 no_advertise, u8 off_link, u8 no_autoconfig,
1769  u8 no_onlink, u8 is_no)
1770 {
1771  ip6_ra_t *radv_info;
1772 
1773  /* look up the radv_t information for this interface */
1774  radv_info = ip6_ra_get_itf (sw_if_index);
1775 
1776  if (!radv_info)
1777  return (VNET_API_ERROR_IP6_NOT_ENABLED);
1778 
1779  f64 now = vlib_time_now (vm);
1780 
1781  /* prefix info add, delete or update */
1783 
1784  /* lookup prefix info for this address on this interface */
1785  uword *p = mhash_get (&radv_info->address_to_prefix_index, prefix_addr);
1786 
1787  prefix = p ? pool_elt_at_index (radv_info->adv_prefixes_pool, p[0]) : 0;
1788 
1789  if (is_no)
1790  {
1791  /* delete */
1792  if (!prefix)
1793  return VNET_API_ERROR_INVALID_VALUE; /* invalid prefix */
1794 
1795  if (prefix->prefix_len != prefix_len)
1796  return VNET_API_ERROR_INVALID_VALUE_2;
1797 
1798  /* FIXME - Should the DP do this or the CP ? */
1799  /* do specific delete processing here before returning */
1800  /* try to remove from routing table */
1801 
1802  mhash_unset (&radv_info->address_to_prefix_index, prefix_addr,
1803  /* old_value */ 0);
1804  pool_put (radv_info->adv_prefixes_pool, prefix);
1805 
1806  radv_info->initial_adverts_sent = radv_info->initial_adverts_count - 1;
1807  radv_info->next_multicast_time = vlib_time_now (vm);
1808  radv_info->last_multicast_time = vlib_time_now (vm);
1809  radv_info->last_radv_time = 0;
1810  return (0);
1811  }
1812 
1813  /* adding or changing */
1814  if (!prefix)
1815  {
1816  /* add */
1817  u32 pi;
1818  pool_get_zero (radv_info->adv_prefixes_pool, prefix);
1819  pi = prefix - radv_info->adv_prefixes_pool;
1820  mhash_set (&radv_info->address_to_prefix_index, prefix_addr, pi,
1821  /* old_value */ 0);
1822 
1823  clib_memset (prefix, 0x0, sizeof (ip6_radv_prefix_t));
1824 
1825  prefix->prefix_len = prefix_len;
1826  clib_memcpy (&prefix->prefix, prefix_addr, sizeof (ip6_address_t));
1827 
1828  /* initialize default values */
1829  prefix->adv_on_link_flag = 1; /* L bit set */
1830  prefix->adv_autonomous_flag = 1; /* A bit set */
1833  prefix->enabled = 1;
1834  prefix->decrement_lifetime_flag = 1;
1835  prefix->deprecated_prefix_flag = 1;
1836 
1837  if (off_link == 0)
1838  {
1839  /* FIXME - Should the DP do this or the CP ? */
1840  /* insert prefix into routing table as a connected prefix */
1841  }
1842 
1843  if (use_default)
1844  goto restart;
1845  }
1846  else
1847  {
1848 
1849  if (prefix->prefix_len != prefix_len)
1850  return VNET_API_ERROR_INVALID_VALUE_2;
1851 
1852  if (off_link != 0)
1853  {
1854  /* FIXME - Should the DP do this or the CP ? */
1855  /* remove from routing table if already there */
1856  }
1857  }
1858 
1859  if ((val_lifetime == ~0) || (pref_lifetime == ~0))
1860  {
1861  prefix->adv_valid_lifetime_in_secs = ~0;
1862  prefix->adv_pref_lifetime_in_secs = ~0;
1863  prefix->decrement_lifetime_flag = 0;
1864  }
1865  else
1866  {
1867  prefix->adv_valid_lifetime_in_secs = val_lifetime;;
1868  prefix->adv_pref_lifetime_in_secs = pref_lifetime;
1869  }
1870 
1871  /* copy remaining */
1872  prefix->enabled = !(no_advertise != 0);
1873  prefix->adv_on_link_flag = !((off_link != 0) || (no_onlink != 0));
1874  prefix->adv_autonomous_flag = !(no_autoconfig != 0);
1875 
1876 restart:
1877  /* restart */
1878  /* fill in the expiration times */
1879  prefix->valid_lifetime_expires = now + prefix->adv_valid_lifetime_in_secs;
1880  prefix->pref_lifetime_expires = now + prefix->adv_pref_lifetime_in_secs;
1881 
1882  radv_info->initial_adverts_sent = radv_info->initial_adverts_count - 1;
1883  radv_info->next_multicast_time = vlib_time_now (vm);
1884  radv_info->last_multicast_time = vlib_time_now (vm);
1885  radv_info->last_radv_time = 0;
1886 
1887  return (0);
1888 }
1889 
1890 clib_error_t *
1892  unformat_input_t * main_input, vlib_cli_command_t * cmd)
1893 {
1894  vnet_main_t *vnm = vnet_get_main ();
1895  clib_error_t *error = 0;
1896  u8 is_no = 0;
1897  u8 suppress = 0, managed = 0, other = 0;
1898  u8 suppress_ll_option = 0, send_unicast = 0, cease = 0;
1899  u8 use_lifetime = 0;
1900  u32 sw_if_index, ra_lifetime = 0, ra_initial_count =
1901  0, ra_initial_interval = 0;
1902  u32 ra_max_interval = 0, ra_min_interval = 0;
1903 
1904  unformat_input_t _line_input, *line_input = &_line_input;
1905 
1906  int add_radv_info = 1;
1907  ip6_address_t ip6_addr;
1908  u32 addr_len;
1909 
1910 
1911  /* Get a line of input. */
1912  if (!unformat_user (main_input, unformat_line_input, line_input))
1913  return 0;
1914 
1915  /* get basic radv info for this interface */
1916  if (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1917  {
1918 
1919  if (unformat_user (line_input,
1920  unformat_vnet_sw_interface, vnm, &sw_if_index))
1921  {
1922  if (!ip6_ra_get_eth_itf (sw_if_index))
1923  {
1924  error =
1925  clib_error_return (0, "Interface must be of ethernet type");
1926  goto done;
1927  }
1928 
1929  if (!ip6_link_is_enabled (sw_if_index))
1930  {
1931  error = clib_error_return (0, "IP6 nt enabler interface %U'",
1932  format_unformat_error, line_input);
1933  goto done;
1934  }
1935  }
1936  else
1937  {
1938  error = clib_error_return (0, "invalid interface name %U'",
1939  format_unformat_error, line_input);
1940  goto done;
1941  }
1942  }
1943 
1944  /* get the rest of the command */
1945  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1946  {
1947  if (unformat (line_input, "no"))
1948  is_no = 1;
1949  else if (unformat (line_input, "prefix %U/%d",
1950  unformat_ip6_address, &ip6_addr, &addr_len))
1951  {
1952  add_radv_info = 0;
1953  }
1954  else if (unformat (line_input, "ra-managed-config-flag"))
1955  {
1956  managed = 1;
1957  }
1958  else if (unformat (line_input, "ra-other-config-flag"))
1959  {
1960  other = 1;
1961  }
1962  else if (unformat (line_input, "ra-suppress") ||
1963  unformat (line_input, "ra-surpress"))
1964  {
1965  suppress = 1;
1966  }
1967  else if (unformat (line_input, "ra-suppress-link-layer") ||
1968  unformat (line_input, "ra-surpress-link-layer"))
1969  {
1970  suppress_ll_option = 1;
1971  }
1972  else if (unformat (line_input, "ra-send-unicast"))
1973  {
1974  send_unicast = 1;
1975  }
1976  else if (unformat (line_input, "ra-lifetime"))
1977  {
1978  if (!unformat (line_input, "%d", &ra_lifetime))
1979  {
1980  error = unformat_parse_error (line_input);
1981  goto done;
1982  }
1983  use_lifetime = 1;
1984  }
1985  else if (unformat (line_input, "ra-initial"))
1986  {
1987  if (!unformat
1988  (line_input, "%d %d", &ra_initial_count, &ra_initial_interval))
1989  {
1990  error = unformat_parse_error (line_input);
1991  goto done;
1992  }
1993  }
1994  else if (unformat (line_input, "ra-interval"))
1995  {
1996  if (!unformat (line_input, "%d", &ra_max_interval))
1997  {
1998  error = unformat_parse_error (line_input);
1999  goto done;
2000  }
2001 
2002  if (!unformat (line_input, "%d", &ra_min_interval))
2003  ra_min_interval = 0;
2004  }
2005  else if (unformat (line_input, "ra-cease"))
2006  {
2007  cease = 1;
2008  }
2009  else
2010  {
2011  error = unformat_parse_error (line_input);
2012  goto done;
2013  }
2014  }
2015 
2016  if (add_radv_info)
2017  {
2018  ip6_ra_config (vm, sw_if_index,
2019  suppress, managed, other,
2020  suppress_ll_option, send_unicast, cease,
2021  use_lifetime, ra_lifetime,
2022  ra_initial_count, ra_initial_interval,
2023  ra_max_interval, ra_min_interval, is_no);
2024  }
2025  else
2026  {
2027  u32 valid_lifetime_in_secs = 0;
2028  u32 pref_lifetime_in_secs = 0;
2029  u8 use_prefix_default_values = 0;
2030  u8 no_advertise = 0;
2031  u8 off_link = 0;
2032  u8 no_autoconfig = 0;
2033  u8 no_onlink = 0;
2034 
2035  /* get the rest of the command */
2036  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2037  {
2038  if (unformat (line_input, "default"))
2039  {
2040  use_prefix_default_values = 1;
2041  break;
2042  }
2043  else if (unformat (line_input, "infinite"))
2044  {
2045  valid_lifetime_in_secs = ~0;
2046  pref_lifetime_in_secs = ~0;
2047  break;
2048  }
2049  else if (unformat (line_input, "%d %d", &valid_lifetime_in_secs,
2050  &pref_lifetime_in_secs))
2051  break;
2052  else
2053  break;
2054  }
2055 
2056 
2057  /* get the rest of the command */
2058  while (!use_prefix_default_values &&
2060  {
2061  if (unformat (line_input, "no-advertise"))
2062  no_advertise = 1;
2063  else if (unformat (line_input, "off-link"))
2064  off_link = 1;
2065  else if (unformat (line_input, "no-autoconfig"))
2066  no_autoconfig = 1;
2067  else if (unformat (line_input, "no-onlink"))
2068  no_onlink = 1;
2069  else
2070  {
2071  error = unformat_parse_error (line_input);
2072  goto done;
2073  }
2074  }
2075 
2076  ip6_ra_prefix (vm, sw_if_index,
2077  &ip6_addr, addr_len,
2078  use_prefix_default_values,
2079  valid_lifetime_in_secs,
2080  pref_lifetime_in_secs,
2081  no_advertise, off_link, no_autoconfig, no_onlink, is_no);
2082  }
2083 
2084 done:
2085  unformat_free (line_input);
2086 
2087  return error;
2088 }
2089 
2090 static u8 *
2091 format_ip6_ra (u8 * s, va_list * args)
2092 {
2093  index_t rai = va_arg (*args, index_t);
2094  u32 indent = va_arg (*args, u32);
2095  ip6_radv_prefix_t *p;
2096  ip6_ra_t *radv_info;
2097 
2098  radv_info = pool_elt_at_index (ip6_ra_pool, rai);
2099 
2100  s = format (s, "%UAdvertised Prefixes:\n", format_white_space, indent);
2101 
2102  indent += 2;
2103 
2104  /* *INDENT-OFF* */
2105  pool_foreach (p, radv_info->adv_prefixes_pool,
2106  ({
2107  s = format (s, "%Uprefix %U, length %d\n",
2108  format_white_space, indent+2,
2109  format_ip6_address, &p->prefix, p->prefix_len);
2110  }));
2111  /* *INDENT-ON* */
2112 
2113  s = format (s, "%UMTU is %d\n",
2114  format_white_space, indent, radv_info->adv_link_mtu);
2115  s = format (s, "%UICMP error messages are unlimited\n",
2116  format_white_space, indent);
2117  s = format (s, "%UICMP redirects are disabled\n",
2118  format_white_space, indent);
2119  s = format (s, "%UICMP unreachables are not sent\n",
2120  format_white_space, indent);
2121  s = format (s, "%UND DAD is disabled\n", format_white_space, indent);
2122  //s = format (s, "%UND reachable time is %d milliseconds\n",);
2123  s = format (s, "%UND advertised reachable time is %d\n",
2124  format_white_space, indent,
2126  s = format (s,
2127  "%UND advertised retransmit interval is %d (msec)\n",
2128  format_white_space, indent,
2129  radv_info->
2131  s =
2132  format (s,
2133  "%UND router advertisements are sent every %0.1f seconds (min interval is %0.1f)\n",
2134  format_white_space, indent, radv_info->max_radv_interval,
2135  radv_info->min_radv_interval);
2136  s =
2137  format (s, "%UND router advertisements live for %d seconds\n",
2138  format_white_space, indent,
2139  radv_info->adv_router_lifetime_in_sec);
2140  s =
2141  format (s, "%UHosts %s stateless autoconfig for addresses\n",
2142  format_white_space, indent,
2143  (radv_info->adv_managed_flag) ? "use" : " don't use");
2144  s =
2145  format (s, "%UND router advertisements sent %d\n", format_white_space,
2146  indent, radv_info->n_advertisements_sent);
2147  s =
2148  format (s, "%UND router solicitations received %d\n", format_white_space,
2149  indent, radv_info->n_solicitations_rcvd);
2150  s =
2151  format (s, "%UND router solicitations dropped %d\n", format_white_space,
2152  indent, radv_info->n_solicitations_dropped);
2153 
2154  return (s);
2155 }
2156 
2157 
2158 /*?
2159  * This command is used to configure the neighbor discovery
2160  * parameters on a given interface. Use the '<em>show ip6 interface</em>'
2161  * command to display some of the current neighbor discovery parameters
2162  * on a given interface. This command has three formats:
2163  *
2164  *
2165  * <b>Format 1 - Router Advertisement Options:</b> (Only one can be entered in a single command)
2166  *
2167  * '<em><b>ip6 nd <interface> [no] [ra-managed-config-flag] | [ra-other-config-flag] | [ra-suppress] | [ra-suppress-link-layer] | [ra-send-unicast] | [ra-lifetime <lifetime>] | [ra-initial <cnt> <interval>] | [ra-interval <max-interval> [<min-interval>]] | [ra-cease]</b></em>'
2168  *
2169  * Where:
2170  *
2171  * <em>[no] ra-managed-config-flag</em> - Advertises in ICMPv6
2172  * router-advertisement messages to use stateful address
2173  * auto-configuration to obtain address information (sets the M-bit).
2174  * Default is the M-bit is not set and the '<em>no</em>' option
2175  * returns it to this default state.
2176  *
2177  * <em>[no] ra-other-config-flag</em> - Indicates in ICMPv6
2178  * router-advertisement messages that hosts use stateful auto
2179  * configuration to obtain nonaddress related information (sets
2180  * the O-bit). Default is the O-bit is not set and the '<em>no</em>'
2181  * option returns it to this default state.
2182  *
2183  * <em>[no] ra-suppress</em> - Disables sending ICMPv6 router-advertisement
2184  * messages. The '<em>no</em>' option implies to enable sending ICMPv6
2185  * router-advertisement messages.
2186  *
2187  * <em>[no] ra-suppress-link-layer</em> - Indicates not to include the
2188  * optional source link-layer address in the ICMPv6 router-advertisement
2189  * messages. Default is to include the optional source link-layer address
2190  * and the '<em>no</em>' option returns it to this default state.
2191  *
2192  * <em>[no] ra-send-unicast</em> - Use the source address of the
2193  * router-solicitation message if availiable. The default is to use
2194  * multicast address of all nodes, and the '<em>no</em>' option returns
2195  * it to this default state.
2196  *
2197  * <em>[no] ra-lifetime <lifetime></em> - Advertises the lifetime of a
2198  * default router in ICMPv6 router-advertisement messages. The range is
2199  * from 0 to 9000 seconds. '<em><lifetime></em>' must be greater than
2200  * '<em><max-interval></em>'. The default value is 600 seconds and the
2201  * '<em>no</em>' option returns it to this default value.
2202  *
2203  * <em>[no] ra-initial <cnt> <interval></em> - Number of initial ICMPv6
2204  * router-advertisement messages sent and the interval between each
2205  * message. Range for count is 1 - 3 and default is 3. Range for interval
2206  * is 1 to 16 seconds, and default is 16 seconds. The '<em>no</em>' option
2207  * returns both to their default value.
2208  *
2209  * <em>[no] ra-interval <max-interval> [<min-interval>]</em> - Configures the
2210  * interval between sending ICMPv6 router-advertisement messages. The
2211  * range for max-interval is from 4 to 200 seconds. min-interval can not
2212  * be more than 75% of max-interval. If not set, min-interval will be
2213  * set to 75% of max-interval. The range for min-interval is from 3 to
2214  * 150 seconds. The '<em>no</em>' option returns both to their default
2215  * value.
2216  *
2217  * <em>[no] ra-cease</em> - Cease sending ICMPv6 router-advertisement messages.
2218  * The '<em>no</em>' options implies to start (or restart) sending
2219  * ICMPv6 router-advertisement messages.
2220  *
2221  *
2222  * <b>Format 2 - Prefix Options:</b>
2223  *
2224  * '<em><b>ip6 nd <interface> [no] prefix <ip6-address>/<width> [<valid-lifetime> <pref-lifetime> | infinite] [no-advertise] [off-link] [no-autoconfig] [no-onlink]</b></em>'
2225  *
2226  * Where:
2227  *
2228  * <em>no</em> - All additional flags are ignored and the prefix is deleted.
2229  *
2230  * <em><valid-lifetime> <pref-lifetime></em> - '<em><valid-lifetime></em>' is the
2231  * length of time in seconds during what the prefix is valid for the purpose of
2232  * on-link determination. Range is 7203 to 2592000 seconds and default is 2592000
2233  * seconds (30 days). '<em><pref-lifetime></em>' is the prefered-lifetime and is the
2234  * length of time in seconds during what addresses generated from the prefix remain
2235  * preferred. Range is 0 to 604800 seconds and default is 604800 seconds (7 days).
2236  *
2237  * <em>infinite</em> - Both '<em><valid-lifetime></em>' and '<em><<pref-lifetime></em>'
2238  * are inifinte, no timeout.
2239  *
2240  * <em>no-advertise</em> - Do not send full router address in prefix
2241  * advertisement. Default is to advertise (i.e. - This flag is off by default).
2242  *
2243  * <em>off-link</em> - Prefix is off-link, clear L-bit in packet. Default is on-link
2244  * (i.e. - This flag is off and L-bit in packet is set by default and this prefix can
2245  * be used for on-link determination). '<em>no-onlink</em>' also controls the L-bit.
2246  *
2247  * <em>no-autoconfig</em> - Do not use prefix for autoconfiguration, clear A-bit in packet.
2248  * Default is autoconfig (i.e. - This flag is off and A-bit in packet is set by default.
2249  *
2250  * <em>no-onlink</em> - Do not use prefix for onlink determination, clear L-bit in packet.
2251  * Default is on-link (i.e. - This flag is off and L-bit in packet is set by default and
2252  * this prefix can be used for on-link determination). '<em>off-link</em>' also controls
2253  * the L-bit.
2254  *
2255  *
2256  * <b>Format 3: - Default of Prefix:</b>
2257  *
2258  * '<em><b>ip6 nd <interface> [no] prefix <ip6-address>/<width> default</b></em>'
2259  *
2260  * When a new prefix is added (or existing one is being overwritten) <em>default</em>
2261  * uses default values for the prefix. If <em>no</em> is used, the <em>default</em>
2262  * is ignored and the prefix is deleted.
2263  *
2264  *
2265  * @cliexpar
2266  * Example of how set a router advertisement option:
2267  * @cliexcmd{ip6 nd GigabitEthernet2/0/0 ra-interval 100 20}
2268  * Example of how to add a prefix:
2269  * @cliexcmd{ip6 nd GigabitEthernet2/0/0 prefix fe80::fe:28ff:fe9c:75b3/64 infinite no-advertise}
2270  * Example of how to delete a prefix:
2271  * @cliexcmd{ip6 nd GigabitEthernet2/0/0 no prefix fe80::fe:28ff:fe9c:75b3/64}
2272 ?*/
2273 /* *INDENT-OFF* */
2274 VLIB_CLI_COMMAND (ip6_nd_command, static) =
2275 {
2276  .path = "ip6 nd",
2277  .short_help = "ip6 nd <interface> ...",
2278  .function = ip6_ra_cmd,
2279 };
2280 /* *INDENT-ON* */
2281 
2282 /**
2283  * VFT for registering as a delegate to an IP6 link
2284  */
2285 const static ip6_link_delegate_vft_t ip6_ra_delegate_vft = {
2287  .ildv_enable = ip6_ra_link_enable,
2288  .ildv_format = format_ip6_ra,
2289 };
2290 
2291 static clib_error_t *
2293 {
2295 
2296  icmp6_register_type (vm, ICMP6_router_solicitation,
2298  icmp6_register_type (vm, ICMP6_router_advertisement,
2300 
2301  ip6_ra_delegate_id = ip6_link_delegate_register (&ip6_ra_delegate_vft);
2302 
2303  return (NULL);
2304 }
2305 
2306 /* *INDENT-OFF* */
2308 {
2309  .runs_after = VLIB_INITS("icmp6_init"),
2310 };
2311 /* *INDENT-ON* */
2312 
2313 /*
2314  * fd.io coding-style-patch-verification: ON
2315  *
2316  * Local Variables:
2317  * eval: (c-set-style "gnu")
2318  * End:
2319  */
void ip6_ra_report_register(ip6_ra_report_notify_t fn)
Definition: ip6_ra.c:167
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
struct ip6_ra_t_ ip6_ra_t
Definition: mhash.h:46
#define vec_foreach_index(var, v)
Iterate over vector indices.
u8 slla[6]
Definition: ip6_ra.h:70
u8 current_hop_limit
Definition: ip6_ra.h:65
#define DEF_ADV_VALID_LIFETIME
Definition: ip6_ra.c:89
u8 curr_hop_limit
Definition: ip6_ra.c:98
static uword ip6_ra_process_timer_event(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip6_ra.c:1487
#define ICMP6_ROUTER_DISCOVERY_FLAG_OTHER_CONFIG_VIA_DHCP
static uword random_default_seed(void)
Default random seed (unix/linux user-mode)
Definition: random.h:91
static void vlib_buffer_reset(vlib_buffer_t *b)
Reset current header & length to state they were in when packet was received.
Definition: buffer.h:277
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:751
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:937
static int ip6_ra_publish(ip6_ra_report_t *r)
Definition: ip6_ra.c:1662
u32 seed
Definition: ip6_ra.c:153
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:255
#define DEF_MAX_RADV_INTERVAL
Definition: ip6_ra.c:56
#define PREDICT_TRUE(x)
Definition: clib.h:121
static ip6_ra_report_notify_t * ip6_ra_listeners
Definition: ip6_ra.c:162
int adv_autonomous_flag
Definition: ip6_ra.c:75
void ip_neighbor_learn_dp(const ip_neighbor_learn_t *l)
APIs invoked by neighbor implementation (i.s.
unsigned long u64
Definition: types.h:89
ip6_address_t prefix
Definition: ip6_ra.c:72
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
u32 initial_adverts_count
Definition: ip6_ra.c:135
u16 router_lifetime_in_sec
Definition: ip6_ra.h:67
uword mhash_unset(mhash_t *h, void *key, uword *old_value)
Definition: mhash.c:346
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:333
IP unicast adjacency.
Definition: adj.h:227
static ip6_ra_t * ip6_ra_get_itf(u32 sw_if_index)
Definition: ip6_ra.c:195
u32 time_in_msec_between_retransmitted_neighbor_solicitations
Definition: ip6_ra.h:69
int vlib_buffer_add_data(vlib_main_t *vm, u32 *buffer_index, void *data, u32 n_data_bytes)
Definition: buffer.c:421
u8 src_address[6]
Definition: packet.h:56
#define MIN_DELAY_BETWEEN_RAS
Definition: ip6_ra.c:64
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
u32 adv_time_in_msec_between_retransmitted_neighbor_solicitations
Definition: ip6_ra.c:103
#define foreach_log_level
Definition: ip6_ra.c:208
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
static u64 clib_cpu_time_now(void)
Definition: time.h:81
static ip6_link_delegate_id_t ip6_ra_delegate_id
Definition: ip6_ra.c:157
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
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:70
u32 adv_pref_lifetime_in_secs
Definition: ip6_ra.c:77
vlib_main_t * vm
Definition: in2out_ed.c:1582
u32 n_solicitations_dropped
Definition: ip6_ra.c:142
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
u8 * va_format(u8 *s, const char *fmt, va_list *va)
Definition: format.c:387
static u32 vnet_sw_interface_get_mtu(vnet_main_t *vnm, u32 sw_if_index, vnet_mtu_t af)
unformat_function_t unformat_vnet_sw_interface
vl_api_prefix_t prefix
Definition: ip.api:144
u16 mask
Definition: flow_types.api:52
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:469
int ip6_ra_config(vlib_main_t *vm, u32 sw_if_index, u8 suppress, u8 managed, u8 other, u8 ll_option, u8 send_unicast, u8 cease, u8 use_lifetime, u32 lifetime, u32 initial_count, u32 initial_interval, u32 max_interval, u32 min_interval, u8 is_no)
Definition: ip6_ra.c:1671
ip6_address_t src_address
Definition: ip6_packet.h:310
u32 initial_adverts_sent
Definition: ip6_ra.c:137
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
static vlib_buffer_t * vlib_buffer_copy(vlib_main_t *vm, vlib_buffer_t *b)
u8 data[128]
Definition: ipsec_types.api:89
icmp6_router_advertisement_packet_t
Definition: ip6_ra.c:53
static f64 random_f64_from_to(f64 from, f64 to)
Definition: ip6_ra.c:1088
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
#define clib_memcpy(d, s, n)
Definition: string.h:180
vlib_node_registration_t ip6_rewrite_mcast_node
(constructor) VLIB_REGISTER_NODE (ip6_rewrite_mcast_node)
Definition: ip6_forward.c:2220
u64 lifetime
Definition: ikev2_types.api:80
ethernet_main_t ethernet_main
Definition: init.c:45
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:459
#define DEF_CURR_HOP_LIMIT
Definition: ip6_ra.c:58
#define static_always_inline
Definition: clib.h:108
int send_unicast
Definition: ip6_ra.c:112
static void ip6_ra_signal_report(ip6_ra_report_t *r)
Definition: ip6_ra.c:1647
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
#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:579
u32 local_interface_sw_if_index
Definition: vnet.h:57
#define DEF_MIN_RADV_INTERVAL
Definition: ip6_ra.c:57
u8 dst_address[6]
Definition: packet.h:55
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
icmp6_send_router_solicitation_params_t params
Definition: ip6_ra.c:146
int cease_radv
Definition: ip6_ra.c:111
ip6_radv_prefix_t * adv_prefixes_pool
Definition: ip6_ra.c:119
typedef CLIB_PACKED(struct { ip6_header_t ip;icmp6_neighbor_discovery_header_t neighbor;icmp6_neighbor_discovery_ethernet_link_layer_address_option_t link_layer_option;})
Definition: ip6_ra.c:35
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static vnet_sw_interface_t * vnet_get_sup_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:182
#define clib_error_return(e, args...)
Definition: error.h:99
static u32 ip6_src_lookup_for_packet(ip6_main_t *im, vlib_buffer_t *b, ip6_header_t *i)
return the DPO that the LB stacks on.
Definition: ip6_fib.h:118
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: vlib_api.c:619
u32 n_advertisements_sent
Definition: ip6_ra.c:140
static void ip6_ra_handle_report(const ip6_ra_report_t *rap)
Definition: ip6_ra.c:1604
static clib_error_t * icmp6_init(vlib_main_t *vm)
Definition: icmp6.c:760
u32 n_solicitations_rcvd
Definition: ip6_ra.c:141
unsigned int u32
Definition: types.h:88
f64 last_multicast_time
Definition: ip6_ra.c:131
f64 min_radv_interval
Definition: ip6_ra.c:125
u16 fp_len
The mask length.
Definition: fib_types.h:207
#define vlib_call_init_function(vm, x)
Definition: init.h:270
#define VLIB_FRAME_SIZE
Definition: node.h:377
ip6_address_t router_address
Definition: ip6_ra.h:63
fib_prefix_t prefix
Definition: ip6_ra.h:55
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:293
i32 priority
Definition: ipsec.api:95
unformat_function_t unformat_line_input
Definition: format.h:283
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
int send_radv
Definition: ip6_ra.c:110
#define pool_flush(VAR, POOL, BODY)
Remove all elements from a pool in a safe way.
Definition: pool.h:573
f64 pref_lifetime_expires
Definition: ip6_ra.c:81
#define ADJ_INDEX_INVALID
Invalid ADJ index - used when no adj is known likewise blazoned capitals INVALID speak volumes where ...
Definition: adj_types.h:36
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
#define DEF_DEF_RTR_LIFETIME
Definition: ip6_ra.c:59
void ip6_ra_report_unregister(ip6_ra_report_notify_t fn)
Definition: ip6_ra.c:180
int adv_other_flag
Definition: ip6_ra.c:100
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:1015
static u8 get_mac_address(u32 sw_if_index, u8 *address)
Definition: ip6_ra.c:1101
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:226
static __clib_warn_unused_result u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:677
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:216
vec_header_t h
Definition: buffer.c:322
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
enum icmp6_neighbor_discovery_option_type icmp6_neighbor_discovery_option_type_t
static void * vlib_process_signal_event_data(vlib_main_t *vm, uword node_index, uword type_opaque, uword n_data_elts, uword n_data_elt_bytes)
Definition: node_funcs.h:909
#define ELOG_DATA(em, f)
Definition: elog.h:484
f64 last_radv_time
Definition: ip6_ra.c:130
#define PREDICT_FALSE(x)
Definition: clib.h:120
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:875
vnet_main_t vnet_main
Definition: misc.c:43
ip6_main_t ip6_main
Definition: ip6_forward.c:2781
f64 min_delay_between_radv
Definition: ip6_ra.c:126
#define MAX_DELAY_BETWEEN_RAS
Definition: ip6_ra.c:65
f64 max_delay_between_radv
Definition: ip6_ra.c:127
log_level_t
Definition: ip6_ra.c:218
icmp6_router_solicitation_or_advertisement_next_t
Definition: ip6_ra.c:264
u32 node_index
Node index.
Definition: node.h:487
f64 start_time
Definition: ip6_ra.c:150
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
static vlib_node_registration_t ip6_icmp_router_advertisement_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_router_advertisement_node)
Definition: ip6_ra.c:1071
static uword mhash_set(mhash_t *h, void *key, uword new_value, uword *old_value)
Definition: mhash.h:117
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:391
f64 max_radv_interval
Definition: ip6_ra.c:124
vlib_node_registration_t ip6_icmp_input_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_input_node)
Definition: icmp6.c:240
unformat_function_t unformat_ip6_address
Definition: format.h:89
int adv_link_layer_address
Definition: ip6_ra.c:113
vlib_buffer_t * buffer
Definition: ip6_ra.c:151
#define pool_free(p)
Free a pool.
Definition: pool.h:427
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
Definition: mhash.c:168
u32 valid_time
Definition: dhcp.api:312
u16 n_vectors
Definition: node.h:396
format_function_t format_ip6_address
Definition: format.h:91
u32 neighbor_reachable_time_in_msec
Definition: ip6_ra.h:68
static_always_inline uword icmp6_router_advertisement(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip6_ra.c:716
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
static void stop_sending_rs(vlib_main_t *vm, ip6_ra_t *ra)
Definition: ip6_ra.c:1180
static u8 * format_ip6_ra(u8 *s, va_list *args)
Definition: ip6_ra.c:2091
#define MAX_DEF_RTR_LIFETIME
Definition: ip6_ra.c:60
#define clib_warning(format, args...)
Definition: error.h:59
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:115
int adv_managed_flag
Definition: ip6_ra.c:99
elog_main_t elog_main
Definition: main.h:224
static vlib_node_registration_t ip6_icmp_router_solicitation_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_router_solicitation_node)
Definition: ip6_ra.c:696
f64 next_multicast_time
Definition: ip6_ra.c:132
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:483
#define MAX_INITIAL_RTR_ADVERT_INTERVAL
Definition: ip6_ra.c:62
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:442
f64 initial_adverts_interval
Definition: ip6_ra.c:136
ra_report_prefix_info_t * prefixes
Definition: ip6_ra.h:72
static void * ip6_next_header(ip6_header_t *i)
Definition: ip6_packet.h:371
static bool check_send_rs(vlib_main_t *vm, ip6_ra_t *radv_info, f64 current_time, f64 *due_time)
Definition: ip6_ra.c:1194
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1582
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
u16 ip6_tcp_udp_icmp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
Definition: ip6_forward.c:1095
f64 valid_lifetime_expires
Definition: ip6_ra.c:80
int ref_count
Definition: ip6_ra.c:116
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:510
#define ASSERT(truth)
mhash_t address_to_prefix_index
Definition: ip6_ra.c:122
void ip6_ra_update_secondary_radv_info(ip6_address_t *address, u8 prefix_len, u32 primary_sw_if_index, u32 valid_time, u32 preferred_time)
Definition: ip6_ra.c:1426
static void ip6_neighbor_syslog(vlib_main_t *vm, int priority, char *fmt,...)
Definition: ip6_ra.c:234
manual_print typedef address
Definition: ip_types.api:85
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
u32 adv_link_mtu
Definition: ip6_ra.c:106
static void mhash_free(mhash_t *h)
Definition: mhash.h:149
int prefix_option
Definition: ip6_ra.c:114
int adv_on_link_flag
Definition: ip6_ra.c:74
static ip6_ra_t * ip6_ra_pool
Definition: ip6_ra.c:158
void(* ip6_ra_report_notify_t)(const ip6_ra_report_t *rap)
Definition: ip6_ra.h:76
static uword ip6_ra_event_process(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip6_ra.c:1612
static f64 random_f64(u32 *seed)
Generate f64 random number in the interval [0,1].
Definition: random.h:145
int deprecated_prefix_flag
Definition: ip6_ra.c:85
static void ip6_ra_delegate_disable(index_t rai)
Definition: ip6_ra.c:1403
static uword ip6_address_is_link_local_unicast(const ip6_address_t *a)
Definition: ip6_packet.h:253
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static_always_inline uword icmp6_router_solicitation(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip6_ra.c:273
static uword vnet_sw_interface_is_admin_up(vnet_main_t *vnm, u32 sw_if_index)
#define unformat_parse_error(input)
Definition: format.h:269
Definition: defs.h:47
u8 keep_sending_rs
Definition: ip6_ra.c:145
void vlib_trace_frame_buffers_only(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, uword n_buffers, uword next_buffer_stride, uword n_buffer_data_bytes_in_trace)
Definition: trace.c:47
clib_error_t * ip6_ra_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: ip6_ra.c:1891
vlib_node_registration_t ip6_rs_process_node
(constructor) VLIB_REGISTER_NODE (ip6_rs_process_node)
Definition: ip6_ra.c:1295
u16 payload_length
Definition: ip6_packet.h:301
u32 sw_if_index
Definition: ip6_ra.c:109
static void * vlib_process_get_event_data(vlib_main_t *vm, uword *return_event_type_opaque)
Definition: node_funcs.h:526
vl_api_address_t ip
Definition: l2.api:501
ethernet_interface_t * ethernet_get_interface(ethernet_main_t *em, u32 hw_if_index)
Definition: interface.c:967
u32 elog_string(elog_main_t *em, char *fmt,...)
add a string to the event-log string table
Definition: elog.c:571
void icmp6_register_type(vlib_main_t *vm, icmp6_type_t type, u32 node_index)
Definition: icmp6.c:750
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u32 n_left
Definition: ip6_ra.c:149
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1583
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:492
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
u32 adv_neighbor_reachable_time_in_msec
Definition: ip6_ra.c:102
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
f64 max_rtr_default_lifetime
Definition: ip6_ra.c:128
static const ethernet_interface_t * ip6_ra_get_eth_itf(u32 sw_if_index)
Definition: ip6_ra.c:1335
static char * log_level_strings[]
Definition: ip6_ra.c:225
static uword send_rs_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f0)
Definition: ip6_ra.c:1256
static void ip6_address_copy(ip6_address_t *dst, const ip6_address_t *src)
Definition: ip6_packet.h:127
#define ICMP6_ROUTER_DISCOVERY_FLAG_ADDRESS_CONFIG_VIA_DHCP
vlib_node_registration_t ip6_ra_process_node
(constructor) VLIB_REGISTER_NODE (ip6_ra_process_node)
Definition: ip6_ra.c:1641
int decrement_lifetime_flag
Definition: ip6_ra.c:86
static void ip6_address_mask_from_width(ip6_address_t *a, u32 width)
Definition: ip6_packet.h:211
static uword ip6_address_is_unspecified(const ip6_address_t *a)
Definition: ip6_packet.h:237
#define vnet_buffer(b)
Definition: buffer.h:417
#define MAX_INITIAL_RTR_ADVERTISEMENTS
Definition: ip6_ra.c:63
f64 due_time
Definition: ip6_ra.c:148
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
int ip6_ra_prefix(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *prefix_addr, u8 prefix_len, u8 use_default, u32 val_lifetime, u32 pref_lifetime, u8 no_advertise, u8 off_link, u8 no_autoconfig, u8 no_onlink, u8 is_no)
Definition: ip6_ra.c:1765
vnet_sw_interface_type_t type
Definition: interface.h:736
static void ip6_ra_link_enable(u32 sw_if_index)
called when IP6 is enabled on an interface create and initialize router advertisement parameters with...
Definition: ip6_ra.c:1353
static clib_error_t * ip6_ra_init(vlib_main_t *vm)
Definition: ip6_ra.c:2292
static int logmask
Definition: ip6_ra.c:231
u32 preferred_time
Definition: dhcp.api:313
#define vec_foreach(var, vec)
Vector iterator.
#define DEF_ADV_PREF_LIFETIME
Definition: ip6_ra.c:90
u16 flags
Copy of main node flags.
Definition: node.h:500
u32 adv_valid_lifetime_in_secs
Definition: ip6_ra.c:76
static vlib_buffer_t * create_buffer_for_rs(vlib_main_t *vm, ip6_ra_t *radv_info)
Definition: ip6_ra.c:1112
f64 sleep_interval
Definition: ip6_ra.c:147
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:301
u32 sw_if_index
Definition: ip6_ra.h:64
#define VLIB_INITS(...)
Definition: init.h:357
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
int failed_device_check
Definition: ip6_ra.c:115
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
Definition: defs.h:46
u16 adv_router_lifetime_in_sec
Definition: ip6_ra.c:101
ip6_address_t dst_address
Definition: ip6_packet.h:310
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
static void ip6_set_reserved_multicast_address(ip6_address_t *a, ip6_multicast_address_scope_t scope, u16 id)
Definition: ip6_packet.h:134
format_function_t format_icmp6_input_trace
Definition: icmp6.h:65