FD.io VPP  v16.09
Vector Packet Processing
ip6_neighbor.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/ip/ip.h>
19 #include <vnet/ethernet/ethernet.h>
20 #include <vppinfra/mhash.h>
21 #include <vppinfra/md5.h>
22 
23 #if DPDK==1
24 #include <vnet/devices/dpdk/dpdk.h>
25 #endif
26 
27 typedef struct {
32 
33 /* can't use sizeof link_layer_address, that's 8 */
34 #define ETHER_MAC_ADDR_LEN 6
35 
36 typedef struct {
38  u8 link_layer_address[8];
40 #define IP6_NEIGHBOR_FLAG_STATIC (1 << 0)
41 #define IP6_NEIGHBOR_FLAG_GLEAN (2 << 0)
45 
46 /* advertised prefix option */
47 typedef struct {
48  /* basic advertised information */
55 
56  /* advertised values are computed from these times if decrementing */
59 
60  /* local information */
61  int enabled;
64 
65 #define MIN_ADV_VALID_LIFETIME 7203 /* seconds */
66 #define DEF_ADV_VALID_LIFETIME 2592000
67 #define DEF_ADV_PREF_LIFETIME 604800
68 
69  /* extensions are added here, mobile, DNS etc.. */
71 
72 
73 typedef struct {
74  /* group information */
80 
81 /* configured router advertisement information per ipv6 interface */
82 typedef struct {
83 
84  /* advertised config information, zero means unspecified */
91 
92  /* mtu option */
94 
95  /* source link layer option */
96  u8 link_layer_address[8];
98 
99  /* prefix option */
101 
102  /* Hash table mapping address to index in interface advertised prefix pool. */
104 
105  /* MLDP group information */
107 
108  /* Hash table mapping address to index in mldp address pool. */
110 
111  /* local information */
114  int send_radv; /* radv on/off on this interface - set by config */
115  int cease_radv; /* we are ceasing to send - set byf config */
127 
128  /* timing information */
129 #define DEF_MAX_RADV_INTERVAL 200
130 #define DEF_MIN_RADV_INTERVAL .75 * DEF_MAX_RADV_INTERVAL
131 #define DEF_CURR_HOP_LIMIT 64
132 #define DEF_DEF_RTR_LIFETIME 3 * DEF_MAX_RADV_INTERVAL
133 #define MAX_DEF_RTR_LIFETIME 9000
134 
135 #define MAX_INITIAL_RTR_ADVERT_INTERVAL 16 /* seconds */
136 #define MAX_INITIAL_RTR_ADVERTISEMENTS 3 /*transmissions */
137 #define MIN_DELAY_BETWEEN_RAS 3 /* seconds */
138 #define MAX_DELAY_BETWEEN_RAS 1800 /* seconds */
139 #define MAX_RA_DELAY_TIME .5 /* seconds */
140 
146 
150 
151 
155 
156  /* stats */
160 
161  /* Link local address to use (defaults to underlying physical for logical interfaces */
164 
165 } ip6_radv_t;
166 
167 typedef struct {
168  u32 next_index;
169  uword node_index;
170  uword type_opaque;
171  uword data;
173 
174 
175 typedef struct {
176  /* Hash tables mapping name to opcode. */
178 
179  /* lite beer "glean" adjacency handling */
182 
184 
186 
188 
190 
192 
193  /* Neighbor attack mitigation */
196 
198 
200 
201 static u8 * format_ip6_neighbor_ip6_entry (u8 * s, va_list * va)
202 {
203  vlib_main_t * vm = va_arg (*va, vlib_main_t *);
204  ip6_neighbor_t * n = va_arg (*va, ip6_neighbor_t *);
205  vnet_main_t * vnm = vnet_get_main();
206  vnet_sw_interface_t * si;
207  u8 * flags = 0;
208 
209  if (! n)
210  return format (s, "%=12s%=20s%=6s%=20s%=40s", "Time", "Address", "Flags", "Link layer", "Interface");
211 
213  flags = format(flags, "G");
214 
216  flags = format(flags, "S");
217 
218  si = vnet_get_sw_interface (vnm, n->key.sw_if_index);
219  s = format (s, "%=12U%=20U%=6s%=20U%=40U",
222  flags ? (char *)flags : "",
225 
226  vec_free(flags);
227  return s;
228 }
229 
230 static clib_error_t *
232  u32 sw_if_index,
233  u32 flags)
234 {
236  ip6_neighbor_t * n;
237 
238  if (! (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
239  {
240  u32 i, * to_delete = 0;
241 
242  pool_foreach (n, nm->neighbor_pool, ({
243  if (n->key.sw_if_index == sw_if_index)
244  vec_add1 (to_delete, n - nm->neighbor_pool);
245  }));
246 
247  for (i = 0; i < vec_len (to_delete); i++)
248  {
249  n = pool_elt_at_index (nm->neighbor_pool, to_delete[i]);
250  mhash_unset (&nm->neighbor_index_by_key, &n->key, 0);
251  pool_put (nm->neighbor_pool, n);
252  }
253 
254  vec_free (to_delete);
255  }
256 
257  return 0;
258 }
259 
261 
262 static void unset_random_neighbor_entry (void)
263 {
265  vnet_main_t * vnm = vnet_get_main();
266  vlib_main_t * vm = vnm->vlib_main;
267  ip6_neighbor_t * e;
268  u32 index;
269 
271  nm->neighbor_delete_rotor = index;
272 
273  /* Try again from elt 0, could happen if an intfc goes down */
274  if (index == ~0)
275  {
277  nm->neighbor_delete_rotor = index;
278  }
279 
280  /* Nothing left in the pool */
281  if (index == ~0)
282  return;
283 
284  e = pool_elt_at_index (nm->neighbor_pool, index);
285 
287  &e->key.ip6_address,
290 }
291 
292 typedef struct {
295  u8 link_layer_address[6];
299 
300 #if DPDK > 0
303 
304 static void set_unset_ip6_neighbor_rpc
306  u32 sw_if_index,
307  ip6_address_t * a,
308  u8 *link_layer_addreess,
309  int is_add, int is_static)
310 {
312  void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length);
313 
314  args.sw_if_index = sw_if_index;
315  args.is_add = is_add;
316  args.is_static = is_static;
317  clib_memcpy (&args.addr, a, sizeof (*a));
318  clib_memcpy (args.link_layer_address, link_layer_addreess, 6);
319 
321  (u8 *) &args, sizeof (args));
322 }
323 #endif
324 
325 int
327  u32 sw_if_index,
328  ip6_address_t * a,
329  u8 * link_layer_address,
330  uword n_bytes_link_layer_address,
331  int is_static)
332 {
333  vnet_main_t * vnm = vnet_get_main();
336  ip6_neighbor_t * n = 0;
337  ip6_main_t * im = &ip6_main;
338  ip_lookup_main_t * lm = &im->lookup_main;
339  int make_new_nd_cache_entry=1;
340  uword * p;
341  u32 next_index;
342  u32 adj_index;
343  ip_adjacency_t *existing_adj;
345 
346 #if DPDK > 0
347  if (os_get_cpu_number())
348  {
349  set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, link_layer_address,
350  1 /* set new neighbor */, is_static);
351  return 0;
352  }
353 #endif
354 
355  k.sw_if_index = sw_if_index;
356  k.ip6_address = a[0];
357  k.pad = 0;
358 
360 
361  p = mhash_get (&nm->neighbor_index_by_key, &k);
362  if (p) {
363  n = pool_elt_at_index (nm->neighbor_pool, p[0]);
364  /* Refuse to over-write static neighbor entry. */
365  if (!is_static &&
367  return -2;
368  make_new_nd_cache_entry = 0;
369  }
370 
371  /* Note: always install the route. It might have been deleted */
373  ip_adjacency_t adj;
374 
375  memset (&adj, 0, sizeof(adj));
377  adj.explicit_fib_index = ~0;
378 
380  (vnm,
381  VNET_L3_PACKET_TYPE_IP6,
382  sw_if_index,
383  ip6_rewrite_node.index,
384  link_layer_address,
385  &adj.rewrite_header,
386  sizeof (adj.rewrite_data));
387 
388  /* result of this lookup should be next-hop adjacency */
389  adj_index = ip6_fib_lookup_with_table (im, im->fib_index_by_sw_if_index[sw_if_index], a);
390  existing_adj = ip_get_adjacency(lm, adj_index);
391 
392  if (existing_adj->lookup_next_index == IP_LOOKUP_NEXT_ARP &&
393  existing_adj->arp.next_hop.ip6.as_u64[0] == a->as_u64[0] &&
394  existing_adj->arp.next_hop.ip6.as_u64[1] == a->as_u64[1])
395  {
396  u32 * ai;
397  u32 * adjs = 0;
398 
399  if (n)
400  adjs = vec_dup(n->adjacencies);
401  else
402  clib_warning ("ip6 neighbor n not set");
403 
404  /* Update all adj assigned to this arp entry */
405  vec_foreach(ai, adjs)
406  {
407  int i;
408  ip_adjacency_t * uadj = ip_get_adjacency(lm, *ai);
409  for (i = 0; i < uadj->n_adj; i++)
410  if (uadj[i].lookup_next_index == IP_LOOKUP_NEXT_ARP &&
411  uadj[i].arp.next_hop.ip6.as_u64[0] == a->as_u64[0] &&
412  uadj[i].arp.next_hop.ip6.as_u64[1] == a->as_u64[1])
413  ip_update_adjacency (lm, *ai + i, &adj);
414  }
415  vec_free(adjs);
416  }
417  else
418  {
419  /* create new adj */
420  args.table_index_or_table_id = im->fib_index_by_sw_if_index[sw_if_index];
422  args.dst_address = a[0];
423  args.dst_address_length = 128;
424  args.adj_index = ~0;
425  args.add_adj = &adj;
426  args.n_add_adj = 1;
427  ip6_add_del_route (im, &args);
428  }
429 
430  if (make_new_nd_cache_entry) {
431  pool_get (nm->neighbor_pool, n);
432  mhash_set (&nm->neighbor_index_by_key, &k, n - nm->neighbor_pool,
433  /* old value */ 0);
434  n->key = k;
435  }
436 
437  /* Update time stamp and ethernet address. */
438  clib_memcpy (n->link_layer_address, link_layer_address, n_bytes_link_layer_address);
440  if (is_static)
442 
443  /* Customer(s) waiting for this address to be resolved? */
445  if (p == 0)
446  goto out;
447 
448  next_index = p[0];
449 
450  while (next_index != (u32)~0)
451  {
452  pr = pool_elt_at_index (nm->pending_resolutions, next_index);
454  pr->type_opaque,
455  pr->data);
456  next_index = pr->next_index;
457  pool_put (nm->pending_resolutions, pr);
458  }
459 
461 
462 out:
464  return 0;
465 }
466 
467 int
469  u32 sw_if_index,
470  ip6_address_t * a,
471  u8 * link_layer_address,
472  uword n_bytes_link_layer_address)
473 {
476  ip6_neighbor_t * n;
477  ip6_main_t * im = &ip6_main;
479  uword * p;
480  int rv = 0;
481 
482 #if DPDK > 0
483  if (os_get_cpu_number())
484  {
485  set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, link_layer_address,
486  0 /* unset */, 0);
487  return 0;
488  }
489 #endif
490 
491  k.sw_if_index = sw_if_index;
492  k.ip6_address = a[0];
493  k.pad = 0;
494 
496 
497  p = mhash_get (&nm->neighbor_index_by_key, &k);
498  if (p == 0)
499  {
500  rv = -1;
501  goto out;
502  }
503 
504  n = pool_elt_at_index (nm->neighbor_pool, p[0]);
505  mhash_unset (&nm->neighbor_index_by_key, &n->key, 0);
506  pool_put (nm->neighbor_pool, n);
507 
508  args.table_index_or_table_id = im->fib_index_by_sw_if_index[sw_if_index];
511  args.dst_address = a[0];
512  args.dst_address_length = 128;
513  args.adj_index = ~0;
514  args.add_adj = NULL;
515  args.n_add_adj = 0;
516  ip6_add_del_route (im, &args);
517  out:
519  return rv;
520 }
521 
522 
523 u32
524 vnet_ip6_neighbor_glean_add(u32 fib_index, void * next_hop_arg)
525 {
527  ip6_main_t * im = &ip6_main;
528  ip_lookup_main_t * lm = &im->lookup_main;
529  ip6_address_t * next_hop = next_hop_arg;
530  ip_adjacency_t add_adj, *adj;
532  ip6_neighbor_t * n;
534  u32 adj_index;
535 
536  adj_index = ip6_fib_lookup_with_table(im, fib_index, next_hop);
537  adj = ip_get_adjacency(lm, adj_index);
538 
539  if (!adj || adj->lookup_next_index != IP_LOOKUP_NEXT_ARP)
540  return ~0;
541 
542  if (adj->arp.next_hop.ip6.as_u64[0] ||
543  adj->arp.next_hop.ip6.as_u64[1])
544  return adj_index;
545 
546  k.sw_if_index = adj->rewrite_header.sw_if_index;
547  k.ip6_address = *next_hop;
548  k.pad = 0;
549  if (mhash_get (&nm->neighbor_index_by_key, &k))
550  return adj_index;
551 
552  pool_get (nm->neighbor_pool, n);
553  mhash_set (&nm->neighbor_index_by_key, &k, n - nm->neighbor_pool, /* old value */ 0);
554  n->key = k;
557 
558  memset(&args, 0, sizeof(args));
559  memcpy(&add_adj, adj, sizeof(add_adj));
560  add_adj.arp.next_hop.ip6 = *next_hop; /* install neighbor /128 route */
561  args.table_index_or_table_id = fib_index;
563  args.dst_address = *next_hop;
564  args.dst_address_length = 128;
565  args.adj_index = ~0;
566  args.add_adj = &add_adj;
567  args.n_add_adj = 1;
568  ip6_add_del_route (im, &args);
569  return ip6_fib_lookup_with_table (im, fib_index, next_hop);
570 }
571 
572 #if DPDK > 0
575 {
576  vlib_main_t * vm = vlib_get_main();
577  if (a->is_add)
579  a->link_layer_address, 6, a->is_static);
580  else
582  a->link_layer_address, 6);
583 }
584 #endif
585 
586 static int
587 ip6_neighbor_sort (void *a1, void *a2)
588 {
589  vnet_main_t * vnm = vnet_get_main();
590  ip6_neighbor_t * n1 = a1, * n2 = a2;
591  int cmp;
592  cmp = vnet_sw_interface_compare (vnm, n1->key.sw_if_index,
593  n2->key.sw_if_index);
594  if (! cmp)
595  cmp = ip6_address_compare (&n1->key.ip6_address, &n2->key.ip6_address);
596  return cmp;
597 }
598 
599 static clib_error_t *
601  unformat_input_t * input,
602  vlib_cli_command_t * cmd)
603 {
604  vnet_main_t * vnm = vnet_get_main();
606  ip6_neighbor_t * n, * ns;
607  clib_error_t * error = 0;
608  u32 sw_if_index;
609 
610  /* Filter entries by interface if given. */
611  sw_if_index = ~0;
612  (void) unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index);
613 
614  ns = 0;
615  pool_foreach (n, nm->neighbor_pool, ({ vec_add1 (ns, n[0]); }));
618  vec_foreach (n, ns) {
619  if (sw_if_index != ~0 && n->key.sw_if_index != sw_if_index)
620  continue;
622  }
623  vec_free (ns);
624 
625  return error;
626 }
627 
629  .path = "show ip6 neighbors",
630  .function = show_ip6_neighbors,
631  .short_help = "Show ip6 neighbors",
632 };
633 
634 static clib_error_t *
636  unformat_input_t * input,
637  vlib_cli_command_t * cmd)
638 {
639  vnet_main_t * vnm = vnet_get_main();
641  u8 mac_address[6];
642  int addr_valid = 0;
643  int is_del = 0;
644  int is_static = 0;
645  u32 sw_if_index;
646 
647  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
648  {
649  /* intfc, ip6-address, mac-address */
650  if (unformat (input, "%U %U %U",
651  unformat_vnet_sw_interface, vnm, &sw_if_index,
652  unformat_ip6_address, &addr,
653  unformat_ethernet_address, mac_address))
654  addr_valid = 1;
655 
656  else if (unformat (input, "delete") || unformat (input, "del"))
657  is_del = 1;
658  else if (unformat (input, "static"))
659  is_static = 1;
660  else
661  break;
662  }
663 
664  if (!addr_valid)
665  return clib_error_return (0, "Missing interface, ip6 or hw address");
666 
667  if (!is_del)
668  vnet_set_ip6_ethernet_neighbor (vm, sw_if_index, &addr,
669  mac_address, sizeof(mac_address), is_static);
670  else
671  vnet_unset_ip6_ethernet_neighbor (vm, sw_if_index, &addr,
672  mac_address, sizeof(mac_address));
673  return 0;
674 }
675 
677  .path = "set ip6 neighbor",
678  .function = set_ip6_neighbor,
679  .short_help = "set ip6 neighbor [del] <intfc> <ip6-address> <mac-address> [static]",
680 };
681 
682 typedef enum {
687 
690  vlib_node_runtime_t * node,
691  vlib_frame_t * frame,
692  uword is_solicitation)
693 {
694  vnet_main_t * vnm = vnet_get_main();
695  ip6_main_t * im = &ip6_main;
696  ip_lookup_main_t * lm = &im->lookup_main;
697  uword n_packets = frame->n_vectors;
698  u32 * from, * to_next;
699  u32 n_left_from, n_left_to_next, next_index, n_advertisements_sent;
702  int bogus_length;
703 
704  from = vlib_frame_vector_args (frame);
705  n_left_from = n_packets;
706  next_index = node->cached_next_index;
707 
708  if (node->flags & VLIB_NODE_FLAG_TRACE)
709  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
710  /* stride */ 1,
711  sizeof (icmp6_input_trace_t));
712 
713  option_type =
714  (is_solicitation
715  ? ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address
716  : ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address);
717  n_advertisements_sent = 0;
718 
719  while (n_left_from > 0)
720  {
721  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
722 
723  while (n_left_from > 0 && n_left_to_next > 0)
724  {
725  vlib_buffer_t * p0;
726  ip6_header_t * ip0;
727  icmp6_neighbor_solicitation_or_advertisement_header_t * h0;
728  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t * o0;
729  u32 bi0, options_len0, sw_if_index0, next0, error0;
730  u32 ip6_sadd_link_local, ip6_sadd_unspecified;
731  int is_rewrite0;
732  u32 ni0;
733 
734  bi0 = to_next[0] = from[0];
735 
736  from += 1;
737  to_next += 1;
738  n_left_from -= 1;
739  n_left_to_next -= 1;
740 
741  p0 = vlib_get_buffer (vm, bi0);
742  ip0 = vlib_buffer_get_current (p0);
743  h0 = ip6_next_header (ip0);
744  options_len0 = clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]);
745 
746  error0 = ICMP6_ERROR_NONE;
747  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
748  ip6_sadd_link_local = ip6_address_is_link_local_unicast(&ip0->src_address);
749  ip6_sadd_unspecified = ip6_address_is_unspecified (&ip0->src_address);
750 
751  /* Check that source address is unspecified, link-local or else on-link. */
752  if (!ip6_sadd_unspecified && !ip6_sadd_link_local)
753  {
754  u32 src_adj_index0 = ip6_src_lookup_for_packet (im, p0, ip0);
755  ip_adjacency_t * adj0 = ip_get_adjacency (&im->lookup_main, src_adj_index0);
756 
757  /* Allow all realistic-looking rewrite adjacencies to pass */
758  ni0 = adj0->lookup_next_index;
759  is_rewrite0 = (ni0 >= IP_LOOKUP_NEXT_ARP) &&
760  (ni0 < IP6_LOOKUP_N_NEXT);
761 
762  error0 = ((adj0->rewrite_header.sw_if_index != sw_if_index0
763  || ! is_rewrite0)
764  ? ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_NOT_ON_LINK
765  : error0);
766  }
767 
768  o0 = (void *) (h0 + 1);
769  o0 = ((options_len0 == 8 && o0->header.type == option_type
770  && o0->header.n_data_u64s == 1) ? o0 : 0);
771 
772  /* If src address unspecified or link local, donot learn neighbor MAC */
773  if (PREDICT_TRUE (error0 == ICMP6_ERROR_NONE && o0 != 0 &&
774  !ip6_sadd_unspecified && !ip6_sadd_link_local))
775  {
777  if (nm->limit_neighbor_cache_size &&
781  vm, sw_if_index0,
782  is_solicitation ? &ip0->src_address : &h0->target_address,
783  o0->ethernet_address, sizeof (o0->ethernet_address), 0);
784  }
785 
786  if (is_solicitation && error0 == ICMP6_ERROR_NONE)
787  {
788  /* Check that target address is one that we know about. */
790  ip6_address_fib_t ip6_af0;
791  void * oldheap;
792 
793  ip6_addr_fib_init (&ip6_af0, &h0->target_address,
795  sw_if_index0));
796 
797  /* Gross kludge, "thank you" MJ, don't even ask */
798  oldheap = clib_mem_set_heap (clib_per_cpu_mheaps[0]);
799  ia0 = ip_get_interface_address (lm, &ip6_af0);
800  clib_mem_set_heap (oldheap);
801  error0 = ia0 == 0 ?
802  ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_UNKNOWN : error0;
803  }
804 
805  if (is_solicitation)
806  next0 = (error0 != ICMP6_ERROR_NONE
809  else
810  {
811  next0 = 0;
812  error0 = error0 == ICMP6_ERROR_NONE ?
813  ICMP6_ERROR_NEIGHBOR_ADVERTISEMENTS_RX : error0;
814  }
815 
816  if (is_solicitation && error0 == ICMP6_ERROR_NONE)
817  {
818  vnet_sw_interface_t * sw_if0;
819  ethernet_interface_t * eth_if0;
820  ethernet_header_t *eth0;
821 
822  /* dst address is either source address or the all-nodes mcast addr */
823  if(!ip6_sadd_unspecified)
824  ip0->dst_address = ip0->src_address;
825  else
827  IP6_MULTICAST_SCOPE_link_local,
828  IP6_MULTICAST_GROUP_ID_all_hosts);
829 
830  ip0->src_address = h0->target_address;
831  ip0->hop_limit = 255;
832  h0->icmp.type = ICMP6_neighbor_advertisement;
833 
834  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index0);
836  eth_if0 = ethernet_get_interface (&ethernet_main, sw_if0->hw_if_index);
837  if (eth_if0 && o0)
838  {
839  clib_memcpy (o0->ethernet_address, eth_if0->address, 6);
840  o0->header.type =
841  ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address;
842  }
843 
844  h0->advertisement_flags = clib_host_to_net_u32
847 
848  h0->icmp.checksum = 0;
849  h0->icmp.checksum =
850  ip6_tcp_udp_icmp_compute_checksum (vm, p0, ip0,
851  &bogus_length);
852  ASSERT(bogus_length == 0);
853 
854  /* Reuse current MAC header, copy SMAC to DMAC and
855  * interface MAC to SMAC */
857  eth0 = vlib_buffer_get_current(p0);
858  clib_memcpy(eth0->dst_address, eth0->src_address, 6);
859  clib_memcpy(eth0->src_address, eth_if0->address, 6);
860 
861  /* Setup input and output sw_if_index for packet */
862  ASSERT(vnet_buffer(p0)->sw_if_index[VLIB_RX] == sw_if_index0);
863  vnet_buffer(p0)->sw_if_index[VLIB_TX] = sw_if_index0;
864  vnet_buffer(p0)->sw_if_index[VLIB_RX] =
866 
867  n_advertisements_sent++;
868  }
869 
870  p0->error = error_node->errors[error0];
871 
872  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
873  to_next, n_left_to_next,
874  bi0, next0);
875  }
876 
877  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
878  }
879 
880  /* Account for advertisements sent. */
881  vlib_error_count (vm, error_node->node_index, ICMP6_ERROR_NEIGHBOR_ADVERTISEMENTS_TX, n_advertisements_sent);
882 
883  return frame->n_vectors;
884 }
885 
886 /* for "syslogging" - use elog for now */
887 #define foreach_log_level \
888  _ (DEBUG, "DEBUG") \
889  _ (INFO, "INFORMATION") \
890  _ (NOTICE, "NOTICE") \
891  _ (WARNING, "WARNING") \
892  _ (ERR, "ERROR") \
893  _ (CRIT, "CRITICAL") \
894  _ (ALERT, "ALERT") \
895  _ (EMERG, "EMERGENCY")
896 
897 typedef enum {
898 #define _(f,s) LOG_##f,
900 #undef _
901 } log_level_t;
902 
903 static char * log_level_strings[] = {
904 #define _(f,s) s,
906 #undef _
907 };
908 
909 static int logmask = 1 << LOG_DEBUG;
910 
911 static void
912 ip6_neighbor_syslog(vlib_main_t *vm, int priority, char * fmt, ...)
913 {
914  /* just use elog for now */
915  u8 *what;
916  va_list va;
917 
918  if( (priority > LOG_EMERG) ||
919  !(logmask & (1 << priority)))
920  return;
921 
922  va_start (va, fmt);
923  if(fmt)
924  {
925  what = va_format (0, fmt, &va);
926 
927  ELOG_TYPE_DECLARE (e) = {
928  .format = "ip6 nd: (%s): %s",
929  .format_args = "T4T4",
930  };
931  struct { u32 s[2]; } * ed;
932  ed = ELOG_DATA (&vm->elog_main, e);
933  ed->s[0] = elog_string(&vm->elog_main, log_level_strings[priority]);
934  ed->s[1] = elog_string(&vm->elog_main, (char *)what);
935  }
936  va_end (va);
937  return;
938 }
939 
940 /* ipv6 neighbor discovery - router advertisements */
941 typedef enum {
947 
950  vlib_node_runtime_t * node,
951  vlib_frame_t * frame)
952 {
953  vnet_main_t * vnm = vnet_get_main();
954  ip6_main_t * im = &ip6_main;
956  uword n_packets = frame->n_vectors;
957  u32 * from, * to_next;
958  u32 n_left_from, n_left_to_next, next_index;
959  u32 n_advertisements_sent = 0;
960  int bogus_length;
961 
963 
965 
966  from = vlib_frame_vector_args (frame);
967  n_left_from = n_packets;
968  next_index = node->cached_next_index;
969 
970  if (node->flags & VLIB_NODE_FLAG_TRACE)
971  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
972  /* stride */ 1,
973  sizeof (icmp6_input_trace_t));
974 
975  /* source may append his LL address */
976  option_type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address;
977 
978  while (n_left_from > 0)
979  {
980  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
981 
982  while (n_left_from > 0 && n_left_to_next > 0)
983  {
984  vlib_buffer_t * p0;
985  ip6_header_t * ip0;
986  ip6_radv_t *radv_info = 0;
987 
988  icmp6_neighbor_discovery_header_t * h0;
989  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t * o0;
990 
991  u32 bi0, options_len0, sw_if_index0, next0, error0;
992  u32 is_solicitation = 1, is_dropped = 0;
993  u32 is_unspecified, is_link_local;
994 
995  bi0 = to_next[0] = from[0];
996 
997  from += 1;
998  to_next += 1;
999  n_left_from -= 1;
1000  n_left_to_next -= 1;
1001 
1002  p0 = vlib_get_buffer (vm, bi0);
1003  ip0 = vlib_buffer_get_current (p0);
1004  h0 = ip6_next_header (ip0);
1005  options_len0 = clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]);
1006  is_unspecified = ip6_address_is_unspecified (&ip0->src_address);
1007  is_link_local = ip6_address_is_link_local_unicast (&ip0->src_address);
1008 
1009  error0 = ICMP6_ERROR_NONE;
1010  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1011 
1012  /* check if solicitation (not from nd_timer node) */
1014  is_solicitation = 0;
1015 
1016  /* Check that source address is unspecified, link-local or else on-link. */
1017  if (!is_unspecified && !is_link_local)
1018  {
1019  u32 src_adj_index0 = ip6_src_lookup_for_packet (im, p0, ip0);
1020  ip_adjacency_t * adj0 = ip_get_adjacency (&im->lookup_main, src_adj_index0);
1021 
1022  error0 = ((adj0->rewrite_header.sw_if_index != sw_if_index0
1025  ? ICMP6_ERROR_ROUTER_SOLICITATION_SOURCE_NOT_ON_LINK
1026  : error0);
1027  }
1028 
1029  /* check for source LL option and process */
1030  o0 = (void *) (h0 + 1);
1031  o0 = ((options_len0 == 8
1032  && o0->header.type == option_type
1033  && o0->header.n_data_u64s == 1)
1034  ? o0
1035  : 0);
1036 
1037  /* if src address unspecified IGNORE any options */
1038  if (PREDICT_TRUE (error0 == ICMP6_ERROR_NONE && o0 != 0 &&
1039  !is_unspecified && !is_link_local)) {
1041  if (nm->limit_neighbor_cache_size &&
1044 
1045  vnet_set_ip6_ethernet_neighbor (vm, sw_if_index0,
1046  &ip0->src_address,
1047  o0->ethernet_address,
1048  sizeof (o0->ethernet_address), 0);
1049  }
1050 
1051  /* default is to drop */
1053 
1054  if (error0 == ICMP6_ERROR_NONE)
1055  {
1056  vnet_sw_interface_t * sw_if0;
1057  ethernet_interface_t * eth_if0;
1058  u32 adj_index0;
1059 
1060  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index0);
1062  eth_if0 = ethernet_get_interface (&ethernet_main, sw_if0->hw_if_index);
1063 
1064  /* only support ethernet interface type for now */
1065  error0 = (!eth_if0) ? ICMP6_ERROR_ROUTER_SOLICITATION_UNSUPPORTED_INTF : error0;
1066 
1067  if (error0 == ICMP6_ERROR_NONE)
1068  {
1069  u32 ri;
1070 
1071  /* adjust the sizeof the buffer to just include the ipv6 header */
1072  p0->current_length -= (options_len0 + sizeof(icmp6_neighbor_discovery_header_t));
1073 
1074  /* look up the radv_t information for this interface */
1076 
1077  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index0];
1078 
1079  if(ri != ~0)
1080  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
1081 
1082  error0 = ((!radv_info) ? ICMP6_ERROR_ROUTER_SOLICITATION_RADV_NOT_CONFIG : error0);
1083 
1084  if (error0 == ICMP6_ERROR_NONE)
1085  {
1086  f64 now = vlib_time_now (vm);
1087 
1088  /* for solicited adverts - need to rate limit */
1089  if(is_solicitation)
1090  {
1091  if( (now - radv_info->last_radv_time) < MIN_DELAY_BETWEEN_RAS )
1092  is_dropped = 1;
1093  else
1094  radv_info->last_radv_time = now;
1095  }
1096 
1097  /* send now */
1098  icmp6_router_advertisement_header_t rh;
1099 
1100  rh.icmp.type = ICMP6_router_advertisement;
1101  rh.icmp.code = 0;
1102  rh.icmp.checksum = 0;
1103 
1104  rh.current_hop_limit = radv_info->curr_hop_limit;
1105  rh.router_lifetime_in_sec = clib_host_to_net_u16(radv_info->adv_router_lifetime_in_sec);
1106  rh.time_in_msec_between_retransmitted_neighbor_solicitations =
1107  clib_host_to_net_u32(radv_info->adv_time_in_msec_between_retransmitted_neighbor_solicitations);
1108  rh.neighbor_reachable_time_in_msec =
1109  clib_host_to_net_u32(radv_info->adv_neighbor_reachable_time_in_msec);
1110 
1112  rh.flags |= ( (radv_info->adv_other_flag) ? ICMP6_ROUTER_DISCOVERY_FLAG_OTHER_CONFIG_VIA_DHCP : 0);
1113 
1114 
1115  u16 payload_length = sizeof(icmp6_router_advertisement_header_t);
1116 
1118  p0->free_list_index,
1119  bi0,
1120  (void *)&rh, sizeof(icmp6_router_advertisement_header_t));
1121 
1122  if(radv_info->adv_link_layer_address)
1123  {
1124  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t h;
1125 
1126  h.header.type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address;
1127  h.header.n_data_u64s = 1;
1128 
1129  /* copy ll address */
1130  clib_memcpy(&h.ethernet_address[0], eth_if0->address, 6);
1131 
1133  p0->free_list_index,
1134  bi0,
1135  (void *)&h, sizeof(icmp6_neighbor_discovery_ethernet_link_layer_address_option_t));
1136 
1137  payload_length += sizeof(icmp6_neighbor_discovery_ethernet_link_layer_address_option_t);
1138  }
1139 
1140  /* add MTU option */
1141  if(radv_info->adv_link_mtu)
1142  {
1143  icmp6_neighbor_discovery_mtu_option_t h;
1144 
1145  h.unused = 0;
1146  h.mtu = clib_host_to_net_u32(radv_info->adv_link_mtu);
1147  h.header.type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_mtu;
1148  h.header.n_data_u64s = 1;
1149 
1150  payload_length += sizeof( icmp6_neighbor_discovery_mtu_option_t);
1151 
1153  p0->free_list_index,
1154  bi0,
1155  (void *)&h, sizeof(icmp6_neighbor_discovery_mtu_option_t));
1156  }
1157 
1158  /* add advertised prefix options */
1159  ip6_radv_prefix_t *pr_info;
1160 
1161  pool_foreach (pr_info, radv_info->adv_prefixes_pool, ({
1162 
1163  if(pr_info->enabled &&
1164  (!pr_info->decrement_lifetime_flag || (pr_info->pref_lifetime_expires >0)))
1165  {
1166  /* advertise this prefix */
1167  icmp6_neighbor_discovery_prefix_information_option_t h;
1168 
1169  h.header.type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_prefix_information;
1170  h.header.n_data_u64s = (sizeof(icmp6_neighbor_discovery_prefix_information_option_t) >> 3);
1171 
1172  h.dst_address_length = pr_info->prefix_len;
1173 
1174  h.flags = (pr_info->adv_on_link_flag) ? ICMP6_NEIGHBOR_DISCOVERY_PREFIX_INFORMATION_FLAG_ON_LINK : 0;
1175  h.flags |= (pr_info->adv_autonomous_flag) ? ICMP6_NEIGHBOR_DISCOVERY_PREFIX_INFORMATION_AUTO : 0;
1176 
1177  if(radv_info->cease_radv && pr_info->deprecated_prefix_flag)
1178  {
1179  h.valid_time = clib_host_to_net_u32(MIN_ADV_VALID_LIFETIME);
1180  h.preferred_time = 0;
1181  }
1182  else
1183  {
1184  if(pr_info->decrement_lifetime_flag)
1185  {
1186  pr_info->adv_valid_lifetime_in_secs = ((pr_info->valid_lifetime_expires > now)) ?
1187  (pr_info->valid_lifetime_expires - now) : 0;
1188 
1189  pr_info->adv_pref_lifetime_in_secs = ((pr_info->pref_lifetime_expires > now)) ?
1190  (pr_info->pref_lifetime_expires - now) : 0;
1191  }
1192 
1193  h.valid_time = clib_host_to_net_u32(pr_info->adv_valid_lifetime_in_secs);
1194  h.preferred_time = clib_host_to_net_u32(pr_info->adv_pref_lifetime_in_secs) ;
1195  }
1196  h.unused = 0;
1197 
1198  clib_memcpy(&h.dst_address, &pr_info->prefix, sizeof(ip6_address_t));
1199 
1200  payload_length += sizeof( icmp6_neighbor_discovery_prefix_information_option_t);
1201 
1202  vlib_buffer_add_data (vm,
1203  p0->free_list_index,
1204  bi0,
1205  (void *)&h, sizeof(icmp6_neighbor_discovery_prefix_information_option_t));
1206 
1207  }
1208  }));
1209 
1210  /* add additional options before here */
1211 
1212  /* finish building the router advertisement... */
1213  if(!is_unspecified && radv_info->send_unicast)
1214  {
1215  ip0->dst_address = ip0->src_address;
1216  }
1217  else
1218  {
1219  /* target address is all-nodes mcast addr */
1221  IP6_MULTICAST_SCOPE_link_local,
1222  IP6_MULTICAST_GROUP_ID_all_hosts);
1223  }
1224 
1225  /* source address MUST be the link-local address */
1226  ip0->src_address = radv_info->link_local_address;
1227 
1228  ip0->hop_limit = 255;
1229  ip0->payload_length = clib_host_to_net_u16 (payload_length);
1230 
1231  icmp6_router_advertisement_header_t * rh0 = (icmp6_router_advertisement_header_t *)(ip0 + 1);
1232  rh0->icmp.checksum =
1233  ip6_tcp_udp_icmp_compute_checksum (vm, p0, ip0,
1234  &bogus_length);
1235  ASSERT(bogus_length == 0);
1236 
1237  /* setup output if and adjacency */
1238  vnet_buffer (p0)->sw_if_index[VLIB_RX] =
1240 
1241  if (is_solicitation)
1242  {
1243  ethernet_header_t *eth0;
1244  /* Reuse current MAC header, copy SMAC to DMAC and
1245  * interface MAC to SMAC */
1246  vlib_buffer_reset (p0);
1247  eth0 = vlib_buffer_get_current(p0);
1248  clib_memcpy(eth0->dst_address, eth0->src_address, 6);
1249  clib_memcpy(eth0->src_address, eth_if0->address, 6);
1250  next0 = is_dropped ?
1252  vnet_buffer(p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1253  }
1254  else
1255  {
1256  adj_index0 = radv_info->all_nodes_adj_index;
1257  if (adj_index0 == 0)
1258  error0 = ICMP6_ERROR_DST_LOOKUP_MISS;
1259  else
1260  {
1261  ip_adjacency_t * adj0 = ip_get_adjacency (&im->lookup_main, adj_index0);
1262  error0 =
1263  ((adj0->rewrite_header.sw_if_index != sw_if_index0
1265  ? ICMP6_ERROR_ROUTER_SOLICITATION_DEST_UNKNOWN
1266  : error0);
1267  next0 = is_dropped ?
1269  vnet_buffer (p0)->ip.adj_index[VLIB_RX] = adj_index0;
1270  }
1271  }
1272 
1273  radv_info->n_solicitations_dropped += is_dropped;
1274  radv_info->n_solicitations_rcvd += is_solicitation;
1275 
1276  if((error0 == ICMP6_ERROR_NONE) && !is_dropped)
1277  {
1278  radv_info->n_advertisements_sent++;
1279  n_advertisements_sent++;
1280  }
1281  }
1282  }
1283  }
1284 
1285  p0->error = error_node->errors[error0];
1286 
1287  if(error0 != ICMP6_ERROR_NONE)
1288  vlib_error_count (vm, error_node->node_index, error0, 1);
1289 
1290  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1291  to_next, n_left_to_next,
1292  bi0, next0);
1293 
1294  }
1295 
1296  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1297  }
1298 
1299  /* Account for router advertisements sent. */
1300  vlib_error_count (vm, error_node->node_index, ICMP6_ERROR_ROUTER_ADVERTISEMENTS_TX, n_advertisements_sent);
1301 
1302  return frame->n_vectors;
1303 }
1304 
1305  /* validate advertised info for consistancy (see RFC-4861 section 6.2.7) - log any inconsistencies, packet will always be dropped */
1308  vlib_node_runtime_t * node,
1309  vlib_frame_t * frame)
1310 {
1311  vnet_main_t * vnm = vnet_get_main();
1313  uword n_packets = frame->n_vectors;
1314  u32 * from, * to_next;
1315  u32 n_left_from, n_left_to_next, next_index;
1316  u32 n_advertisements_rcvd = 0;
1317 
1319 
1320  from = vlib_frame_vector_args (frame);
1321  n_left_from = n_packets;
1322  next_index = node->cached_next_index;
1323 
1324  if (node->flags & VLIB_NODE_FLAG_TRACE)
1325  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
1326  /* stride */ 1,
1327  sizeof (icmp6_input_trace_t));
1328 
1329  while (n_left_from > 0)
1330  {
1331  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1332 
1333  while (n_left_from > 0 && n_left_to_next > 0)
1334  {
1335  vlib_buffer_t * p0;
1336  ip6_header_t * ip0;
1337  ip6_radv_t *radv_info = 0;
1338  icmp6_router_advertisement_header_t * h0;
1339  u32 bi0, options_len0, sw_if_index0, next0, error0;
1340 
1341  bi0 = to_next[0] = from[0];
1342 
1343  from += 1;
1344  to_next += 1;
1345  n_left_from -= 1;
1346  n_left_to_next -= 1;
1347 
1348  p0 = vlib_get_buffer (vm, bi0);
1349  ip0 = vlib_buffer_get_current (p0);
1350  h0 = ip6_next_header (ip0);
1351  options_len0 = clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]);
1352 
1353  error0 = ICMP6_ERROR_NONE;
1354  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1355 
1356  /* Check that source address is link-local*/
1357  error0 = (!ip6_address_is_link_local_unicast (&ip0->src_address)) ?
1358  ICMP6_ERROR_ROUTER_ADVERTISEMENT_SOURCE_NOT_LINK_LOCAL : error0;
1359 
1360  /* default is to drop */
1362 
1363  n_advertisements_rcvd++;
1364 
1365  if (error0 == ICMP6_ERROR_NONE)
1366  {
1367  vnet_sw_interface_t * sw_if0;
1368  ethernet_interface_t * eth_if0;
1369 
1370  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index0);
1372  eth_if0 = ethernet_get_interface (&ethernet_main, sw_if0->hw_if_index);
1373 
1374  /* only support ethernet interface type for now */
1375  error0 = (!eth_if0) ? ICMP6_ERROR_ROUTER_SOLICITATION_UNSUPPORTED_INTF : error0;
1376 
1377  if (error0 == ICMP6_ERROR_NONE)
1378  {
1379  u32 ri;
1380 
1381  /* look up the radv_t information for this interface */
1383 
1384  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index0];
1385 
1386  if(ri != ~0)
1387  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
1388 
1389  error0 = ((!radv_info) ? ICMP6_ERROR_ROUTER_SOLICITATION_RADV_NOT_CONFIG : error0);
1390 
1391  if (error0 == ICMP6_ERROR_NONE)
1392  {
1393  /* validate advertised information */
1394  if((h0->current_hop_limit && radv_info->curr_hop_limit) &&
1395  (h0->current_hop_limit != radv_info->curr_hop_limit))
1396  {
1397  ip6_neighbor_syslog(vm, LOG_WARNING,
1398  "our AdvCurHopLimit on %U doesn't agree with %U",
1399  format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address);
1400  }
1401 
1403  radv_info->adv_managed_flag)
1404  {
1405  ip6_neighbor_syslog(vm, LOG_WARNING,
1406  "our AdvManagedFlag on %U doesn't agree with %U",
1407  format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address);
1408  }
1409 
1411  radv_info->adv_other_flag)
1412  {
1413  ip6_neighbor_syslog(vm, LOG_WARNING,
1414  "our AdvOtherConfigFlag on %U doesn't agree with %U",
1415  format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address);
1416  }
1417 
1418  if((h0->time_in_msec_between_retransmitted_neighbor_solicitations &&
1420  (h0->time_in_msec_between_retransmitted_neighbor_solicitations !=
1421  clib_host_to_net_u32(radv_info->adv_time_in_msec_between_retransmitted_neighbor_solicitations)))
1422  {
1423  ip6_neighbor_syslog(vm, LOG_WARNING,
1424  "our AdvRetransTimer on %U doesn't agree with %U",
1425  format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address);
1426  }
1427 
1428  if((h0->neighbor_reachable_time_in_msec &&
1430  (h0->neighbor_reachable_time_in_msec !=
1431  clib_host_to_net_u32(radv_info->adv_neighbor_reachable_time_in_msec)))
1432  {
1433  ip6_neighbor_syslog(vm, LOG_WARNING,
1434  "our AdvReachableTime on %U doesn't agree with %U",
1435  format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address);
1436  }
1437 
1438  /* check for MTU or prefix options or .. */
1439  u8 * opt_hdr = (u8 *)(h0 + 1);
1440  while( options_len0 > 0 &&
1441  opt_hdr < p0->data + p0->current_data)
1442  {
1443  icmp6_neighbor_discovery_option_header_t *o0 = ( icmp6_neighbor_discovery_option_header_t *)opt_hdr;
1444  int opt_len = o0->n_data_u64s << 3;
1445  icmp6_neighbor_discovery_option_type_t option_type = o0->type;
1446 
1447  if(options_len0 < 2)
1448  {
1449  ip6_neighbor_syslog(vm, LOG_ERR,
1450  "malformed RA packet on %U from %U",
1451  format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address);
1452  break;
1453  }
1454 
1455  if(opt_len == 0)
1456  {
1457  ip6_neighbor_syslog(vm, LOG_ERR,
1458  " zero length option in RA on %U from %U",
1459  format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address);
1460  break;
1461  }
1462  else if( opt_len > options_len0)
1463  {
1464  ip6_neighbor_syslog(vm, LOG_ERR,
1465  "option length in RA packet greater than total length on %U from %U",
1466  format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address);
1467  break;
1468  }
1469 
1470  options_len0 -= opt_len;
1471  opt_hdr += opt_len;
1472 
1473  switch(option_type)
1474  {
1475  case ICMP6_NEIGHBOR_DISCOVERY_OPTION_mtu:
1476  {
1477  icmp6_neighbor_discovery_mtu_option_t *h =
1478  (icmp6_neighbor_discovery_mtu_option_t *)(o0);
1479 
1480  if(opt_len < sizeof(*h))
1481  break;
1482 
1483  if((h->mtu && radv_info->adv_link_mtu) &&
1484  (h->mtu != clib_host_to_net_u32(radv_info->adv_link_mtu)))
1485  {
1486  ip6_neighbor_syslog(vm, LOG_WARNING,
1487  "our AdvLinkMTU on %U doesn't agree with %U",
1488  format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address);
1489  }
1490  }
1491  break;
1492 
1493  case ICMP6_NEIGHBOR_DISCOVERY_OPTION_prefix_information:
1494  {
1495  icmp6_neighbor_discovery_prefix_information_option_t *h =
1496  (icmp6_neighbor_discovery_prefix_information_option_t *)(o0);
1497 
1498  /* validate advertised prefix options */
1499  ip6_radv_prefix_t *pr_info;
1500  u32 preferred, valid;
1501 
1502  if(opt_len < sizeof(*h))
1503  break;
1504 
1505  preferred = clib_net_to_host_u32(h->preferred_time);
1506  valid = clib_net_to_host_u32(h->valid_time);
1507 
1508  /* look for matching prefix - if we our advertising it, it better be consistant */
1509  pool_foreach (pr_info, radv_info->adv_prefixes_pool, ({
1510 
1511  ip6_address_t mask;
1512  ip6_address_mask_from_width(&mask, pr_info->prefix_len);
1513 
1514  if(pr_info->enabled &&
1515  (pr_info->prefix_len == h->dst_address_length) &&
1516  ip6_address_is_equal_masked (&pr_info->prefix, &h->dst_address, &mask))
1517  {
1518  /* found it */
1519  if(!pr_info->decrement_lifetime_flag &&
1520  valid != pr_info->adv_valid_lifetime_in_secs)
1521  {
1522  ip6_neighbor_syslog(vm, LOG_WARNING,
1523  "our ADV validlifetime on %U for %U does not agree with %U",
1524  format_vnet_sw_if_index_name, vnm, sw_if_index0,format_ip6_address, &pr_info->prefix,
1525  format_ip6_address, &h->dst_address);
1526  }
1527  if(!pr_info->decrement_lifetime_flag &&
1528  preferred != pr_info->adv_pref_lifetime_in_secs)
1529  {
1530  ip6_neighbor_syslog(vm, LOG_WARNING,
1531  "our ADV preferredlifetime on %U for %U does not agree with %U",
1532  format_vnet_sw_if_index_name, vnm, sw_if_index0,format_ip6_address, &pr_info->prefix,
1533  format_ip6_address, &h->dst_address);
1534  }
1535  }
1536  break;
1537  }));
1538  break;
1539  }
1540  default:
1541  /* skip this one */
1542  break;
1543  }
1544  }
1545  }
1546  }
1547  }
1548 
1549  p0->error = error_node->errors[error0];
1550 
1551  if(error0 != ICMP6_ERROR_NONE)
1552  vlib_error_count (vm, error_node->node_index, error0, 1);
1553 
1554  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1555  to_next, n_left_to_next,
1556  bi0, next0);
1557  }
1558 
1559  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1560  }
1561 
1562  /* Account for router advertisements sent. */
1563  vlib_error_count (vm, error_node->node_index, ICMP6_ERROR_ROUTER_ADVERTISEMENTS_RX, n_advertisements_rcvd);
1564 
1565  return frame->n_vectors;
1566 }
1567 
1568 /* create and initialize router advertisement parameters with default values for this intfc */
1569 static u32
1571  u32 sw_if_index,
1572  u32 is_add)
1573 {
1574  ip6_main_t * im = &ip6_main;
1576  ip_lookup_main_t * lm = &im->lookup_main;
1577  ip6_radv_t * a= 0;
1578  u32 ri = ~0;;
1579  vnet_sw_interface_t * sw_if0;
1580  ethernet_interface_t * eth_if0 = 0;
1581 
1582  /* lookup radv container - ethernet interfaces only */
1583  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index);
1584  if(sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
1585  eth_if0 = ethernet_get_interface (&ethernet_main, sw_if0->hw_if_index);
1586 
1587  if(!eth_if0)
1588  return ri;
1589 
1591  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
1592 
1593  if(ri != ~0)
1594  {
1595  a = pool_elt_at_index (nm->if_radv_pool, ri);
1596 
1597  if(!is_add)
1598  {
1599  u32 i, * to_delete = 0;
1600  ip6_radv_prefix_t *p;
1601  ip6_mldp_group_t *m;
1602 
1603  /* remove adjacencies */
1607 
1608  /* clean up prefix_pool */
1609  pool_foreach (p, a->adv_prefixes_pool, ({
1610  vec_add1 (to_delete, p - a->adv_prefixes_pool);
1611  }));
1612 
1613  for (i = 0; i < vec_len (to_delete); i++)
1614  {
1615  p = pool_elt_at_index (a->adv_prefixes_pool, to_delete[i]);
1617  pool_put (a->adv_prefixes_pool, p);
1618  }
1619 
1620  vec_free (to_delete);
1621  to_delete = 0;
1622 
1623  /* clean up mldp group pool */
1624  pool_foreach (m, a->mldp_group_pool, ({
1625  vec_add1 (to_delete, m - a->mldp_group_pool);
1626  }));
1627 
1628  for (i = 0; i < vec_len (to_delete); i++)
1629  {
1630  m = pool_elt_at_index (a->mldp_group_pool, to_delete[i]);
1632  pool_put (a->mldp_group_pool, m);
1633  }
1634 
1635  vec_free (to_delete);
1636 
1637  pool_put (nm->if_radv_pool, a);
1638  nm->if_radv_pool_index_by_sw_if_index[sw_if_index] = ~0;
1639  ri = ~0;
1640  }
1641  }
1642  else
1643  {
1644  if(is_add)
1645  {
1646  vnet_hw_interface_t * hw_if0;
1647 
1648  hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index);
1649 
1650  pool_get (nm->if_radv_pool, a);
1651 
1652  ri = a - nm->if_radv_pool;
1653  nm->if_radv_pool_index_by_sw_if_index[sw_if_index] = ri;
1654 
1655  /* initialize default values (most of which are zero) */
1656  memset (a, 0, sizeof (a[0]));
1657 
1658  a->sw_if_index = sw_if_index;
1659  a->fib_index = ~0;
1664 
1665  a->adv_link_layer_address = 1; /* send ll address source address option */
1666 
1670  a->seed = (u32) (clib_cpu_time_now() & 0xFFFFFFFF);
1671 
1672  /* for generating random interface ids */
1673  a->randomizer = random_u64 (&a->seed);
1674 
1678 
1679  /* deafult is to send */
1680  a->send_radv = 1;
1681 
1682  /* fill in radv_info for this interface that will be needed later */
1684 
1685  clib_memcpy (a->link_layer_address, eth_if0->address, 6);
1686 
1687  /* fill in default link-local address (this may be overridden) */
1689  a->link_local_prefix_len = 64;
1690 
1691  mhash_init (&a->address_to_prefix_index, sizeof (uword), sizeof (ip6_address_t));
1692  mhash_init (&a->address_to_mldp_index, sizeof (uword), sizeof (ip6_address_t));
1693 
1694  {
1695  ip_adjacency_t *adj;
1696  u8 link_layer_address[6] =
1697  {0x33, 0x33, 0x00, 0x00, 0x00, IP6_MULTICAST_GROUP_ID_all_hosts};
1698 
1699  adj = ip_add_adjacency (lm, /* template */ 0, /* block size */ 1,
1700  &a->all_nodes_adj_index);
1701 
1703  adj->if_address_index = ~0;
1704 
1706  (vnm,
1707  VNET_L3_PACKET_TYPE_IP6,
1708  sw_if_index,
1709  ip6_rewrite_node.index,
1710  link_layer_address,
1711  &adj->rewrite_header,
1712  sizeof (adj->rewrite_data));
1713  }
1714 
1715  {
1716  ip_adjacency_t *adj;
1717  u8 link_layer_address[6] =
1718  {0x33, 0x33, 0x00, 0x00, 0x00, IP6_MULTICAST_GROUP_ID_all_routers};
1719 
1720  adj = ip_add_adjacency (lm, /* template */ 0, /* block size */ 1,
1721  &a->all_routers_adj_index);
1722 
1724  adj->if_address_index = ~0;
1725 
1727  (vnm,
1728  VNET_L3_PACKET_TYPE_IP6,
1729  sw_if_index,
1730  ip6_rewrite_node.index,
1731  link_layer_address,
1732  &adj->rewrite_header,
1733  sizeof (adj->rewrite_data));
1734  }
1735 
1736  {
1737  ip_adjacency_t *adj;
1738  u8 link_layer_address[6] =
1739  {0x33, 0x33, 0x00, 0x00, 0x00, IP6_MULTICAST_GROUP_ID_mldv2_routers};
1740 
1741  adj = ip_add_adjacency (lm, /* template */ 0, /* block size */ 1,
1743 
1745  adj->if_address_index = ~0;
1746 
1748  (vnm,
1749  VNET_L3_PACKET_TYPE_IP6,
1750  sw_if_index,
1751  ip6_rewrite_node.index,
1752  link_layer_address,
1753  &adj->rewrite_header,
1754  sizeof (adj->rewrite_data));
1755  }
1756 
1757  /* add multicast groups we will always be reporting */
1759  ip6_mldp_group_t *mcast_group_info;
1760 
1762  IP6_MULTICAST_SCOPE_link_local,
1763  IP6_MULTICAST_GROUP_ID_all_hosts);
1764 
1765  /* lookup mldp info for this interface */
1766 
1767  uword * p = mhash_get (&a->address_to_mldp_index, &addr);
1768  mcast_group_info = p ? pool_elt_at_index (a->mldp_group_pool, p[0]) : 0;
1769 
1770  /* add address */
1771  if(!mcast_group_info)
1772  {
1773  /* add */
1774  u32 mi;
1775  pool_get (a->mldp_group_pool, mcast_group_info);
1776 
1777  mi = mcast_group_info - a->mldp_group_pool;
1778  mhash_set (&a->address_to_mldp_index, &addr, mi, /* old_value */ 0);
1779 
1780  mcast_group_info->type = 4;
1781  mcast_group_info->mcast_source_address_pool = 0;
1782  mcast_group_info->num_sources = 0;
1783  clib_memcpy(&mcast_group_info->mcast_address, &addr, sizeof(ip6_address_t));
1784  }
1785 
1787  IP6_MULTICAST_SCOPE_link_local,
1788  IP6_MULTICAST_GROUP_ID_all_routers);
1789 
1790  p = mhash_get (&a->address_to_mldp_index, &addr);
1791  mcast_group_info = p ? pool_elt_at_index (a->mldp_group_pool, p[0]) : 0;
1792 
1793  if(!mcast_group_info)
1794  {
1795  /* add */
1796  u32 mi;
1797  pool_get (a->mldp_group_pool, mcast_group_info);
1798 
1799  mi = mcast_group_info - a->mldp_group_pool;
1800  mhash_set (&a->address_to_mldp_index, &addr, mi, /* old_value */ 0);
1801 
1802  mcast_group_info->type = 4;
1803  mcast_group_info->mcast_source_address_pool = 0;
1804  mcast_group_info->num_sources = 0;
1805  clib_memcpy(&mcast_group_info->mcast_address, &addr, sizeof(ip6_address_t));
1806  }
1807 
1809  IP6_MULTICAST_SCOPE_link_local,
1810  IP6_MULTICAST_GROUP_ID_mldv2_routers);
1811 
1812  p = mhash_get (&a->address_to_mldp_index, &addr);
1813  mcast_group_info = p ? pool_elt_at_index (a->mldp_group_pool, p[0]) : 0;
1814 
1815  if(!mcast_group_info)
1816  {
1817  /* add */
1818  u32 mi;
1819  pool_get (a->mldp_group_pool, mcast_group_info);
1820 
1821  mi = mcast_group_info - a->mldp_group_pool;
1822  mhash_set (&a->address_to_mldp_index, &addr, mi, /* old_value */ 0);
1823 
1824  mcast_group_info->type = 4;
1825  mcast_group_info->mcast_source_address_pool = 0;
1826  mcast_group_info->num_sources = 0;
1827  clib_memcpy(&mcast_group_info->mcast_address, &addr, sizeof(ip6_address_t));
1828  }
1829  }
1830  }
1831  return ri;
1832 }
1833 
1834 /* send an mldpv2 report */
1835 static void
1837 {
1838  vnet_main_t * vnm = vnet_get_main();
1839  vlib_main_t * vm = vnm->vlib_main;
1841  vnet_sw_interface_t * sw_if0;
1842  ethernet_interface_t * eth_if0;
1843  u32 ri;
1844  int bogus_length;
1845 
1846  ip6_radv_t *radv_info;
1847  u16 payload_length;
1848  vlib_buffer_t * b0;
1849  ip6_header_t * ip0;
1850  u32 * to_next;
1851  vlib_frame_t * f;
1852  u32 bo0;
1853  u32 n_to_alloc = 1;
1854  u32 n_allocated;
1855 
1856  icmp6_multicast_listener_report_header_t *rh0;
1857  icmp6_multicast_listener_report_packet_t *rp0;
1858 
1859  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index);
1861  eth_if0 = ethernet_get_interface (&ethernet_main, sw_if0->hw_if_index);
1862 
1863  if (!eth_if0 || !vnet_sw_interface_is_admin_up (vnm, sw_if_index))
1864  return;
1865 
1866  /* look up the radv_t information for this interface */
1868 
1869  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
1870 
1871  if(ri == ~0)
1872  return;
1873 
1874  /* send report now - build a mldpv2 report packet */
1875  n_allocated = vlib_buffer_alloc_from_free_list(vm,
1876  &bo0,
1877  n_to_alloc,
1879  if (PREDICT_FALSE(n_allocated == 0))
1880  {
1881  clib_warning ("buffer allocation failure");
1882  return;
1883  }
1884 
1885  b0 = vlib_get_buffer (vm, bo0);
1886 
1887  /* adjust the sizeof the buffer to just include the ipv6 header */
1888  b0->current_length = sizeof(icmp6_multicast_listener_report_packet_t);
1889 
1890  payload_length = sizeof(icmp6_multicast_listener_report_header_t);
1891 
1892  b0->error = ICMP6_ERROR_NONE;
1893 
1894  rp0 = vlib_buffer_get_current (b0);
1895  ip0 = (ip6_header_t *)&rp0-> ip;
1896  rh0 = (icmp6_multicast_listener_report_header_t *)&rp0-> report_hdr;
1897 
1898  memset (rp0 , 0x0, sizeof (icmp6_multicast_listener_report_packet_t));
1899 
1900  ip0->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0x6 << 28);
1901 
1902  ip0->protocol = IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS;
1903  /* for DEBUG - vnet driver won't seem to emit router alerts */
1904  /* ip0->protocol = IP_PROTOCOL_ICMP6; */
1905  ip0->hop_limit = 1;
1906 
1907  rh0->icmp.type = ICMP6_multicast_listener_report_v2;
1908 
1909  /* source address MUST be the link-local address */
1910  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
1911  ip0->src_address = radv_info->link_local_address;
1912 
1913  /* destination is all mldpv2 routers */
1915  IP6_MULTICAST_SCOPE_link_local,
1916  IP6_MULTICAST_GROUP_ID_mldv2_routers);
1917 
1918  /* add reports here */
1919  ip6_mldp_group_t *m;
1920  int num_addr_records = 0;
1921  icmp6_multicast_address_record_t rr;
1922 
1923  /* fill in the hop-by-hop extension header (router alert) info */
1924  rh0->ext_hdr.next_hdr = IP_PROTOCOL_ICMP6;
1925  rh0->ext_hdr.n_data_u64s = 0;
1926 
1927  rh0->alert.type = IP6_MLDP_ALERT_TYPE;
1928  rh0->alert.len = 2;
1929  rh0->alert.value = 0;
1930 
1931  rh0->pad.type = 1;
1932  rh0->pad.len = 0;
1933 
1934  rh0->icmp.checksum = 0;
1935 
1936  pool_foreach (m, radv_info->mldp_group_pool, ({
1937 
1938  rr.type = m->type;
1939  rr.aux_data_len_u32s = 0;
1940  rr.num_sources = clib_host_to_net_u16 (m->num_sources);
1941  clib_memcpy(&rr.mcast_addr, &m->mcast_address, sizeof(ip6_address_t));
1942 
1943  num_addr_records++;
1944 
1945  vlib_buffer_add_data (vm,
1946  b0->free_list_index,
1947  bo0,
1948  (void *)&rr, sizeof(icmp6_multicast_address_record_t));
1949 
1950  payload_length += sizeof( icmp6_multicast_address_record_t);
1951  }));
1952 
1953  rh0->rsvd = 0;
1954  rh0->num_addr_records = clib_host_to_net_u16(num_addr_records);
1955 
1956  /* update lengths */
1957  ip0->payload_length = clib_host_to_net_u16 (payload_length);
1958 
1959  rh0->icmp.checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0,
1960  &bogus_length);
1961  ASSERT(bogus_length == 0);
1962 
1963  /*
1964  * OK to override w/ no regard for actual FIB, because
1965  * ip6-rewrite-local only looks at the adjacency.
1966  */
1967  vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1969 
1970  vnet_buffer (b0)->ip.adj_index[VLIB_RX] =
1971  radv_info->all_mldv2_routers_adj_index;
1972 
1973  vlib_node_t * node = vlib_get_node_by_name (vm, (u8 *) "ip6-rewrite-local");
1974 
1975  f = vlib_get_frame_to_node (vm, node->index);
1976  to_next = vlib_frame_vector_args (f);
1977  to_next[0] = bo0;
1978  f->n_vectors = 1;
1979 
1980  vlib_put_frame_to_node (vm, node->index, f);
1981  return;
1982 }
1983 
1985  .function = icmp6_router_solicitation,
1986  .name = "icmp6-router-solicitation",
1987 
1988  .vector_size = sizeof (u32),
1989 
1990  .format_trace = format_icmp6_input_trace,
1991 
1992  .n_next_nodes = ICMP6_ROUTER_SOLICITATION_N_NEXT,
1993  .next_nodes = {
1994  [ICMP6_ROUTER_SOLICITATION_NEXT_DROP] = "error-drop",
1995  [ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_RW] = "ip6-rewrite-local",
1996  [ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_TX] = "interface-output",
1997  },
1998 };
1999 
2000 /* send a RA or update the timer info etc.. */
2001 static uword
2003  vlib_node_runtime_t * node,
2004  vlib_frame_t * frame)
2005 {
2006  vnet_main_t * vnm = vnet_get_main();
2008  ip6_radv_t *radv_info;
2009  vlib_frame_t * f = 0;
2010  u32 n_this_frame = 0;
2011  u32 n_left_to_next = 0;
2012  u32 * to_next = 0;
2013  u32 bo0;
2014  icmp6_router_solicitation_header_t * h0;
2015  vlib_buffer_t * b0;
2016  f64 now = vlib_time_now (vm);
2017 
2018  /* Interface ip6 radv info list */
2019  pool_foreach (radv_info, nm->if_radv_pool, ({
2020 
2021  if( !vnet_sw_interface_is_admin_up (vnm, radv_info->sw_if_index))
2022  {
2023  radv_info->initial_adverts_sent = radv_info->initial_adverts_count-1;
2024  radv_info->next_multicast_time = now;
2025  radv_info->last_multicast_time = now;
2026  radv_info->last_radv_time = 0;
2027  radv_info->all_routers_mcast = 0;
2028  continue;
2029  }
2030 
2031  /* Make sure that we've joined the all-routers multicast group */
2032  if(!radv_info->all_routers_mcast)
2033  {
2034  /* send MDLP_REPORT_EVENT message */
2035  ip6_neighbor_send_mldpv2_report(radv_info->sw_if_index);
2036  radv_info->all_routers_mcast = 1;
2037  }
2038 
2039  /* is it time to send a multicast RA on this interface? */
2040  if(radv_info->send_radv && (now >= radv_info->next_multicast_time))
2041  {
2042  u32 n_to_alloc = 1;
2043  u32 n_allocated;
2044 
2045  f64 rfn = (radv_info->max_radv_interval - radv_info->min_radv_interval) *
2046  random_f64 (&radv_info->seed) + radv_info->min_radv_interval;
2047 
2048  /* multicast send - compute next multicast send time */
2049  if( radv_info->initial_adverts_sent > 0)
2050  {
2051  radv_info->initial_adverts_sent--;
2052  if(rfn > radv_info-> initial_adverts_interval)
2053  rfn = radv_info-> initial_adverts_interval;
2054 
2055  /* check to see if we are ceasing to send */
2056  if( radv_info->initial_adverts_sent == 0)
2057  if(radv_info->cease_radv)
2058  radv_info->send_radv = 0;
2059  }
2060 
2061  radv_info->next_multicast_time = rfn + now;
2062  radv_info->last_multicast_time = now;
2063 
2064  /* send advert now - build a "solicted" router advert with unspecified source address */
2065  n_allocated = vlib_buffer_alloc_from_free_list(vm,
2066  &bo0,
2067  n_to_alloc,
2069 
2070  if (PREDICT_FALSE(n_allocated == 0))
2071  {
2072  clib_warning ("buffer allocation failure");
2073  continue;
2074  }
2075  b0 = vlib_get_buffer (vm, bo0);
2076  b0->current_length = sizeof( icmp6_router_solicitation_header_t);
2077  b0->error = ICMP6_ERROR_NONE;
2078  vnet_buffer (b0)->sw_if_index[VLIB_RX] = radv_info->sw_if_index;
2079 
2080  h0 = vlib_buffer_get_current (b0);
2081 
2082  memset (h0, 0, sizeof (icmp6_router_solicitation_header_t));
2083 
2084  h0->ip.ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0x6 << 28);
2085  h0->ip.payload_length = clib_host_to_net_u16 (sizeof (icmp6_router_solicitation_header_t)
2086  - STRUCT_OFFSET_OF (icmp6_router_solicitation_header_t, neighbor));
2087  h0->ip.protocol = IP_PROTOCOL_ICMP6;
2088  h0->ip.hop_limit = 255;
2089 
2090  /* set src/dst address as "unspecified" this marks this packet as internally generated rather than recieved */
2091  h0->ip.src_address.as_u64[0] = 0;
2092  h0->ip.src_address.as_u64[1] = 0;
2093 
2094  h0->ip.dst_address.as_u64[0] = 0;
2095  h0->ip.dst_address.as_u64[1] = 0;
2096 
2097  h0->neighbor.icmp.type = ICMP6_router_solicitation;
2098 
2099  if (PREDICT_FALSE(f == 0))
2100  {
2102  to_next = vlib_frame_vector_args (f);
2103  n_left_to_next = VLIB_FRAME_SIZE;
2104  n_this_frame = 0;
2105  }
2106 
2107  n_this_frame++;
2108  n_left_to_next--;
2109  to_next[0] = bo0;
2110  to_next += 1;
2111 
2112  if (PREDICT_FALSE(n_left_to_next == 0))
2113  {
2114  f->n_vectors = n_this_frame;
2116  f = 0;
2117  }
2118  }
2119  }));
2120 
2121  if (f)
2122  {
2123  ASSERT(n_this_frame);
2124  f->n_vectors = n_this_frame;
2126  }
2127  return 0;
2128 }
2129 
2130 static uword
2132  vlib_node_runtime_t * node,
2133  vlib_frame_t * frame)
2134 {
2135  uword event_type;
2137 
2138  /* init code here */
2139 
2140  while (1)
2141  {
2142  vlib_process_wait_for_event_or_clock (vm, 1. /* seconds */);
2143 
2144  event_data = vlib_process_get_event_data (vm, &event_type);
2145 
2146  if(!event_data)
2147  {
2148  /* No events found: timer expired. */
2149  /* process interface list and send RAs as appropriate, update timer info */
2150  ip6_neighbor_process_timer_event (vm, node, frame);
2151  }
2152  else
2153  {
2154  switch (event_type) {
2155 
2156  case ICMP6_ND_EVENT_INIT:
2157  break;
2158 
2159  case ~0:
2160  break;
2161 
2162  default:
2163  ASSERT (0);
2164  }
2165 
2166  if (event_data)
2167  _vec_len (event_data) = 0;
2168  }
2169  }
2170  return frame->n_vectors;
2171 }
2172 
2174  .function = icmp6_router_advertisement,
2175  .name = "icmp6-router-advertisement",
2176 
2177  .vector_size = sizeof (u32),
2178 
2179  .format_trace = format_icmp6_input_trace,
2180 
2181  .n_next_nodes = 1,
2182  .next_nodes = {
2183  [0] = "error-drop",
2184  },
2185 };
2186 
2188 
2190  .name = "ip6-icmp-neighbor-discovery-event-process",
2191  .type = VLIB_NODE_TYPE_PROCESS,
2192 };
2193 
2194 static uword
2196  vlib_node_runtime_t * node,
2197  vlib_frame_t * frame)
2198 { return icmp6_neighbor_solicitation_or_advertisement (vm, node, frame, /* is_solicitation */ 1); }
2199 
2200 static uword
2202  vlib_node_runtime_t * node,
2203  vlib_frame_t * frame)
2204 { return icmp6_neighbor_solicitation_or_advertisement (vm, node, frame, /* is_solicitation */ 0); }
2205 
2207  .function = icmp6_neighbor_solicitation,
2208  .name = "icmp6-neighbor-solicitation",
2209 
2210  .vector_size = sizeof (u32),
2211 
2212  .format_trace = format_icmp6_input_trace,
2213 
2214  .n_next_nodes = ICMP6_NEIGHBOR_SOLICITATION_N_NEXT,
2215  .next_nodes = {
2216  [ICMP6_NEIGHBOR_SOLICITATION_NEXT_DROP] = "error-drop",
2217  [ICMP6_NEIGHBOR_SOLICITATION_NEXT_REPLY] = "interface-output",
2218  },
2219 };
2220 
2222  .function = icmp6_neighbor_advertisement,
2223  .name = "icmp6-neighbor-advertisement",
2224 
2225  .vector_size = sizeof (u32),
2226 
2227  .format_trace = format_icmp6_input_trace,
2228 
2229  .n_next_nodes = 1,
2230  .next_nodes = {
2231  [0] = "error-drop",
2232  },
2233 };
2234 
2235 /* API support functions */
2236 int
2238  u8 suppress, u8 managed, u8 other,
2239  u8 ll_option, u8 send_unicast, u8 cease,
2240  u8 use_lifetime, u32 lifetime,
2241  u32 initial_count, u32 initial_interval,
2242  u32 max_interval, u32 min_interval,
2243  u8 is_no)
2244 {
2246  int error;
2247  u32 ri;
2248 
2249  /* look up the radv_t information for this interface */
2251  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
2252  error = (ri != ~0) ? 0 : VNET_API_ERROR_INVALID_SW_IF_INDEX;
2253 
2254  if(!error)
2255  {
2256 
2257  ip6_radv_t * radv_info;
2258  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
2259 
2260  if((max_interval != 0) && (min_interval ==0))
2261  min_interval = .75 * max_interval;
2262 
2263  max_interval = (max_interval != 0) ? ( (is_no) ? DEF_MAX_RADV_INTERVAL : max_interval) : radv_info->max_radv_interval;
2264  min_interval = (min_interval != 0) ? ( (is_no) ? DEF_MIN_RADV_INTERVAL : min_interval) : radv_info->min_radv_interval;
2265  lifetime = (use_lifetime != 0) ? ( (is_no) ? DEF_DEF_RTR_LIFETIME : lifetime) : radv_info->adv_router_lifetime_in_sec;
2266 
2267  if(lifetime)
2268  {
2269  if(lifetime > MAX_DEF_RTR_LIFETIME)
2270  lifetime = MAX_DEF_RTR_LIFETIME;
2271 
2272  if(lifetime <= max_interval)
2273  return VNET_API_ERROR_INVALID_VALUE;
2274  }
2275 
2276  if(min_interval != 0)
2277  {
2278  if((min_interval > .75 * max_interval) ||
2279  (min_interval < 3))
2280  return VNET_API_ERROR_INVALID_VALUE;
2281  }
2282 
2283  if((initial_count > MAX_INITIAL_RTR_ADVERTISEMENTS) ||
2284  (initial_interval > MAX_INITIAL_RTR_ADVERT_INTERVAL))
2285  return VNET_API_ERROR_INVALID_VALUE;
2286 
2287  /*
2288  if "flag" is set and is_no is true then restore default value else set value corresponding to "flag"
2289  if "flag" is clear don't change corresponding value
2290  */
2291  radv_info->send_radv = (suppress != 0) ? ( (is_no != 0) ? 1 : 0 ) : radv_info->send_radv;
2292  radv_info->adv_managed_flag = ( managed != 0) ? ( (is_no) ? 0 : 1) : radv_info->adv_managed_flag;
2293  radv_info->adv_other_flag = (other != 0) ? ( (is_no) ? 0: 1) : radv_info->adv_other_flag;
2294  radv_info->adv_link_layer_address = ( ll_option != 0) ? ( (is_no) ? 1 : 0) : radv_info->adv_link_layer_address;
2295  radv_info->send_unicast = (send_unicast != 0) ? ( (is_no) ? 0 : 1) : radv_info->send_unicast;
2296  radv_info->cease_radv = ( cease != 0) ? ( (is_no) ? 0 : 1) : radv_info->cease_radv;
2297 
2298  radv_info->min_radv_interval = min_interval;
2299  radv_info->max_radv_interval = max_interval;
2300  radv_info->adv_router_lifetime_in_sec = lifetime;
2301 
2302  radv_info->initial_adverts_count =
2303  (initial_count != 0) ? ( (is_no) ? MAX_INITIAL_RTR_ADVERTISEMENTS : initial_count) : radv_info->initial_adverts_count ;
2304  radv_info->initial_adverts_interval =
2305  (initial_interval != 0) ? ( (is_no) ? MAX_INITIAL_RTR_ADVERT_INTERVAL : initial_interval) : radv_info->initial_adverts_interval;
2306 
2307  /* restart */
2308  if((cease != 0) && (is_no))
2309  radv_info-> send_radv = 1;
2310 
2311  radv_info->initial_adverts_sent = radv_info->initial_adverts_count -1;
2312  radv_info->next_multicast_time = vlib_time_now (vm);
2313  radv_info->last_multicast_time = vlib_time_now (vm);
2314  radv_info->last_radv_time = 0;
2315  }
2316  return(error);
2317 }
2318 
2319 int
2321  ip6_address_t *prefix_addr, u8 prefix_len,
2322  u8 use_default, u32 val_lifetime, u32 pref_lifetime,
2323  u8 no_advertise, u8 off_link, u8 no_autoconfig, u8 no_onlink,
2324  u8 is_no)
2325 {
2327  int error;
2328 
2329  u32 ri;
2330 
2331  /* look up the radv_t information for this interface */
2333 
2334  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
2335 
2336  error = (ri != ~0) ? 0 : VNET_API_ERROR_INVALID_SW_IF_INDEX;
2337 
2338  if(!error)
2339  {
2340  f64 now = vlib_time_now (vm);
2341  ip6_radv_t * radv_info;
2342  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
2343 
2344  /* prefix info add, delete or update */
2345  ip6_radv_prefix_t * prefix;
2346 
2347  /* lookup prefix info for this address on this interface */
2348  uword * p = mhash_get (&radv_info->address_to_prefix_index, prefix_addr);
2349 
2350  prefix = p ? pool_elt_at_index (radv_info->adv_prefixes_pool, p[0]) : 0;
2351 
2352  if(is_no)
2353  {
2354  /* delete */
2355  if(!prefix)
2356  return VNET_API_ERROR_INVALID_VALUE; /* invalid prefix */
2357 
2358  if(prefix->prefix_len != prefix_len)
2359  return VNET_API_ERROR_INVALID_VALUE_2;
2360 
2361  /* FIXME - Should the DP do this or the CP ?*/
2362  /* do specific delete processing here before returning */
2363  /* try to remove from routing table */
2364 
2365  mhash_unset (&radv_info->address_to_prefix_index, prefix_addr,/* old_value */ 0);
2366  pool_put (radv_info->adv_prefixes_pool, prefix);
2367 
2368  radv_info->initial_adverts_sent = radv_info->initial_adverts_count -1;
2369  radv_info->next_multicast_time = vlib_time_now (vm);
2370  radv_info->last_multicast_time = vlib_time_now (vm);
2371  radv_info->last_radv_time = 0;
2372  return(error);
2373  }
2374 
2375  /* adding or changing */
2376  if(!prefix)
2377  {
2378  /* add */
2379  u32 pi;
2380  pool_get (radv_info->adv_prefixes_pool, prefix);
2381  pi = prefix - radv_info->adv_prefixes_pool;
2382  mhash_set (&radv_info->address_to_prefix_index, prefix_addr, pi, /* old_value */ 0);
2383 
2384  memset(prefix, 0x0, sizeof(ip6_radv_prefix_t));
2385 
2386  prefix->prefix_len = prefix_len;
2387  clib_memcpy(&prefix->prefix, prefix_addr, sizeof(ip6_address_t));
2388 
2389  /* initialize default values */
2390  prefix->adv_on_link_flag = 1; /* L bit set */
2391  prefix->adv_autonomous_flag = 1; /* A bit set */
2394  prefix->enabled = 1;
2395  prefix->decrement_lifetime_flag = 1;
2396  prefix->deprecated_prefix_flag = 1;
2397 
2398  if(off_link == 0)
2399  {
2400  /* FIXME - Should the DP do this or the CP ?*/
2401  /* insert prefix into routing table as a connected prefix */
2402  }
2403 
2404  if(use_default)
2405  goto restart;
2406  }
2407  else
2408  {
2409 
2410  if(prefix->prefix_len != prefix_len)
2411  return VNET_API_ERROR_INVALID_VALUE_2;
2412 
2413  if(off_link != 0)
2414  {
2415  /* FIXME - Should the DP do this or the CP ?*/
2416  /* remove from routing table if already there */
2417  }
2418  }
2419 
2420  if((val_lifetime == ~0) || (pref_lifetime == ~0))
2421  {
2422  prefix->adv_valid_lifetime_in_secs = ~0;
2423  prefix->adv_pref_lifetime_in_secs = ~0;
2424  prefix->decrement_lifetime_flag = 0;
2425  }
2426  else
2427  {
2428  prefix->adv_valid_lifetime_in_secs = val_lifetime;;
2429  prefix->adv_pref_lifetime_in_secs = pref_lifetime;
2430  }
2431 
2432  /* copy remaining */
2433  prefix->enabled = !(no_advertise != 0);
2434  prefix->adv_on_link_flag = !((off_link != 0) || (no_onlink != 0));
2435  prefix->adv_autonomous_flag = !(no_autoconfig != 0);
2436 
2437  restart:
2438  /* restart */
2439  /* fill in the expiration times */
2440  prefix->valid_lifetime_expires = now + prefix->adv_valid_lifetime_in_secs;
2441  prefix->pref_lifetime_expires = now + prefix->adv_pref_lifetime_in_secs;
2442 
2443  radv_info->initial_adverts_sent = radv_info->initial_adverts_count -1;
2444  radv_info->next_multicast_time = vlib_time_now (vm);
2445  radv_info->last_multicast_time = vlib_time_now (vm);
2446  radv_info->last_radv_time = 0;
2447  }
2448  return(error);
2449 }
2450 
2451 clib_error_t *
2453 {
2454  vnet_main_t * vnm = vnet_get_main();
2456  clib_error_t * error = 0;
2457  u8 is_no = 0;
2458  u8 suppress = 0, managed = 0, other = 0;
2459  u8 suppress_ll_option = 0, send_unicast = 0, cease= 0;
2460  u8 use_lifetime = 0;
2461  u32 sw_if_index, ra_lifetime = 0, ra_initial_count = 0, ra_initial_interval = 0;
2462  u32 ra_max_interval = 0 , ra_min_interval = 0;
2463 
2464  unformat_input_t _line_input, * line_input = &_line_input;
2465  vnet_sw_interface_t * sw_if0;
2466 
2467  int add_radv_info = 1;
2468  __attribute__((unused)) ip6_radv_t * radv_info = 0;
2469  ip6_address_t ip6_addr;
2470  u32 addr_len;
2471 
2472 
2473  /* Get a line of input. */
2474  if (! unformat_user (main_input, unformat_line_input, line_input))
2475  return 0;
2476 
2477  /* get basic radv info for this interface */
2478  if(unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2479  {
2480 
2481  if (unformat_user (line_input,
2482  unformat_vnet_sw_interface, vnm, &sw_if_index))
2483  {
2484  u32 ri;
2485  ethernet_interface_t * eth_if0 = 0;
2486 
2487  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index);
2488  if(sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
2489  eth_if0 = ethernet_get_interface (&ethernet_main, sw_if0->hw_if_index);
2490 
2491  if(!eth_if0)
2492  {
2493  error = clib_error_return (0, "Interface must be of ethernet type");
2494  goto done;
2495  }
2496 
2497  /* look up the radv_t information for this interface */
2499 
2500  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
2501 
2502  if(ri != ~0)
2503  {
2504  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
2505  }
2506  else
2507  {
2508  error = clib_error_return (0, "unknown interface %U'",
2509  format_unformat_error, line_input);
2510  goto done;
2511  }
2512  }
2513  else
2514  {
2515  error = clib_error_return (0, "invalid interface name %U'",
2516  format_unformat_error, line_input);
2517  goto done;
2518  }
2519  }
2520 
2521  /* get the rest of the command */
2522  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2523  {
2524  if (unformat (line_input, "no"))
2525  is_no = 1;
2526  else if(unformat (line_input, "prefix %U/%d",
2527  unformat_ip6_address, &ip6_addr,
2528  &addr_len))
2529  {
2530  add_radv_info = 0;
2531  break;
2532  }
2533  else if (unformat (line_input, "ra-managed-config-flag"))
2534  {
2535  managed = 1;
2536  break;
2537  }
2538  else if (unformat (line_input, "ra-other-config-flag"))
2539  {
2540  other = 1;
2541  break;
2542  }
2543  else if (unformat (line_input, "ra-suppress") ||
2544  unformat (line_input, "ra-surpress"))
2545  {
2546  suppress = 1;
2547  break;
2548  }
2549  else if (unformat (line_input, "ra-suppress-link-layer") ||
2550  unformat (line_input, "ra-surpress-link-layer"))
2551  {
2552  suppress_ll_option = 1;
2553  break;
2554  }
2555  else if (unformat (line_input, "ra-send-unicast"))
2556  {
2557  send_unicast = 1;
2558  break;
2559  }
2560  else if (unformat (line_input, "ra-lifetime"))
2561  {
2562  if (!unformat (line_input, "%d", &ra_lifetime))
2563  return(error = unformat_parse_error (line_input));
2564  use_lifetime = 1;
2565  break;
2566  }
2567  else if (unformat (line_input, "ra-initial"))
2568  {
2569  if (!unformat (line_input, "%d %d", &ra_initial_count, &ra_initial_interval))
2570  return(error = unformat_parse_error (line_input));
2571  break;
2572  }
2573  else if (unformat (line_input, "ra-interval"))
2574  {
2575  if (!unformat (line_input, "%d", &ra_max_interval))
2576  return(error = unformat_parse_error (line_input));
2577 
2578  if (!unformat (line_input, "%d", &ra_min_interval))
2579  ra_min_interval = 0;
2580  break;
2581  }
2582  else if(unformat (line_input, "ra-cease"))
2583  {
2584  cease = 1;
2585  break;
2586  }
2587  else
2588  return(unformat_parse_error (line_input));
2589  }
2590 
2591  if(add_radv_info)
2592  {
2593  ip6_neighbor_ra_config(vm, sw_if_index,
2594  suppress, managed, other,
2595  suppress_ll_option, send_unicast, cease,
2596  use_lifetime, ra_lifetime,
2597  ra_initial_count, ra_initial_interval,
2598  ra_max_interval, ra_min_interval,
2599  is_no);
2600  }
2601  else
2602  {
2603  u32 valid_lifetime_in_secs = 0;
2604  u32 pref_lifetime_in_secs = 0;
2605  u8 use_prefix_default_values = 0;
2606  u8 no_advertise = 0;
2607  u8 off_link= 0;
2608  u8 no_autoconfig = 0;
2609  u8 no_onlink= 0;
2610 
2611  /* get the rest of the command */
2612  while(unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2613  {
2614  if(unformat (line_input, "default"))
2615  {
2616  use_prefix_default_values = 1;
2617  break;
2618  }
2619  else if(unformat (line_input, "infinite"))
2620  {
2621  valid_lifetime_in_secs = ~0;
2622  pref_lifetime_in_secs = ~0;
2623  break;
2624  }
2625  else if(unformat (line_input, "%d %d", &valid_lifetime_in_secs,
2626  &pref_lifetime_in_secs))
2627  break;
2628  else
2629  break;
2630  }
2631 
2632 
2633  /* get the rest of the command */
2634  while (!use_prefix_default_values &&
2636  {
2637  if(unformat (line_input, "no-advertise"))
2638  no_advertise = 1;
2639  else if(unformat (line_input, "off-link"))
2640  off_link = 1;
2641  else if(unformat (line_input, "no-autoconfig"))
2642  no_autoconfig = 1;
2643  else if(unformat (line_input, "no-onlink"))
2644  no_onlink = 1;
2645  else
2646  return(unformat_parse_error (line_input));
2647  }
2648 
2649  ip6_neighbor_ra_prefix(vm, sw_if_index,
2650  &ip6_addr, addr_len,
2651  use_prefix_default_values,
2652  valid_lifetime_in_secs,
2653  pref_lifetime_in_secs,
2654  no_advertise,
2655  off_link,
2656  no_autoconfig,
2657  no_onlink,
2658  is_no);
2659  }
2660 
2661  unformat_free (line_input);
2662 
2663  done:
2664  return error;
2665 }
2666 
2667 static void
2669  u32 *addrs)
2670 {
2672  u32 i;
2673 
2674  for (i = 0; i < vec_len (addrs); i++)
2675  {
2677  ip6_address_t * address = ip_interface_address_get_address (lm, a);
2678 
2679  vlib_cli_output (vm, "\t\t%U/%d",
2680  format_ip6_address, address,
2681  a->address_length);
2682  }
2683 }
2684 
2685 static clib_error_t *
2687  unformat_input_t * input,
2688  vlib_cli_command_t * cmd)
2689 {
2690  vnet_main_t * vnm = vnet_get_main();
2692  clib_error_t * error = 0;
2693  u32 sw_if_index;
2694 
2695  sw_if_index = ~0;
2696 
2697  if (unformat_user (input,
2698  unformat_vnet_sw_interface, vnm, &sw_if_index))
2699  {
2700  u32 ri;
2701 
2702  /* look up the radv_t information for this interface */
2704 
2705  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
2706 
2707  if(ri != ~0)
2708  {
2710  ip6_radv_t * radv_info;
2711  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
2712 
2713  vlib_cli_output (vm, "%U is admin %s\n", format_vnet_sw_interface_name, vnm,
2714  vnet_get_sw_interface (vnm, sw_if_index),
2715  (vnet_sw_interface_is_admin_up (vnm, sw_if_index) ? "up" : "down"));
2716 
2717  u32 ai;
2718  u32 *link_scope = 0, *global_scope = 0;
2719  u32 *local_scope = 0, *unknown_scope = 0;
2721 
2723  ai = lm->if_address_pool_index_by_sw_if_index[sw_if_index];
2724 
2725  while (ai != (u32)~0)
2726  {
2727  a = pool_elt_at_index(lm->if_address_pool, ai);
2728  ip6_address_t * address = ip_interface_address_get_address (lm, a);
2729 
2730  if (ip6_address_is_link_local_unicast (address))
2731  vec_add1 (link_scope, ai);
2732  else if(ip6_address_is_global_unicast (address))
2733  vec_add1 (global_scope, ai);
2734  else if(ip6_address_is_local_unicast (address))
2735  vec_add1 (local_scope, ai);
2736  else
2737  vec_add1 (unknown_scope, ai);
2738 
2739  ai = a->next_this_sw_interface;
2740  }
2741 
2742  if (vec_len (link_scope))
2743  {
2744  vlib_cli_output (vm, "\tLink-local address(es):\n");
2745  ip6_print_addrs (vm, link_scope);
2746  vec_free (link_scope);
2747  }
2748 
2749  if (vec_len (local_scope))
2750  {
2751  vlib_cli_output (vm, "\tLocal unicast address(es):\n");
2752  ip6_print_addrs (vm, local_scope);
2753  vec_free (local_scope);
2754  }
2755 
2756  if (vec_len (global_scope))
2757  {
2758  vlib_cli_output (vm, "\tGlobal unicast address(es):\n");
2759  ip6_print_addrs (vm, global_scope);
2760  vec_free (global_scope);
2761  }
2762 
2763  if (vec_len (unknown_scope))
2764  {
2765  vlib_cli_output (vm, "\tOther-scope address(es):\n");
2766  ip6_print_addrs (vm, unknown_scope);
2767  vec_free (unknown_scope);
2768  }
2769 
2770  vlib_cli_output (vm, "\tJoined group address(es):\n");
2771  ip6_mldp_group_t *m;
2772  pool_foreach (m, radv_info->mldp_group_pool, ({
2773  vlib_cli_output (vm, "\t\t%U\n", format_ip6_address, &m->mcast_address);
2774  }));
2775 
2776  vlib_cli_output (vm, "\tAdvertised Prefixes:\n");
2777  ip6_radv_prefix_t * p;
2778  pool_foreach (p, radv_info->adv_prefixes_pool, ({
2779  vlib_cli_output (vm, "\t\tprefix %U, length %d\n",
2780  format_ip6_address, &p->prefix, p->prefix_len);
2781  }));
2782 
2783  vlib_cli_output (vm, "\tMTU is %d\n", radv_info->adv_link_mtu);
2784  vlib_cli_output (vm, "\tICMP error messages are unlimited\n");
2785  vlib_cli_output (vm, "\tICMP redirects are disabled\n");
2786  vlib_cli_output (vm, "\tICMP unreachables are not sent\n");
2787  vlib_cli_output (vm, "\tND DAD is disabled\n");
2788  //vlib_cli_output (vm, "\tND reachable time is %d milliseconds\n",);
2789  vlib_cli_output (vm, "\tND advertised reachable time is %d\n",
2791  vlib_cli_output (vm, "\tND advertised retransmit interval is %d (msec)\n",
2793 
2794  u32 ra_interval = radv_info->max_radv_interval;
2795  u32 ra_interval_min = radv_info->min_radv_interval;
2796  vlib_cli_output (vm, "\tND router advertisements are sent every %d seconds (min interval is %d)\n",
2797  ra_interval, ra_interval_min);
2798  vlib_cli_output (vm, "\tND router advertisements live for %d seconds\n",
2799  radv_info->adv_router_lifetime_in_sec);
2800  vlib_cli_output (vm, "\tHosts %s stateless autoconfig for addresses\n",
2801  (radv_info->adv_managed_flag) ? "use" :" don't use");
2802  vlib_cli_output (vm, "\tND router advertisements sent %d\n", radv_info->n_advertisements_sent);
2803  vlib_cli_output (vm, "\tND router solicitations received %d\n", radv_info->n_solicitations_rcvd);
2804  vlib_cli_output (vm, "\tND router solicitations dropped %d\n", radv_info->n_solicitations_dropped);
2805  }
2806  else
2807  {
2808  error = clib_error_return (0, "IPv6 not enabled on interface",
2809  format_unformat_error, input);
2810 
2811  }
2812  }
2813  return error;
2814 }
2815 
2816 VLIB_CLI_COMMAND (show_ip6_interface_command, static) = {
2817  .path = "show ip6 interface",
2818  .function = show_ip6_interface_cmd,
2819  .short_help = "show ip6 interface <iface name>",
2820 };
2821 
2822 clib_error_t *
2824  u32 sw_if_index)
2825 {
2826  clib_error_t * error = 0;
2828  u32 ri;
2829 
2830  /* look up the radv_t information for this interface */
2832  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
2833 
2834  /* if not created - do nothing */
2835  if(ri != ~0)
2836  {
2837  vnet_main_t * vnm = vnet_get_main();
2838  ip6_radv_t * radv_info;
2839 
2840  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
2841 
2842  /* check radv_info ref count for other ip6 addresses on this interface */
2843  if(radv_info->ref_count == 0 )
2844  {
2845  /* essentially "disables" ipv6 on this interface */
2846  error = ip6_add_del_interface_address (vm, sw_if_index,
2847  &radv_info->link_local_address,
2848  radv_info->link_local_prefix_len,
2849  1 /* is_del */);
2850 
2851  ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, 0/* is_add */);
2852  }
2853  }
2854  return error;
2855 }
2856 
2857 int
2859  u32 sw_if_index)
2860 {
2862  u32 ri = ~0;
2863 
2864  /* look up the radv_t information for this interface */
2866 
2867  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
2868 
2869  return ri != ~0;
2870 }
2871 
2872 clib_error_t *
2874  u32 sw_if_index)
2875 {
2876  clib_error_t * error = 0;
2878  u32 ri;
2879  int is_add = 1;
2880 
2881  /* look up the radv_t information for this interface */
2883 
2884  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
2885 
2886  /* if not created yet */
2887  if(ri == ~0)
2888  {
2889  vnet_main_t * vnm = vnet_get_main();
2890  vnet_sw_interface_t * sw_if0;
2891 
2892  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index);
2893  if(sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
2894  {
2895  ethernet_interface_t * eth_if0;
2896 
2897  eth_if0 = ethernet_get_interface (&ethernet_main, sw_if0->hw_if_index);
2898  if(eth_if0)
2899  {
2900  /* create radv_info. for this interface. This holds all the info needed for router adverts */
2901  ri = ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, is_add);
2902 
2903  if(ri != ~0)
2904  {
2905  ip6_radv_t * radv_info;
2906  ip6_address_t link_local_address;
2907 
2908  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
2909 
2911  eth_if0->address);
2912 
2913  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index);
2914  if(sw_if0->type == VNET_SW_INTERFACE_TYPE_SUB)
2915  {
2916  /* make up an interface id */
2917  md5_context_t m;
2918  u8 digest[16];
2919 
2920  link_local_address.as_u64[0] = radv_info->randomizer;
2921 
2922  md5_init (&m);
2923  md5_add (&m, &link_local_address, 16);
2924  md5_finish (&m, digest);
2925 
2926  clib_memcpy(&link_local_address, digest, 16);
2927 
2928  radv_info->randomizer = link_local_address.as_u64[0];
2929 
2930  link_local_address.as_u64[0] = clib_host_to_net_u64 (0xFE80000000000000ULL);
2931  /* clear u bit */
2932  link_local_address.as_u8[8] &= 0xfd;
2933  }
2934 
2935  /* essentially "enables" ipv6 on this interface */
2936  error = ip6_add_del_interface_address (vm, sw_if_index,
2937  &link_local_address, 64 /* address width */,
2938  0 /* is_del */);
2939 
2940  if(error)
2941  ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, !is_add);
2942  else
2943  {
2944  radv_info->link_local_address = link_local_address;
2945  radv_info->link_local_prefix_len = 64;
2946  }
2947  }
2948  }
2949  }
2950  }
2951  return error;
2952 }
2953 
2954 static clib_error_t *
2956  unformat_input_t * input,
2957  vlib_cli_command_t * cmd)
2958 {
2959  vnet_main_t * vnm = vnet_get_main();
2960  clib_error_t * error = 0;
2961  u32 sw_if_index;
2962 
2963  sw_if_index = ~0;
2964 
2965  if (unformat_user (input,
2966  unformat_vnet_sw_interface, vnm, &sw_if_index))
2967  {
2968  enable_ip6_interface(vm, sw_if_index);
2969  }
2970  else
2971  {
2972  error = clib_error_return (0, "unknown interface\n'",
2973  format_unformat_error, input);
2974 
2975  }
2976  return error;
2977 }
2978 
2979 VLIB_CLI_COMMAND (enable_ip6_interface_command, static) = {
2980  .path = "enable ip6 interface",
2981  .function = enable_ip6_interface_cmd,
2982  .short_help = "enable ip6 interface <iface name>",
2983 };
2984 
2985 static clib_error_t *
2987  unformat_input_t * input,
2988  vlib_cli_command_t * cmd)
2989 {
2990  vnet_main_t * vnm = vnet_get_main();
2991  clib_error_t * error = 0;
2992  u32 sw_if_index;
2993 
2994  sw_if_index = ~0;
2995 
2996  if (unformat_user (input,
2997  unformat_vnet_sw_interface, vnm, &sw_if_index))
2998  {
2999  error = disable_ip6_interface(vm, sw_if_index);
3000  }
3001  else
3002  {
3003  error = clib_error_return (0, "unknown interface\n'",
3004  format_unformat_error, input);
3005 
3006  }
3007  return error;
3008 }
3009 
3010 VLIB_CLI_COMMAND (disable_ip6_interface_command, static) = {
3011  .path = "disable ip6 interface",
3012  .function = disable_ip6_interface_cmd,
3013  .short_help = "disable ip6 interface <iface name>",
3014 };
3015 
3016 VLIB_CLI_COMMAND (ip6_nd_command, static) = {
3017  .path = "ip6 nd",
3018  .short_help = "Set ip6 neighbor discovery parameters",
3019  .function = ip6_neighbor_cmd,
3020 };
3021 
3022 clib_error_t *
3024  u32 sw_if_index,
3025  ip6_address_t *address,
3026  u8 address_length)
3027 {
3028  clib_error_t * error = 0;
3030  u32 ri;
3031  ip6_radv_t * radv_info;
3032  vnet_main_t * vnm = vnet_get_main();
3033 
3034  if( !ip6_address_is_link_local_unicast (address))
3035  {
3036  vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_LINK_LOCAL;
3037  return(error = clib_error_return (0, "address not link-local",
3039  }
3040 
3041  /* call enable ipv6 */
3042  enable_ip6_interface(vm, sw_if_index);
3043 
3044  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
3045 
3046  if(ri != ~0)
3047  {
3048  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
3049 
3050  /* save if link local address (overwrite default) */
3051 
3052  /* delete the old one */
3053  error = ip6_add_del_interface_address (vm, sw_if_index,
3054  &radv_info->link_local_address,
3055  radv_info->link_local_prefix_len /* address width */,
3056  1 /* is_del */);
3057 
3058  if(!error)
3059  {
3060  /* add the new one */
3061  error = ip6_add_del_interface_address (vm, sw_if_index,
3062  address ,
3063  address_length /* address width */,
3064  0/* is_del */);
3065 
3066  if(!error)
3067  {
3068  radv_info->link_local_address = *address;
3069  radv_info->link_local_prefix_len = address_length;
3070  }
3071  }
3072  }
3073  else
3074  {
3075  vnm->api_errno = VNET_API_ERROR_IP6_NOT_ENABLED;
3076  error = clib_error_return (0, "ip6 not enabled for interface",
3078  }
3079  return error;
3080 }
3081 
3082 clib_error_t *
3084  unformat_input_t * input,
3085  vlib_cli_command_t * cmd)
3086 {
3087  vnet_main_t * vnm = vnet_get_main();
3088  clib_error_t * error = 0;
3089  u32 sw_if_index;
3090  ip6_address_t ip6_addr;
3091  u32 addr_len = 0;
3092 
3093  if (unformat_user (input,
3094  unformat_vnet_sw_interface, vnm, &sw_if_index))
3095  {
3096  /* get the rest of the command */
3097  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3098  {
3099  if(unformat (input, "%U/%d",
3100  unformat_ip6_address, &ip6_addr,
3101  &addr_len))
3102  break;
3103  else
3104  return(unformat_parse_error (input));
3105  }
3106  }
3107  error = set_ip6_link_local_address(vm,
3108  sw_if_index,
3109  &ip6_addr,
3110  addr_len);
3111  return error;
3112 }
3113 
3114 VLIB_CLI_COMMAND (set_ip6_link_local_address_command, static) = {
3115  .path = "set ip6 link-local address",
3116  .short_help = "Set ip6 interface link-local address <intfc> <address.>",
3117  .function = set_ip6_link_local_address_cmd,
3118 };
3119 
3120 /* callback when an interface address is added or deleted */
3121 static void
3123  uword opaque,
3124  u32 sw_if_index,
3125  ip6_address_t * address,
3126  u32 address_length,
3127  u32 if_address_index,
3128  u32 is_delete)
3129 {
3130  vnet_main_t * vnm = vnet_get_main();
3132  u32 ri;
3133  vlib_main_t * vm = vnm->vlib_main;
3134  ip6_radv_t * radv_info;
3135  ip6_address_t a;
3136  ip6_mldp_group_t *mcast_group_info;
3137 
3138  /* create solicited node multicast address for this interface adddress */
3140 
3141  a.as_u8[0xd] = address->as_u8[0xd];
3142  a.as_u8[0xe] = address->as_u8[0xe];
3143  a.as_u8[0xf] = address->as_u8[0xf];
3144 
3145  if(!is_delete)
3146  {
3147  /* try to create radv_info - does nothing if ipv6 already enabled */
3148  enable_ip6_interface(vm, sw_if_index);
3149 
3150  /* look up the radv_t information for this interface */
3152  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
3153  if(ri != ~0)
3154  {
3155  /* get radv_info */
3156  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
3157 
3158  /* add address */
3159  if( !ip6_address_is_link_local_unicast (address))
3160  radv_info->ref_count++;
3161 
3162  /* lookup prefix info for this address on this interface */
3163  uword * p = mhash_get (&radv_info->address_to_mldp_index, &a);
3164  mcast_group_info = p ? pool_elt_at_index (radv_info->mldp_group_pool, p[0]) : 0;
3165 
3166  /* add -solicted node multicast address */
3167  if(!mcast_group_info)
3168  {
3169  /* add */
3170  u32 mi;
3171  pool_get (radv_info->mldp_group_pool, mcast_group_info);
3172 
3173  mi = mcast_group_info - radv_info->mldp_group_pool;
3174  mhash_set (&radv_info->address_to_mldp_index, &a, mi, /* old_value */ 0);
3175 
3176  mcast_group_info->type = 4;
3177  mcast_group_info->mcast_source_address_pool = 0;
3178  mcast_group_info->num_sources = 0;
3179  clib_memcpy(&mcast_group_info->mcast_address, &a, sizeof(ip6_address_t));
3180  }
3181  }
3182  }
3183  else
3184  {
3185 
3186  /* delete */
3187  /* look up the radv_t information for this interface */
3189  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
3190  if(ri != ~0)
3191  {
3192  /* get radv_info */
3193  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
3194 
3195  /* lookup prefix info for this address on this interface */
3196  uword * p = mhash_get (&radv_info->address_to_mldp_index, &a);
3197  mcast_group_info = p ? pool_elt_at_index (radv_info->mldp_group_pool, p[0]) : 0;
3198 
3199  if(mcast_group_info)
3200  {
3201  mhash_unset (&radv_info->address_to_mldp_index, &a,/* old_value */ 0);
3202  pool_put (radv_info->mldp_group_pool, mcast_group_info);
3203  }
3204 
3205  /* if interface up send MLDP "report" */
3206  radv_info->all_routers_mcast = 0;
3207 
3208  /* add address */
3209  if( !ip6_address_is_link_local_unicast (address))
3210  radv_info->ref_count--;
3211  }
3212  }
3213 }
3214 
3216 {
3218 
3219  nm->limit_neighbor_cache_size = neighbor_limit;
3220  return 0;
3221 }
3222 
3223 
3224 static void
3226 {
3227  int done = 0;
3228  int i;
3229  while (!done)
3230  {
3232  if (vec_elt(n->adjacencies, i) == adj_index)
3233  {
3234  vec_del1(n->adjacencies, i);
3235  continue;
3236  }
3237  done = 1;
3238  }
3239 }
3240 
3241 static void
3243 {
3244  int i;
3246  if (vec_elt(n->adjacencies, i) == adj_index)
3247  return;
3248  vec_add1(n->adjacencies, adj_index);
3249 }
3250 
3251 static void
3253  u32 adj_index,
3254  ip_adjacency_t * adj,
3255  u32 is_del)
3256 {
3259  ip6_neighbor_t *n = 0;
3260  uword * p;
3261  u32 ai;
3262 
3263  for(ai = adj->heap_handle; ai < adj->heap_handle + adj->n_adj ; ai++)
3264  {
3265  adj = ip_get_adjacency (lm, ai);
3266  if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP &&
3267  (adj->arp.next_hop.ip6.as_u64[0] || adj->arp.next_hop.ip6.as_u64[1]))
3268  {
3269  k.sw_if_index = adj->rewrite_header.sw_if_index;
3270  k.ip6_address.as_u64[0] = adj->arp.next_hop.ip6.as_u64[0];
3271  k.ip6_address.as_u64[1] = adj->arp.next_hop.ip6.as_u64[1];
3272  k.pad = 0;
3273  p = mhash_get (&nm->neighbor_index_by_key, &k);
3274  if (p)
3275  n = pool_elt_at_index (nm->neighbor_pool, p[0]);
3276  }
3277  else
3278  continue;
3279 
3280  if (is_del)
3281  {
3282  if (!n)
3283  clib_warning("Adjacency contains unknown ND next hop %U (del)",
3284  format_ip46_address, &adj->arp.next_hop, IP46_TYPE_IP6);
3285  else
3287  }
3288  else /* add */
3289  {
3290  if (!n)
3291  clib_warning("Adjacency contains unknown ND next hop %U (add)",
3292  format_ip46_address, &adj->arp.next_hop, IP46_TYPE_IP6);
3293  else
3295  }
3296  }
3297 }
3298 
3300 {
3302  ip6_main_t * im = &ip6_main;
3303  ip_lookup_main_t * lm = &im->lookup_main;
3304 
3306  /* value size */ sizeof (uword),
3307  /* key size */ sizeof (ip6_neighbor_key_t));
3308 
3309  icmp6_register_type (vm, ICMP6_neighbor_solicitation, ip6_icmp_neighbor_solicitation_node.index);
3310  icmp6_register_type (vm, ICMP6_neighbor_advertisement, ip6_icmp_neighbor_advertisement_node.index);
3311  icmp6_register_type (vm, ICMP6_router_solicitation, ip6_icmp_router_solicitation_node.index);
3312  icmp6_register_type (vm, ICMP6_router_advertisement, ip6_icmp_router_advertisement_node.index);
3313 
3314  /* handler node for ip6 neighbor discovery events and timers */
3316 
3317  /* add call backs */
3319  memset(&cb, 0x0, sizeof(ip6_add_del_interface_address_callback_t));
3320 
3321  /* when an interface address changes... */
3323  cb.function_opaque = 0;
3325 
3327  /* value size */ sizeof (uword),
3328  /* key size */ sizeof (ip6_address_t));
3329 
3330  /* default, configurable */
3331  nm->limit_neighbor_cache_size = 50000;
3332 
3333 #if 0
3334  /* $$$$ Hack fix for today */
3336  (im->discover_neighbor_next_index_by_hw_if_index, 32, 0 /* drop */);
3337 #endif
3338 
3340 
3341  return 0;
3342 }
3343 
3345 
3346 
3348  void * address_arg,
3349  uword node_index,
3350  uword type_opaque,
3351  uword data)
3352 {
3354  ip6_address_t * address = address_arg;
3355  uword * p;
3356  pending_resolution_t * pr;
3357 
3358  pool_get (nm->pending_resolutions, pr);
3359 
3360  pr->next_index = ~0;
3361  pr->node_index = node_index;
3362  pr->type_opaque = type_opaque;
3363  pr->data = data;
3364 
3365  p = mhash_get (&nm->pending_resolutions_by_address, address);
3366  if (p)
3367  {
3368  /* Insert new resolution at the head of the list */
3369  pr->next_index = p[0];
3370  mhash_unset (&nm->pending_resolutions_by_address, address, 0);
3371  }
3372 
3373  mhash_set (&nm->pending_resolutions_by_address, address,
3374  pr - nm->pending_resolutions, 0 /* old value */);
3375 }
3376 
format_function_t format_ip46_address
Definition: format.h:54
#define ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:457
ip6_radv_t * if_radv_pool
Definition: ip6_neighbor.c:191
#define MIN_DELAY_BETWEEN_RAS
Definition: ip6_neighbor.c:137
#define DEF_DEF_RTR_LIFETIME
Definition: ip6_neighbor.c:132
#define pool_next_index(P, I)
Return next occupied pool index after i, useful for safe iteration.
Definition: pool.h:377
Definition: mhash.h:46
#define IP6_ROUTE_FLAG_NEIGHBOR
Definition: ip6.h:359
#define vec_foreach_index(var, v)
Iterate over vector indices.
void md5_finish(md5_context_t *c, u8 *digest)
Definition: md5.c:290
icmp6_router_solicitation_or_advertisement_next_t
Definition: ip6_neighbor.c:941
u32 n_solicitations_rcvd
Definition: ip6_neighbor.c:158
static void unset_random_neighbor_entry(void)
Definition: ip6_neighbor.c:262
static void ip6_neighbor_syslog(vlib_main_t *vm, int priority, char *fmt,...)
Definition: ip6_neighbor.c:912
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
void * clib_per_cpu_mheaps[CLIB_MAX_MHEAPS]
Definition: mem_mheap.c:46
#define ICMP6_ROUTER_DISCOVERY_FLAG_OTHER_CONFIG_VIA_DHCP
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
static vlib_node_registration_t ip6_icmp_neighbor_solicitation_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_neighbor_solicitation_node)
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:682
a
Definition: bitmap.h:516
int ip6_neighbor_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)
u8 link_local_prefix_len
Definition: ip6_neighbor.c:163
format_function_t format_ip6_address
Definition: format.h:87
static clib_error_t * ip6_neighbor_init(vlib_main_t *vm)
f64 last_radv_time
Definition: ip6_neighbor.c:147
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
ip_interface_address_t * if_address_pool
Pool of addresses that are assigned to interfaces.
Definition: lookup.h:439
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
static char * log_level_strings[]
Definition: ip6_neighbor.c:903
u16 n_adj
Number of adjecencies in block.
Definition: lookup.h:176
mhash_t neighbor_index_by_key
Definition: ip6_neighbor.c:187
u32 free_list_index
Buffer free list that this buffer was allocated from and will be freed to.
Definition: buffer.h:105
ip_lookup_next_t lookup_next_index
Definition: lookup.h:180
#define PREDICT_TRUE(x)
Definition: clib.h:98
u8 as_u8[16]
Definition: ip6_packet.h:47
u64 as_u64[2]
Definition: ip6_packet.h:50
IP unicast adjacency.
Definition: lookup.h:164
int send_unicast
Definition: ip6_neighbor.c:116
ip6_address_t prefix
Definition: ip6_neighbor.c:49
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:55
static uword ip6_address_is_local_unicast(ip6_address_t *a)
Definition: ip6_packet.h:265
f64 last_multicast_time
Definition: ip6_neighbor.c:148
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
void md5_init(md5_context_t *c)
Definition: md5.c:211
#define NULL
Definition: clib.h:55
uword mhash_unset(mhash_t *h, void *key, uword *old_value)
Definition: mhash.c:353
u32 index
Definition: node.h:237
u32 vlib_buffer_alloc_from_free_list(vlib_main_t *vm, u32 *buffers, u32 n_buffers, u32 free_list_index)
Allocate buffers from specific freelist into supplied array.
Definition: dpdk_buffer.c:655
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
ip6_radv_prefix_t * adv_prefixes_pool
Definition: ip6_neighbor.c:100
static void ip6_neighbor_entry_add_adj(ip6_neighbor_t *n, u32 adj_index)
#define ethernet_buffer_header_size(b)
Determine the size of the Ethernet headers of the current frame in the buffer.
Definition: ethernet.h:358
u8 src_address[6]
Definition: packet.h:54
static uword ip6_address_is_global_unicast(ip6_address_t *a)
Definition: ip6_packet.h:270
pending_resolution_t * pending_resolutions
Definition: ip6_neighbor.c:181
static vlib_cli_command_t set_ip6_neighbor_command
(constructor) VLIB_CLI_COMMAND (set_ip6_neighbor_command)
Definition: ip6_neighbor.c:676
#define ETHER_MAC_ADDR_LEN
Definition: ip6_neighbor.c:34
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
static u32 ip6_src_lookup_for_packet(ip6_main_t *im, vlib_buffer_t *b, ip6_header_t *i)
Definition: ip6.h:309
word vnet_sw_interface_compare(vnet_main_t *vnm, uword sw_if_index0, uword sw_if_index1)
Definition: interface.c:1031
static u64 clib_cpu_time_now(void)
Definition: time.h:73
vlib_node_registration_t ip6_rewrite_node
(constructor) VLIB_REGISTER_NODE (ip6_rewrite_node)
Definition: ip6_forward.c:2637
ip_adjacency_t * ip_add_adjacency(ip_lookup_main_t *lm, ip_adjacency_t *copy_adj, u32 n_adj, u32 *adj_index_return)
Definition: lookup.c:167
static int logmask
Definition: ip6_neighbor.c:909
struct _vlib_node_registration vlib_node_registration_t
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:62
u32 adv_pref_lifetime_in_secs
Definition: ip6_neighbor.c:54
#define DEF_ADV_PREF_LIFETIME
Definition: ip6_neighbor.c:67
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
format_function_t format_vlib_cpu_time
Definition: node_funcs.h:1105
unformat_function_t unformat_vnet_sw_interface
u32 adv_neighbor_reachable_time_in_msec
Definition: ip6_neighbor.c:89
vlib_error_t * errors
Definition: node.h:418
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
ip6_address_t src_address
Definition: ip6_packet.h:298
format_function_t format_vnet_sw_if_index_name
clib_error_t * disable_ip6_interface(vlib_main_t *vm, u32 sw_if_index)
u32 vlib_register_node(vlib_main_t *vm, vlib_node_registration_t *r)
Definition: node.c:446
static uword ip6_neighbor_process_timer_event(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
ethernet_main_t ethernet_main
Definition: ethernet.h:241
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
static void ip6_print_addrs(vlib_main_t *vm, u32 *addrs)
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:78
#define static_always_inline
Definition: clib.h:85
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u32 local_interface_sw_if_index
Definition: vnet.h:62
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(ip6_neighbor_sw_interface_up_down)
u8 link_layer_addr_len
Definition: ip6_neighbor.c:97
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:187
#define ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE
u8 dst_address[6]
Definition: packet.h:53
static clib_error_t * disable_ip6_interface_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static u8 * format_ip6_neighbor_ip6_entry(u8 *s, va_list *va)
Definition: ip6_neighbor.c:201
u32 vnet_ip6_neighbor_glean_add(u32 fib_index, void *next_hop_arg)
Definition: ip6_neighbor.c:524
static uword ip6_icmp_neighbor_discovery_event_process(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static clib_error_t * show_ip6_neighbors(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip6_neighbor.c:600
#define DEF_ADV_VALID_LIFETIME
Definition: ip6_neighbor.c:66
mhash_t address_to_mldp_index
Definition: ip6_neighbor.c:109
static vnet_sw_interface_t * vnet_get_sup_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
#define IP6_NEIGHBOR_FLAG_STATIC
Definition: ip6_neighbor.c:40
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: memory_vlib.c:1321
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
#define clib_warning(format, args...)
Definition: error.h:59
u32 table_index_or_table_id
Definition: ip6.h:367
unsigned long u64
Definition: types.h:89
f64 max_radv_interval
Definition: ip6_neighbor.c:141
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
static clib_error_t * set_ip6_neighbor(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip6_neighbor.c:635
u32 * neighbor_input_next_index_by_hw_if_index
Definition: ip6_neighbor.c:183
void ip6_add_del_route(ip6_main_t *im, ip6_add_del_route_args_t *args)
Definition: ip6_forward.c:208
void ip_del_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.c:314
#define MAX_DELAY_BETWEEN_RAS
Definition: ip6_neighbor.c:138
f64 max_delay_between_radv
Definition: ip6_neighbor.c:144
u32 adv_time_in_msec_between_retransmitted_neighbor_solicitations
Definition: ip6_neighbor.c:90
vnet_api_error_t api_errno
Definition: vnet.h:78
ip6_address_t dst_address
Definition: ip6.h:370
format_function_t format_vnet_sw_interface_name
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
static void ip6_neighbor_entry_del_adj(ip6_neighbor_t *n, u32 adj_index)
vlib_main_t * vlib_main
Definition: vnet.h:80
f64 min_radv_interval
Definition: ip6_neighbor.c:142
void vnet_register_ip6_neighbor_resolution_event(vnet_main_t *vnm, void *address_arg, uword node_index, uword type_opaque, uword data)
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:929
static void ip6_neighbor_add_del_adj_cb(struct ip_lookup_main_t *lm, u32 adj_index, ip_adjacency_t *adj, u32 is_del)
uword type_opaque
Definition: arp.c:67
int vnet_unset_ip6_ethernet_neighbor(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *a, u8 *link_layer_address, uword n_bytes_link_layer_address)
Definition: ip6_neighbor.c:468
int all_routers_mcast
Definition: ip6_neighbor.c:120
u32 all_nodes_adj_index
Definition: ip6_neighbor.c:124
static clib_error_t * enable_ip6_interface_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
#define DEF_MAX_RADV_INTERVAL
Definition: ip6_neighbor.c:129
ip_adjacency_t * add_adj
Definition: ip6.h:379
#define IP6_MLDP_ALERT_TYPE
u8 link_layer_address[8]
Definition: ip6_neighbor.c:96
f64 next_multicast_time
Definition: ip6_neighbor.c:149
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
#define foreach_log_level
Definition: ip6_neighbor.c:887
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:334
enum icmp6_neighbor_discovery_option_type icmp6_neighbor_discovery_option_type_t
#define ELOG_DATA(em, f)
Definition: elog.h:392
#define unformat_parse_error(input)
Definition: format.h:267
int ip6_address_compare(ip6_address_t *a1, ip6_address_t *a2)
Definition: ip46_cli.c:45
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:765
vnet_main_t vnet_main
Definition: misc.c:42
#define VLIB_FRAME_SIZE
Definition: node.h:328
int adv_other_flag
Definition: ip6_neighbor.c:87
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:194
mhash_t address_to_prefix_index
Definition: ip6_neighbor.c:103
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:214
#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:130
static uword mhash_set(mhash_t *h, void *key, uword new_value, uword *old_value)
Definition: mhash.h:117
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:348
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
ip6_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Definition: ip6.h:136
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:118
void ip6_link_local_address_from_ethernet_mac_address(ip6_address_t *ip, u8 *mac)
Definition: ip6_forward.c:3085
unformat_function_t unformat_ip6_address
Definition: format.h:86
int failed_device_check
Definition: ip6_neighbor.c:119
vlib_node_registration_t ip6_icmp_input_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_input_node)
Definition: icmp6.c:226
ip6_mldp_group_t * mldp_group_pool
Definition: ip6_neighbor.c:106
static_always_inline uword icmp6_neighbor_solicitation_or_advertisement(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, uword is_solicitation)
Definition: ip6_neighbor.c:689
clib_error_t * enable_ip6_interface(vlib_main_t *vm, u32 sw_if_index)
icmp6_neighbor_solicitation_or_advertisement_next_t
Definition: ip6_neighbor.c:682
int adv_managed_flag
Definition: ip6_neighbor.c:86
static uword icmp6_neighbor_advertisement(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
u32 n_solicitations_dropped
Definition: ip6_neighbor.c:159
void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
Definition: mhash.c:168
static void set_unset_ip6_neighbor_rpc(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *a, u8 *link_layer_addreess, int is_add, int is_static)
Definition: ip6_neighbor.c:305
u16 n_vectors
Definition: node.h:344
u8 * va_format(u8 *s, char *fmt, va_list *va)
Definition: format.c:386
ip6_address_t mcast_address
Definition: ip6_neighbor.c:76
log_level_t
Definition: ip6_neighbor.c:897
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
void vnet_rewrite_for_sw_interface(vnet_main_t *vnm, vnet_l3_packet_type_t packet_type, u32 sw_if_index, u32 node_index, void *dst_address, vnet_rewrite_header_t *rw, u32 max_rewrite_bytes)
Definition: rewrite.c:190
u8 curr_hop_limit
Definition: ip6_neighbor.c:85
static void * clib_mem_set_heap(void *heap)
Definition: mem.h:201
ip6_address_t * mcast_source_address_pool
Definition: ip6_neighbor.c:78
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:88
#define clib_memcpy(a, b, c)
Definition: string.h:63
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:200
u32 ip6_fib_lookup_with_table(ip6_main_t *im, u32 fib_index, ip6_address_t *dst)
Definition: ip6_forward.c:61
#define DEF_CURR_HOP_LIMIT
Definition: ip6_neighbor.c:131
#define IP6_ROUTE_FLAG_DEL
Definition: ip6.h:352
elog_main_t elog_main
Definition: main.h:141
int adv_link_layer_address
Definition: ip6_neighbor.c:117
static ip_interface_address_t * ip_get_interface_address(ip_lookup_main_t *lm, void *addr_fib)
Definition: lookup.h:594
static uword * mhash_get(mhash_t *h, void *key)
Definition: mhash.h:110
static vlib_cli_command_t show_ip6_neighbors_command
(constructor) VLIB_CLI_COMMAND (show_ip6_neighbors_command)
Definition: ip6_neighbor.c:628
void vlib_worker_thread_barrier_sync(vlib_main_t *vm)
Definition: threads.c:1144
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:350
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: lookup.h:73
static void ip6_addr_fib_init(ip6_address_fib_t *addr_fib, ip6_address_t *address, u32 fib_index)
Definition: ip6_packet.h:75
void md5_add(md5_context_t *c, void *data, int data_bytes)
Definition: md5.c:235
u64 cpu_time_last_updated
Definition: ip6_neighbor.c:42
static void * ip6_next_header(ip6_header_t *i)
Definition: ip6_packet.h:302
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
Definition: buffer.h:303
u32 initial_adverts_count
Definition: ip6_neighbor.c:152
u32 * if_address_pool_index_by_sw_if_index
Head of doubly linked list of interface addresses for each software interface.
Definition: lookup.h:446
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:1666
ip6_add_del_interface_address_function_t * function
Definition: ip6.h:103
#define MAX_INITIAL_RTR_ADVERTISEMENTS
Definition: ip6_neighbor.c:136
u16 cached_next_index
Definition: node.h:462
ip6_address_t link_local_address
Definition: ip6_neighbor.c:162
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:415
u32 max_l3_packet_bytes[VLIB_N_RX_TX]
Definition: interface.h:345
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:206
static void ip_register_add_del_adjacency_callback(ip_lookup_main_t *lm, ip_add_del_adjacency_callback_t cb)
Definition: lookup.h:530
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
int prefix_option
Definition: ip6_neighbor.c:118
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define vnet_buffer(b)
Definition: buffer.h:335
ip6_address_t ip6_address
Definition: ip6_neighbor.c:28
ip6_main_t ip6_main
Definition: ip6_forward.c:2955
ip_lookup_main_t lookup_main
Definition: ip6.h:110
u32 n_advertisements_sent
Definition: ip6_neighbor.c:157
static clib_error_t * show_ip6_interface_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
f64 min_delay_between_radv
Definition: ip6_neighbor.c:143
#define DEF_MIN_RADV_INTERVAL
Definition: ip6_neighbor.c:130
static_always_inline uword icmp6_router_solicitation(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip6_neighbor.c:949
static int ip6_neighbor_sort(void *a1, void *a2)
Definition: ip6_neighbor.c:587
u32 vlib_buffer_add_data(vlib_main_t *vm, u32 free_list_index, u32 buffer_index, void *data, u32 n_data_bytes)
Definition: dpdk_buffer.c:851
u32 * if_radv_pool_index_by_sw_if_index
Definition: ip6_neighbor.c:189
u16 adv_router_lifetime_in_sec
Definition: ip6_neighbor.c:88
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
void ip_update_adjacency(ip_lookup_main_t *lm, u32 adj_index, ip_adjacency_t *copy_adj)
Definition: lookup.c:263
mhash_t pending_resolutions_by_address
Definition: ip6_neighbor.c:180
static uword icmp6_neighbor_solicitation(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define IP6_ROUTE_FLAG_FIB_INDEX
Definition: ip6.h:354
static uword vnet_sw_interface_is_admin_up(vnet_main_t *vnm, u32 sw_if_index)
u64 uword
Definition: types.h:112
#define vec_elt(v, i)
Get vector value at index i.
int vnet_set_ip6_ethernet_neighbor(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *a, u8 *link_layer_address, uword n_bytes_link_layer_address, int is_static)
Definition: ip6_neighbor.c:326
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:285
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
static vlib_node_registration_t ip6_icmp_router_solicitation_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_router_solicitation_node)
#define IP6_NEIGHBOR_FLAG_GLEAN
Definition: ip6_neighbor.c:41
Definition: defs.h:47
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:45
clib_error_t * set_ip6_link_local_address_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static void ip6_neighbor_send_mldpv2_report(u32 sw_if_index)
unsigned short u16
Definition: types.h:57
vlib_node_registration_t ip6_icmp_neighbor_discovery_event_node
u16 payload_length
Definition: ip6_packet.h:289
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
static void * vlib_process_get_event_data(vlib_main_t *vm, uword *return_event_type_opaque)
Definition: node_funcs.h:471
static void ip6_neighbor_set_unset_rpc_callback(ip6_neighbor_set_unset_rpc_args_t *a)
Definition: ip6_neighbor.c:574
ethernet_interface_t * ethernet_get_interface(ethernet_main_t *em, u32 hw_if_index)
Definition: interface.c:515
static void ip6_set_solicited_node_multicast_address(ip6_address_t *a, u32 id)
Definition: ip6_packet.h:135
ip6_neighbor_key_t key
Definition: ip6_neighbor.c:37
static uword ip6_address_is_link_local_unicast(ip6_address_t *a)
Definition: ip6_packet.h:260
u32 elog_string(elog_main_t *em, char *fmt,...)
Definition: elog.c:525
void icmp6_register_type(vlib_main_t *vm, icmp6_type_t type, u32 node_index)
Definition: icmp6.c:778
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
ip46_address_t next_hop
Definition: lookup.h:194
unsigned char u8
Definition: types.h:56
u32 heap_handle
Handle for this adjacency in adjacency heap.
Definition: lookup.h:167
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:900
int ip6_neighbor_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)
static void ip6_neighbor_add_del_interface_address(ip6_main_t *im, uword opaque, u32 sw_if_index, ip6_address_t *address, u32 address_length, u32 if_address_index, u32 is_delete)
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:251
#define ICMP6_ROUTER_DISCOVERY_FLAG_ADDRESS_CONFIG_VIA_DHCP
clib_error_t * set_ip6_link_local_address(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *address, u8 address_length)
static u32 ip6_neighbor_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
static vlib_node_registration_t ip6_icmp_neighbor_advertisement_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_neighbor_advertisement_node)
static clib_error_t * ip6_neighbor_sw_interface_up_down(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: ip6_neighbor.c:231
f64 initial_adverts_interval
Definition: ip6_neighbor.c:153
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1176
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
vnet_sw_interface_type_t type
Definition: interface.h:410
uword node_index
Definition: arp.c:66
This packet is to be rewritten and forwarded to the next processing node.
Definition: lookup.h:78
#define IP6_ROUTE_FLAG_ADD
Definition: ip6.h:351
u32 if_address_index
Interface address index for this local/arp adjacency.
Definition: lookup.h:172
#define vec_foreach(var, vec)
Vector iterator.
static uword ip6_address_is_unspecified(ip6_address_t *a)
Definition: ip6_packet.h:243
struct ip_adjacency_t::@143::@145 arp
IP_LOOKUP_NEXT_ARP only.
i16 explicit_fib_index
Force re-lookup in a different FIB.
Definition: lookup.h:185
u32 adv_valid_lifetime_in_secs
Definition: ip6_neighbor.c:53
clib_error_t * ip6_add_del_interface_address(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *address, u32 address_length, u32 is_del)
Definition: ip6_forward.c:1204
vhost_vring_addr_t addr
Definition: vhost-user.h:82
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
u32 initial_adverts_sent
Definition: ip6_neighbor.c:154
static void * ip_interface_address_get_address(ip_lookup_main_t *lm, ip_interface_address_t *a)
Definition: lookup.h:601
static void ip6_link_local_address_from_ethernet_address(ip6_address_t *a, u8 *ethernet_address)
Definition: ip6_packet.h:147
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:185
#define MAX_INITIAL_RTR_ADVERT_INTERVAL
Definition: ip6_neighbor.c:135
u32 flags
Definition: vhost-user.h:76
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:445
u32 all_mldv2_routers_adj_index
Definition: ip6_neighbor.c:126
clib_error_t * ip6_neighbor_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
f64 max_rtr_default_lifetime
Definition: ip6_neighbor.c:145
unformat_function_t unformat_line_input
Definition: format.h:281
static vlib_node_registration_t ip6_icmp_router_advertisement_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_router_advertisement_node)
ip6_neighbor_t * neighbor_pool
Definition: ip6_neighbor.c:185
u32 * fib_index_by_sw_if_index
Definition: ip6.h:123
u32 all_routers_adj_index
Definition: ip6_neighbor.c:125
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
u8 link_layer_address[8]
Definition: ip6_neighbor.c:38
static u64 random_u64(u32 *seed)
64-bit random number generator
Definition: random.h:126
static_always_inline uword icmp6_router_advertisement(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define MAX_DEF_RTR_LIFETIME
Definition: ip6_neighbor.c:133
u32 adv_link_mtu
Definition: ip6_neighbor.c:93
Definition: defs.h:46
static ip6_neighbor_main_t ip6_neighbor_main
Definition: ip6_neighbor.c:199
ip6_address_t dst_address
Definition: ip6_packet.h:298
int ip6_interface_enabled(vlib_main_t *vm, u32 sw_if_index)
static void ip6_set_reserved_multicast_address(ip6_address_t *a, ip6_multicast_address_scope_t scope, u16 id)
Definition: ip6_packet.h:125
static ip_adjacency_t * ip_get_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.h:480
clib_error_t * ip6_set_neighbor_limit(u32 neighbor_limit)
format_function_t format_icmp6_input_trace
Definition: icmp6.h:66
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109