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