FD.io VPP  v17.04.2-2-ga8f93f8
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/ip/ip6_neighbor.h>
20 #include <vnet/ethernet/ethernet.h>
21 #include <vppinfra/mhash.h>
22 #include <vppinfra/md5.h>
23 #include <vnet/adj/adj.h>
24 #include <vnet/adj/adj_mcast.h>
25 #include <vnet/fib/fib_table.h>
26 #include <vnet/fib/ip6_fib.h>
27 #include <vnet/mfib/ip6_mfib.h>
28 
29 /**
30  * @file
31  * @brief IPv6 Neighbor Adjacency and Neighbor Discovery.
32  *
33  * The files contains the API and CLI code for managing IPv6 neighbor
34  * adjacency tables and neighbor discovery logic.
35  */
36 
37 /* can't use sizeof link_layer_address, that's 8 */
38 #define ETHER_MAC_ADDR_LEN 6
39 
40 /* advertised prefix option */
41 typedef struct
42 {
43  /* basic advertised information */
50 
51  /* advertised values are computed from these times if decrementing */
54 
55  /* local information */
56  int enabled;
59 
60 #define MIN_ADV_VALID_LIFETIME 7203 /* seconds */
61 #define DEF_ADV_VALID_LIFETIME 2592000
62 #define DEF_ADV_PREF_LIFETIME 604800
63 
64  /* extensions are added here, mobile, DNS etc.. */
66 
67 
68 typedef struct
69 {
70  /* group information */
76 
77 /* configured router advertisement information per ipv6 interface */
78 typedef struct
79 {
80 
81  /* advertised config information, zero means unspecified */
88 
89  /* mtu option */
91 
92  /* source link layer option */
93  u8 link_layer_address[8];
95 
96  /* prefix option */
98 
99  /* Hash table mapping address to index in interface advertised prefix pool. */
101 
102  /* MLDP group information */
104 
105  /* Hash table mapping address to index in mldp address pool. */
107 
108  /* local information */
110  int send_radv; /* radv on/off on this interface - set by config */
111  int cease_radv; /* we are ceasing to send - set byf config */
121 
122  /* timing information */
123 #define DEF_MAX_RADV_INTERVAL 200
124 #define DEF_MIN_RADV_INTERVAL .75 * DEF_MAX_RADV_INTERVAL
125 #define DEF_CURR_HOP_LIMIT 64
126 #define DEF_DEF_RTR_LIFETIME 3 * DEF_MAX_RADV_INTERVAL
127 #define MAX_DEF_RTR_LIFETIME 9000
128 
129 #define MAX_INITIAL_RTR_ADVERT_INTERVAL 16 /* seconds */
130 #define MAX_INITIAL_RTR_ADVERTISEMENTS 3 /*transmissions */
131 #define MIN_DELAY_BETWEEN_RAS 3 /* seconds */
132 #define MAX_DELAY_BETWEEN_RAS 1800 /* seconds */
133 #define MAX_RA_DELAY_TIME .5 /* seconds */
134 
140 
144 
145 
149 
150  /* stats */
154 
155  /* Link local address to use (defaults to underlying physical for logical interfaces */
157 } ip6_radv_t;
158 
159 typedef struct
160 {
161  u32 next_index;
162  uword node_index;
163  uword type_opaque;
164  uword data;
165  /* Used for nd event notification only */
166  void *data_callback;
167  u32 pid;
169 
170 
171 typedef struct
172 {
173  /* Hash tables mapping name to opcode. */
175 
176  /* lite beer "glean" adjacency handling */
179 
180  /* Mac address change notification */
183 
185 
187 
189 
191 
193 
194  /* Neighbor attack mitigation */
197 
199 
200 /* ipv6 neighbor discovery - timer/event types */
201 typedef enum
202 {
205 
206 typedef union
207 {
209  struct
210  {
213  } up_down_event;
215 
217 static ip6_address_t ip6a_zero; /* ip6 address 0 */
218 
219 static u8 *
221 {
222  vlib_main_t *vm = va_arg (*va, vlib_main_t *);
223  ip6_neighbor_t *n = va_arg (*va, ip6_neighbor_t *);
224  vnet_main_t *vnm = vnet_get_main ();
226  u8 *flags = 0;
227 
228  if (!n)
229  return format (s, "%=12s%=20s%=6s%=20s%=40s", "Time", "Address", "Flags",
230  "Link layer", "Interface");
231 
233  flags = format (flags, "D");
234 
236  flags = format (flags, "S");
237 
239  flags = format (flags, "N");
240 
241  si = vnet_get_sw_interface (vnm, n->key.sw_if_index);
242  s = format (s, "%=12U%=20U%=6s%=20U%=40U",
245  flags ? (char *) flags : "",
248 
249  vec_free (flags);
250  return s;
251 }
252 
253 static clib_error_t *
255  u32 sw_if_index, u32 flags)
256 {
258  ip6_neighbor_t *n;
259 
260  if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
261  {
262  u32 i, *to_delete = 0;
263 
264  /* *INDENT-OFF* */
265  pool_foreach (n, nm->neighbor_pool,
266  ({
267  if (n->key.sw_if_index == sw_if_index)
268  vec_add1 (to_delete, n - nm->neighbor_pool);
269  }));
270  /* *INDENT-ON* */
271 
272  for (i = 0; i < vec_len (to_delete); i++)
273  {
274  n = pool_elt_at_index (nm->neighbor_pool, to_delete[i]);
275  mhash_unset (&nm->neighbor_index_by_key, &n->key, 0);
278  pool_put (nm->neighbor_pool, n);
279  }
280 
281  vec_free (to_delete);
282  }
283 
284  return 0;
285 }
286 
288 
289 static void
291 {
293  vnet_main_t *vnm = vnet_get_main ();
294  vlib_main_t *vm = vnm->vlib_main;
295  ip6_neighbor_t *e;
296  u32 index;
297 
299  nm->neighbor_delete_rotor = index;
300 
301  /* Try again from elt 0, could happen if an intfc goes down */
302  if (index == ~0)
303  {
305  nm->neighbor_delete_rotor = index;
306  }
307 
308  /* Nothing left in the pool */
309  if (index == ~0)
310  return;
311 
312  e = pool_elt_at_index (nm->neighbor_pool, index);
313 
315  &e->key.ip6_address,
318 }
319 
320 typedef struct
321 {
325  u8 link_layer_address[6];
329 
332 
333 static void set_unset_ip6_neighbor_rpc
335  u32 sw_if_index,
336  ip6_address_t * a, u8 * link_layer_address, int is_add, int is_static,
337  int is_no_fib_entry)
338 {
340  void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length);
341 
342  args.sw_if_index = sw_if_index;
343  args.is_add = is_add;
344  args.is_static = is_static;
345  args.is_no_fib_entry = is_no_fib_entry;
346  clib_memcpy (&args.addr, a, sizeof (*a));
347  if (NULL != link_layer_address)
348  clib_memcpy (args.link_layer_address, link_layer_address, 6);
349 
351  (u8 *) & args, sizeof (args));
352 }
353 
354 static void
356 {
357  icmp6_neighbor_solicitation_header_t *h;
358  vnet_main_t *vnm = vnet_get_main ();
359  ip6_main_t *im = &ip6_main;
361  ip6_address_t *dst, *src;
364  vlib_buffer_t *b;
365  int bogus_length;
366  vlib_main_t *vm;
367  u32 bi = 0;
368 
369  vm = vlib_get_main ();
370 
371  si = vnet_get_sw_interface (vnm, adj->rewrite_header.sw_if_index);
372  dst = &adj->sub_type.nbr.next_hop.ip6;
373 
375  {
376  return;
377  }
379  adj->rewrite_header.
380  sw_if_index, &ia);
381  if (!src)
382  {
383  return;
384  }
385 
388  &bi);
389 
390  hi = vnet_get_sup_hw_interface (vnm, adj->rewrite_header.sw_if_index);
391 
392  h->ip.dst_address.as_u8[13] = dst->as_u8[13];
393  h->ip.dst_address.as_u8[14] = dst->as_u8[14];
394  h->ip.dst_address.as_u8[15] = dst->as_u8[15];
395  h->ip.src_address = src[0];
396  h->neighbor.target_address = dst[0];
397 
398  clib_memcpy (h->link_layer_option.ethernet_address,
399  hi->hw_address, vec_len (hi->hw_address));
400 
401  h->neighbor.icmp.checksum =
402  ip6_tcp_udp_icmp_compute_checksum (vm, 0, &h->ip, &bogus_length);
403  ASSERT (bogus_length == 0);
404 
405  b = vlib_get_buffer (vm, bi);
406  vnet_buffer (b)->sw_if_index[VLIB_RX] =
407  vnet_buffer (b)->sw_if_index[VLIB_TX] = adj->rewrite_header.sw_if_index;
408 
409  /* Add encapsulation string for software interface (e.g. ethernet header). */
410  vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t));
411  vlib_buffer_advance (b, -adj->rewrite_header.data_bytes);
412 
413  {
415  u32 *to_next = vlib_frame_vector_args (f);
416  to_next[0] = bi;
417  f->n_vectors = 1;
419  }
420 }
421 
422 static void
424 {
427  nbr->key.sw_if_index,
428  adj_get_link_type (ai),
429  nbr->link_layer_address));
430 }
431 
432 static void
434 {
435  ip_adjacency_t *adj = adj_get (ai);
436 
440  adj->rewrite_header.
441  sw_if_index,
442  adj_get_link_type (ai),
444 }
445 
446 #define IP6_NBR_MK_KEY(k, sw_if_index, addr) \
447 { \
448  k.sw_if_index = sw_if_index; \
449  k.ip6_address = *addr; \
450  k.pad = 0; \
451 }
452 
453 static ip6_neighbor_t *
454 ip6_nd_find (u32 sw_if_index, const ip6_address_t * addr)
455 {
457  ip6_neighbor_t *n = NULL;
459  uword *p;
460 
461  IP6_NBR_MK_KEY (k, sw_if_index, addr);
462 
463  p = mhash_get (&nm->neighbor_index_by_key, &k);
464  if (p)
465  {
466  n = pool_elt_at_index (nm->neighbor_pool, p[0]);
467  }
468 
469  return (n);
470 }
471 
472 static adj_walk_rc_t
474 {
475  ip6_neighbor_t *nbr = ctx;
476 
477  ip6_nd_mk_complete (ai, nbr);
478 
479  return (ADJ_WALK_RC_CONTINUE);
480 }
481 
482 static adj_walk_rc_t
484 {
486 
487  return (ADJ_WALK_RC_CONTINUE);
488 }
489 
490 void
492 {
493  ip6_neighbor_t *nbr;
494  ip_adjacency_t *adj;
495 
496  adj = adj_get (ai);
497 
498  nbr = ip6_nd_find (sw_if_index, &adj->sub_type.nbr.next_hop.ip6);
499 
500  switch (adj->lookup_next_index)
501  {
502  case IP_LOOKUP_NEXT_ARP:
504  if (NULL != nbr)
505  {
506  adj_nbr_walk_nh6 (sw_if_index, &nbr->key.ip6_address,
508  }
509  else
510  {
511  /*
512  * no matching ND entry.
513  * construct the rewrite required to for an ND packet, and stick
514  * that in the adj's pipe to smoke.
515  */
519  sw_if_index,
522 
523  /*
524  * since the FIB has added this adj for a route, it makes sense it may
525  * want to forward traffic sometime soon. Let's send a speculative ND.
526  * just one. If we were to do periodically that wouldn't be bad either,
527  * but that's more code than i'm prepared to write at this time for
528  * relatively little reward.
529  */
530  ip6_nbr_probe (adj);
531  }
532  break;
534  /*
535  * Construct a partial rewrite from the known ethernet mcast dest MAC
536  */
538  (ai,
540  sw_if_index,
541  adj->ia_link,
543 
544  /*
545  * Complete the remaining fields of the adj's rewrite to direct the
546  * complete of the rewrite at switch time by copying in the IP
547  * dst address's bytes.
548  * Ofset is 12 bytes from the end of the MAC header - which is 2
549  * bytes into the desintation address. And we write 4 bytes.
550  */
551  adj->rewrite_header.dst_mcast_offset = 12;
552  adj->rewrite_header.dst_mcast_n_bytes = 4;
553 
554  break;
555 
556  case IP_LOOKUP_NEXT_DROP:
557  case IP_LOOKUP_NEXT_PUNT:
563  case IP_LOOKUP_N_NEXT:
564  ASSERT (0);
565  break;
566  }
567 }
568 
569 int
571  u32 sw_if_index,
572  ip6_address_t * a,
573  u8 * link_layer_address,
574  uword n_bytes_link_layer_address,
575  int is_static, int is_no_fib_entry)
576 {
579  ip6_neighbor_t *n = 0;
580  int make_new_nd_cache_entry = 1;
581  uword *p;
582  u32 next_index;
583  pending_resolution_t *pr, *mc;
584 
585  if (os_get_cpu_number ())
586  {
587  set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, link_layer_address,
588  1 /* set new neighbor */ , is_static,
589  is_no_fib_entry);
590  return 0;
591  }
592 
593  k.sw_if_index = sw_if_index;
594  k.ip6_address = a[0];
595  k.pad = 0;
596 
597  p = mhash_get (&nm->neighbor_index_by_key, &k);
598  if (p)
599  {
600  n = pool_elt_at_index (nm->neighbor_pool, p[0]);
601  /* Refuse to over-write static neighbor entry. */
602  if (!is_static && (n->flags & IP6_NEIGHBOR_FLAG_STATIC))
603  return -2;
604  make_new_nd_cache_entry = 0;
605  }
606 
607  if (make_new_nd_cache_entry)
608  {
609  pool_get (nm->neighbor_pool, n);
610  mhash_set (&nm->neighbor_index_by_key, &k, n - nm->neighbor_pool,
611  /* old value */ 0);
612  n->key = k;
614 
616  link_layer_address, n_bytes_link_layer_address);
617 
618  /*
619  * create the adj-fib. the entry in the FIB table for and to the peer.
620  */
621  if (!is_no_fib_entry)
622  {
623  fib_prefix_t pfx = {
624  .fp_len = 128,
625  .fp_proto = FIB_PROTOCOL_IP6,
626  .fp_addr.ip6 = k.ip6_address,
627  };
628  u32 fib_index;
629 
631  n->fib_entry_index =
632  fib_table_entry_update_one_path (fib_index, &pfx,
636  n->key.sw_if_index, ~0, 1, NULL,
639  }
640  }
641  else
642  {
643  /*
644  * prevent a DoS attack from the data-plane that
645  * spams us with no-op updates to the MAC address
646  */
647  if (0 == memcmp (n->link_layer_address,
648  link_layer_address, n_bytes_link_layer_address))
649  return -1;
650 
652  link_layer_address, n_bytes_link_layer_address);
653  }
654 
655  /* Update time stamp and flags. */
657  if (is_static)
659  else
661 
662  adj_nbr_walk_nh6 (sw_if_index,
664 
665  /* Customer(s) waiting for this address to be resolved? */
667  if (p)
668  {
669  next_index = p[0];
670 
671  while (next_index != (u32) ~ 0)
672  {
673  pr = pool_elt_at_index (nm->pending_resolutions, next_index);
675  pr->type_opaque, pr->data);
676  next_index = pr->next_index;
677  pool_put (nm->pending_resolutions, pr);
678  }
679 
681  }
682 
683  /* Customer(s) requesting ND event for this address? */
684  p = mhash_get (&nm->mac_changes_by_address, a);
685  if (p)
686  {
687  next_index = p[0];
688 
689  while (next_index != (u32) ~ 0)
690  {
691  int (*fp) (u32, u8 *, u32, ip6_address_t *);
692  int rv = 1;
693  mc = pool_elt_at_index (nm->mac_changes, next_index);
694  fp = mc->data_callback;
695 
696  /* Call the user's data callback, return 1 to suppress dup events */
697  if (fp)
698  rv =
699  (*fp) (mc->data, link_layer_address, sw_if_index, &ip6a_zero);
700  /*
701  * Signal the resolver process, as long as the user
702  * says they want to be notified
703  */
704  if (rv == 0)
706  mc->type_opaque, mc->data);
707  next_index = mc->next_index;
708  }
709  }
710 
711  return 0;
712 }
713 
714 int
716  u32 sw_if_index,
717  ip6_address_t * a,
718  u8 * link_layer_address,
719  uword n_bytes_link_layer_address)
720 {
723  ip6_neighbor_t *n;
724  uword *p;
725  int rv = 0;
726 
727  if (os_get_cpu_number ())
728  {
729  set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, link_layer_address,
730  0 /* unset */ , 0, 0);
731  return 0;
732  }
733 
734  k.sw_if_index = sw_if_index;
735  k.ip6_address = a[0];
736  k.pad = 0;
737 
738  p = mhash_get (&nm->neighbor_index_by_key, &k);
739  if (p == 0)
740  {
741  rv = -1;
742  goto out;
743  }
744 
745  n = pool_elt_at_index (nm->neighbor_pool, p[0]);
746  mhash_unset (&nm->neighbor_index_by_key, &n->key, 0);
747 
748  adj_nbr_walk_nh6 (sw_if_index,
750 
751 
754  pool_put (nm->neighbor_pool, n);
755 
756 out:
757  return rv;
758 }
759 
762 {
763  vlib_main_t *vm = vlib_get_main ();
764  if (a->is_add)
766  a->link_layer_address, 6, a->is_static,
767  a->is_no_fib_entry);
768  else
770  a->link_layer_address, 6);
771 }
772 
773 static int
774 ip6_neighbor_sort (void *a1, void *a2)
775 {
776  vnet_main_t *vnm = vnet_get_main ();
777  ip6_neighbor_t *n1 = a1, *n2 = a2;
778  int cmp;
779  cmp = vnet_sw_interface_compare (vnm, n1->key.sw_if_index,
780  n2->key.sw_if_index);
781  if (!cmp)
782  cmp = ip6_address_compare (&n1->key.ip6_address, &n2->key.ip6_address);
783  return cmp;
784 }
785 
788 {
790  ip6_neighbor_t *n, *ns = 0;
791 
792  /* *INDENT-OFF* */
793  pool_foreach (n, nm->neighbor_pool,
794  ({
795  if (sw_if_index != ~0 && n->key.sw_if_index != sw_if_index)
796  continue;
797  vec_add1 (ns, n[0]);
798  }));
799  /* *INDENT-ON* */
800 
801  if (ns)
803  return ns;
804 }
805 
806 static clib_error_t *
808  unformat_input_t * input, vlib_cli_command_t * cmd)
809 {
810  vnet_main_t *vnm = vnet_get_main ();
811  ip6_neighbor_t *n, *ns;
812  clib_error_t *error = 0;
813  u32 sw_if_index;
814 
815  /* Filter entries by interface if given. */
816  sw_if_index = ~0;
817  (void) unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index);
818 
819  ns = ip6_neighbors_entries (sw_if_index);
820  if (ns)
821  {
823  vec_foreach (n, ns)
824  {
826  }
827  vec_free (ns);
828  }
829 
830  return error;
831 }
832 
833 /*?
834  * This command is used to display the adjacent IPv6 hosts found via
835  * neighbor discovery. Optionally, limit the output to the specified
836  * interface.
837  *
838  * @cliexpar
839  * Example of how to display the IPv6 neighbor adjacency table:
840  * @cliexstart{show ip6 neighbors}
841  * Time Address Flags Link layer Interface
842  * 34.0910 ::a:1:1:0:7 02:fe:6a:07:39:6f GigabitEthernet2/0/0
843  * 173.2916 ::b:5:1:c:2 02:fe:50:62:3a:94 GigabitEthernet2/0/0
844  * 886.6654 ::1:1:c:0:9 S 02:fe:e4:45:27:5b GigabitEthernet3/0/0
845  * @cliexend
846  * Example of how to display the IPv6 neighbor adjacency table for given interface:
847  * @cliexstart{show ip6 neighbors GigabitEthernet2/0/0}
848  * Time Address Flags Link layer Interface
849  * 34.0910 ::a:1:1:0:7 02:fe:6a:07:39:6f GigabitEthernet2/0/0
850  * 173.2916 ::b:5:1:c:2 02:fe:50:62:3a:94 GigabitEthernet2/0/0
851  * @cliexend
852 ?*/
853 /* *INDENT-OFF* */
855  .path = "show ip6 neighbors",
856  .function = show_ip6_neighbors,
857  .short_help = "show ip6 neighbors [<interface>]",
858 };
859 /* *INDENT-ON* */
860 
861 static clib_error_t *
863  unformat_input_t * input, vlib_cli_command_t * cmd)
864 {
865  vnet_main_t *vnm = vnet_get_main ();
867  u8 mac_address[6];
868  int addr_valid = 0;
869  int is_del = 0;
870  int is_static = 0;
871  int is_no_fib_entry = 0;
872  u32 sw_if_index;
873 
875  {
876  /* intfc, ip6-address, mac-address */
877  if (unformat (input, "%U %U %U",
878  unformat_vnet_sw_interface, vnm, &sw_if_index,
879  unformat_ip6_address, &addr,
880  unformat_ethernet_address, mac_address))
881  addr_valid = 1;
882 
883  else if (unformat (input, "delete") || unformat (input, "del"))
884  is_del = 1;
885  else if (unformat (input, "static"))
886  is_static = 1;
887  else if (unformat (input, "no-fib-entry"))
888  is_no_fib_entry = 1;
889  else
890  break;
891  }
892 
893  if (!addr_valid)
894  return clib_error_return (0, "Missing interface, ip6 or hw address");
895 
896  if (!is_del)
897  vnet_set_ip6_ethernet_neighbor (vm, sw_if_index, &addr,
898  mac_address, sizeof (mac_address),
899  is_static, is_no_fib_entry);
900  else
901  vnet_unset_ip6_ethernet_neighbor (vm, sw_if_index, &addr,
902  mac_address, sizeof (mac_address));
903  return 0;
904 }
905 
906 /*?
907  * This command is used to manually add an entry to the IPv6 neighbor
908  * adjacency table. Optionally, the entry can be added as static. It is
909  * also used to remove an entry from the table. Use the '<em>show ip6
910  * neighbors</em>' command to display all learned and manually entered entries.
911  *
912  * @cliexpar
913  * Example of how to add a static entry to the IPv6 neighbor adjacency table:
914  * @cliexcmd{set ip6 neighbor GigabitEthernet2/0/0 ::1:1:c:0:9 02:fe:e4:45:27:5b static}
915  * Example of how to delete an entry from the IPv6 neighbor adjacency table:
916  * @cliexcmd{set ip6 neighbor del GigabitEthernet2/0/0 ::1:1:c:0:9 02:fe:e4:45:27:5b}
917 ?*/
918 /* *INDENT-OFF* */
920 {
921  .path = "set ip6 neighbor",
922  .function = set_ip6_neighbor,
923  .short_help = "set ip6 neighbor [del] <interface> <ip6-address> <mac-address> [static]",
924 };
925 /* *INDENT-ON* */
926 
927 typedef enum
928 {
933 
936  vlib_node_runtime_t * node,
937  vlib_frame_t * frame,
938  uword is_solicitation)
939 {
940  vnet_main_t *vnm = vnet_get_main ();
941  ip6_main_t *im = &ip6_main;
942  uword n_packets = frame->n_vectors;
943  u32 *from, *to_next;
944  u32 n_left_from, n_left_to_next, next_index, n_advertisements_sent;
946  vlib_node_runtime_t *error_node =
948  int bogus_length;
949 
950  from = vlib_frame_vector_args (frame);
951  n_left_from = n_packets;
952  next_index = node->cached_next_index;
953 
954  if (node->flags & VLIB_NODE_FLAG_TRACE)
955  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
956  /* stride */ 1,
957  sizeof (icmp6_input_trace_t));
958 
959  option_type =
960  (is_solicitation
961  ? ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address
962  : ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address);
963  n_advertisements_sent = 0;
964 
965  while (n_left_from > 0)
966  {
967  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
968 
969  while (n_left_from > 0 && n_left_to_next > 0)
970  {
971  vlib_buffer_t *p0;
972  ip6_header_t *ip0;
973  icmp6_neighbor_solicitation_or_advertisement_header_t *h0;
974  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *o0;
975  u32 bi0, options_len0, sw_if_index0, next0, error0;
976  u32 ip6_sadd_link_local, ip6_sadd_unspecified;
977  int is_rewrite0;
978  u32 ni0;
979 
980  bi0 = to_next[0] = from[0];
981 
982  from += 1;
983  to_next += 1;
984  n_left_from -= 1;
985  n_left_to_next -= 1;
986 
987  p0 = vlib_get_buffer (vm, bi0);
988  ip0 = vlib_buffer_get_current (p0);
989  h0 = ip6_next_header (ip0);
990  options_len0 =
991  clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]);
992 
993  error0 = ICMP6_ERROR_NONE;
994  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
995  ip6_sadd_link_local =
997  ip6_sadd_unspecified =
999 
1000  /* Check that source address is unspecified, link-local or else on-link. */
1001  if (!ip6_sadd_unspecified && !ip6_sadd_link_local)
1002  {
1003  u32 src_adj_index0 = ip6_src_lookup_for_packet (im, p0, ip0);
1004 
1005  if (ADJ_INDEX_INVALID != src_adj_index0)
1006  {
1007  ip_adjacency_t *adj0 =
1008  ip_get_adjacency (&im->lookup_main, src_adj_index0);
1009 
1010  /* Allow all realistic-looking rewrite adjacencies to pass */
1011  ni0 = adj0->lookup_next_index;
1012  is_rewrite0 = (ni0 >= IP_LOOKUP_NEXT_ARP) &&
1013  (ni0 < IP6_LOOKUP_N_NEXT);
1014 
1015  error0 = ((adj0->rewrite_header.sw_if_index != sw_if_index0
1016  || !is_rewrite0)
1017  ?
1018  ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_NOT_ON_LINK
1019  : error0);
1020  }
1021  else
1022  {
1023  error0 =
1024  ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_NOT_ON_LINK;
1025  }
1026  }
1027 
1028  o0 = (void *) (h0 + 1);
1029  o0 = ((options_len0 == 8 && o0->header.type == option_type
1030  && o0->header.n_data_u64s == 1) ? o0 : 0);
1031 
1032  /* If src address unspecified or link local, donot learn neighbor MAC */
1033  if (PREDICT_TRUE (error0 == ICMP6_ERROR_NONE && o0 != 0 &&
1034  !ip6_sadd_unspecified && !ip6_sadd_link_local))
1035  {
1037  if (nm->limit_neighbor_cache_size &&
1038  pool_elts (nm->neighbor_pool) >=
1041  vnet_set_ip6_ethernet_neighbor (vm, sw_if_index0,
1042  is_solicitation ?
1043  &ip0->src_address :
1044  &h0->target_address,
1045  o0->ethernet_address,
1046  sizeof (o0->ethernet_address),
1047  0, 0);
1048  }
1049 
1050  if (is_solicitation && error0 == ICMP6_ERROR_NONE)
1051  {
1052  /* Check that target address is local to this router. */
1053  fib_node_index_t fei;
1054  u32 fib_index;
1055 
1056  fib_index =
1058 
1059  if (~0 == fib_index)
1060  {
1061  error0 = ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_UNKNOWN;
1062  }
1063  else
1064  {
1065  fei = ip6_fib_table_lookup_exact_match (fib_index,
1066  &h0->target_address,
1067  128);
1068 
1069  if (FIB_NODE_INDEX_INVALID == fei)
1070  {
1071  /* The target address is not in the FIB */
1072  error0 =
1073  ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_UNKNOWN;
1074  }
1075  else
1076  {
1077  if (FIB_ENTRY_FLAG_LOCAL &
1080  {
1081  /* It's an address that belongs to one of our interfaces
1082  * that's good. */
1083  }
1084  else
1086  (fei, FIB_SOURCE_IP6_ND_PROXY))
1087  {
1088  /* The address was added by IPv6 Proxy ND config.
1089  * We should only respond to these if the NS arrived on
1090  * the link that has a matching covering prefix */
1091  }
1092  else
1093  {
1094  error0 =
1095  ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_UNKNOWN;
1096  }
1097  }
1098  }
1099  }
1100 
1101  if (is_solicitation)
1102  next0 = (error0 != ICMP6_ERROR_NONE
1105  else
1106  {
1107  next0 = 0;
1108  error0 = error0 == ICMP6_ERROR_NONE ?
1109  ICMP6_ERROR_NEIGHBOR_ADVERTISEMENTS_RX : error0;
1110  }
1111 
1112  if (is_solicitation && error0 == ICMP6_ERROR_NONE)
1113  {
1114  vnet_sw_interface_t *sw_if0;
1115  ethernet_interface_t *eth_if0;
1116  ethernet_header_t *eth0;
1117 
1118  /* dst address is either source address or the all-nodes mcast addr */
1119  if (!ip6_sadd_unspecified)
1120  ip0->dst_address = ip0->src_address;
1121  else
1123  IP6_MULTICAST_SCOPE_link_local,
1124  IP6_MULTICAST_GROUP_ID_all_hosts);
1125 
1126  ip0->src_address = h0->target_address;
1127  ip0->hop_limit = 255;
1128  h0->icmp.type = ICMP6_neighbor_advertisement;
1129 
1130  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index0);
1132  eth_if0 =
1134  if (eth_if0 && o0)
1135  {
1136  clib_memcpy (o0->ethernet_address, eth_if0->address, 6);
1137  o0->header.type =
1138  ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address;
1139  }
1140 
1141  h0->advertisement_flags = clib_host_to_net_u32
1144 
1145  h0->icmp.checksum = 0;
1146  h0->icmp.checksum =
1147  ip6_tcp_udp_icmp_compute_checksum (vm, p0, ip0,
1148  &bogus_length);
1149  ASSERT (bogus_length == 0);
1150 
1151  /* Reuse current MAC header, copy SMAC to DMAC and
1152  * interface MAC to SMAC */
1154  eth0 = vlib_buffer_get_current (p0);
1155  clib_memcpy (eth0->dst_address, eth0->src_address, 6);
1156  if (eth_if0)
1157  clib_memcpy (eth0->src_address, eth_if0->address, 6);
1158 
1159  /* Setup input and output sw_if_index for packet */
1160  ASSERT (vnet_buffer (p0)->sw_if_index[VLIB_RX] == sw_if_index0);
1161  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1162  vnet_buffer (p0)->sw_if_index[VLIB_RX] =
1164 
1165  n_advertisements_sent++;
1166  }
1167 
1168  p0->error = error_node->errors[error0];
1169 
1170  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1171  to_next, n_left_to_next,
1172  bi0, next0);
1173  }
1174 
1175  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1176  }
1177 
1178  /* Account for advertisements sent. */
1179  vlib_error_count (vm, error_node->node_index,
1180  ICMP6_ERROR_NEIGHBOR_ADVERTISEMENTS_TX,
1181  n_advertisements_sent);
1182 
1183  return frame->n_vectors;
1184 }
1185 
1186 /* for "syslogging" - use elog for now */
1187 #define foreach_log_level \
1188  _ (DEBUG, "DEBUG") \
1189  _ (INFO, "INFORMATION") \
1190  _ (NOTICE, "NOTICE") \
1191  _ (WARNING, "WARNING") \
1192  _ (ERR, "ERROR") \
1193  _ (CRIT, "CRITICAL") \
1194  _ (ALERT, "ALERT") \
1195  _ (EMERG, "EMERGENCY")
1196 
1197 typedef enum
1198 {
1199 #define _(f,s) LOG_##f,
1201 #undef _
1202 } log_level_t;
1203 
1204 static char *log_level_strings[] = {
1205 #define _(f,s) s,
1207 #undef _
1208 };
1209 
1210 static int logmask = 1 << LOG_DEBUG;
1211 
1212 static void
1213 ip6_neighbor_syslog (vlib_main_t * vm, int priority, char *fmt, ...)
1214 {
1215  /* just use elog for now */
1216  u8 *what;
1217  va_list va;
1218 
1219  if ((priority > LOG_EMERG) || !(logmask & (1 << priority)))
1220  return;
1221 
1222  va_start (va, fmt);
1223  if (fmt)
1224  {
1225  what = va_format (0, fmt, &va);
1226 
1227  ELOG_TYPE_DECLARE (e) =
1228  {
1229  .format = "ip6 nd: (%s): %s",.format_args = "T4T4",};
1230  struct
1231  {
1232  u32 s[2];
1233  } *ed;
1234  ed = ELOG_DATA (&vm->elog_main, e);
1235  ed->s[0] = elog_string (&vm->elog_main, log_level_strings[priority]);
1236  ed->s[1] = elog_string (&vm->elog_main, (char *) what);
1237  }
1238  va_end (va);
1239  return;
1240 }
1241 
1242 /* ipv6 neighbor discovery - router advertisements */
1243 typedef enum
1244 {
1250 
1253  vlib_node_runtime_t * node, vlib_frame_t * frame)
1254 {
1255  vnet_main_t *vnm = vnet_get_main ();
1256  ip6_main_t *im = &ip6_main;
1258  uword n_packets = frame->n_vectors;
1259  u32 *from, *to_next;
1260  u32 n_left_from, n_left_to_next, next_index;
1261  u32 n_advertisements_sent = 0;
1262  int bogus_length;
1263 
1265 
1266  vlib_node_runtime_t *error_node =
1268 
1269  from = vlib_frame_vector_args (frame);
1270  n_left_from = n_packets;
1271  next_index = node->cached_next_index;
1272 
1273  if (node->flags & VLIB_NODE_FLAG_TRACE)
1274  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
1275  /* stride */ 1,
1276  sizeof (icmp6_input_trace_t));
1277 
1278  /* source may append his LL address */
1279  option_type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address;
1280 
1281  while (n_left_from > 0)
1282  {
1283  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1284 
1285  while (n_left_from > 0 && n_left_to_next > 0)
1286  {
1287  vlib_buffer_t *p0;
1288  ip6_header_t *ip0;
1289  ip6_radv_t *radv_info = 0;
1290 
1291  icmp6_neighbor_discovery_header_t *h0;
1292  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *o0;
1293 
1294  u32 bi0, options_len0, sw_if_index0, next0, error0;
1295  u32 is_solicitation = 1, is_dropped = 0;
1296  u32 is_unspecified, is_link_local;
1297 
1298  bi0 = to_next[0] = from[0];
1299 
1300  from += 1;
1301  to_next += 1;
1302  n_left_from -= 1;
1303  n_left_to_next -= 1;
1304 
1305  p0 = vlib_get_buffer (vm, bi0);
1306  ip0 = vlib_buffer_get_current (p0);
1307  h0 = ip6_next_header (ip0);
1308  options_len0 =
1309  clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]);
1310  is_unspecified = ip6_address_is_unspecified (&ip0->src_address);
1311  is_link_local =
1313 
1314  error0 = ICMP6_ERROR_NONE;
1315  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1316 
1317  /* check if solicitation (not from nd_timer node) */
1319  is_solicitation = 0;
1320 
1321  /* Check that source address is unspecified, link-local or else on-link. */
1322  if (!is_unspecified && !is_link_local)
1323  {
1324  u32 src_adj_index0 = ip6_src_lookup_for_packet (im, p0, ip0);
1325 
1326  if (ADJ_INDEX_INVALID != src_adj_index0)
1327  {
1329  src_adj_index0);
1330 
1331  error0 = (adj0->rewrite_header.sw_if_index != sw_if_index0
1332  ?
1333  ICMP6_ERROR_ROUTER_SOLICITATION_SOURCE_NOT_ON_LINK
1334  : error0);
1335  }
1336  else
1337  {
1338  error0 = ICMP6_ERROR_ROUTER_SOLICITATION_SOURCE_NOT_ON_LINK;
1339  }
1340  }
1341 
1342  /* check for source LL option and process */
1343  o0 = (void *) (h0 + 1);
1344  o0 = ((options_len0 == 8
1345  && o0->header.type == option_type
1346  && o0->header.n_data_u64s == 1) ? o0 : 0);
1347 
1348  /* if src address unspecified IGNORE any options */
1349  if (PREDICT_TRUE (error0 == ICMP6_ERROR_NONE && o0 != 0 &&
1350  !is_unspecified && !is_link_local))
1351  {
1353  if (nm->limit_neighbor_cache_size &&
1354  pool_elts (nm->neighbor_pool) >=
1357 
1358  vnet_set_ip6_ethernet_neighbor (vm, sw_if_index0,
1359  &ip0->src_address,
1360  o0->ethernet_address,
1361  sizeof (o0->ethernet_address),
1362  0, 0);
1363  }
1364 
1365  /* default is to drop */
1367 
1368  if (error0 == ICMP6_ERROR_NONE)
1369  {
1370  vnet_sw_interface_t *sw_if0;
1371  ethernet_interface_t *eth_if0;
1372  u32 adj_index0;
1373 
1374  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index0);
1376  eth_if0 =
1378 
1379  /* only support ethernet interface type for now */
1380  error0 =
1381  (!eth_if0) ? ICMP6_ERROR_ROUTER_SOLICITATION_UNSUPPORTED_INTF
1382  : error0;
1383 
1384  if (error0 == ICMP6_ERROR_NONE)
1385  {
1386  u32 ri;
1387 
1388  /* adjust the sizeof the buffer to just include the ipv6 header */
1389  p0->current_length -=
1390  (options_len0 +
1391  sizeof (icmp6_neighbor_discovery_header_t));
1392 
1393  /* look up the radv_t information for this interface */
1395  (nm->if_radv_pool_index_by_sw_if_index, sw_if_index0, ~0);
1396 
1397  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index0];
1398 
1399  if (ri != ~0)
1400  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
1401 
1402  error0 =
1403  ((!radv_info) ?
1404  ICMP6_ERROR_ROUTER_SOLICITATION_RADV_NOT_CONFIG :
1405  error0);
1406 
1407  if (error0 == ICMP6_ERROR_NONE)
1408  {
1409  f64 now = vlib_time_now (vm);
1410 
1411  /* for solicited adverts - need to rate limit */
1412  if (is_solicitation)
1413  {
1414  if (0 != radv_info->last_radv_time &&
1415  (now - radv_info->last_radv_time) <
1417  is_dropped = 1;
1418  else
1419  radv_info->last_radv_time = now;
1420  }
1421 
1422  /* send now */
1423  icmp6_router_advertisement_header_t rh;
1424 
1425  rh.icmp.type = ICMP6_router_advertisement;
1426  rh.icmp.code = 0;
1427  rh.icmp.checksum = 0;
1428 
1429  rh.current_hop_limit = radv_info->curr_hop_limit;
1430  rh.router_lifetime_in_sec =
1431  clib_host_to_net_u16
1432  (radv_info->adv_router_lifetime_in_sec);
1433  rh.
1434  time_in_msec_between_retransmitted_neighbor_solicitations
1435  =
1436  clib_host_to_net_u32 (radv_info->
1437  adv_time_in_msec_between_retransmitted_neighbor_solicitations);
1438  rh.neighbor_reachable_time_in_msec =
1439  clib_host_to_net_u32 (radv_info->
1440  adv_neighbor_reachable_time_in_msec);
1441 
1442  rh.flags =
1443  (radv_info->adv_managed_flag) ?
1445  0;
1446  rh.flags |=
1447  ((radv_info->adv_other_flag) ?
1449  0);
1450 
1451 
1452  u16 payload_length =
1453  sizeof (icmp6_router_advertisement_header_t);
1454 
1456  p0->free_list_index,
1457  bi0,
1458  (void *) &rh,
1459  sizeof
1460  (icmp6_router_advertisement_header_t));
1461 
1462  if (radv_info->adv_link_layer_address)
1463  {
1464  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t
1465  h;
1466 
1467  h.header.type =
1468  ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address;
1469  h.header.n_data_u64s = 1;
1470 
1471  /* copy ll address */
1472  clib_memcpy (&h.ethernet_address[0],
1473  eth_if0->address, 6);
1474 
1476  p0->free_list_index,
1477  bi0,
1478  (void *) &h,
1479  sizeof
1480  (icmp6_neighbor_discovery_ethernet_link_layer_address_option_t));
1481 
1482  payload_length +=
1483  sizeof
1484  (icmp6_neighbor_discovery_ethernet_link_layer_address_option_t);
1485  }
1486 
1487  /* add MTU option */
1488  if (radv_info->adv_link_mtu)
1489  {
1490  icmp6_neighbor_discovery_mtu_option_t h;
1491 
1492  h.unused = 0;
1493  h.mtu =
1494  clib_host_to_net_u32 (radv_info->adv_link_mtu);
1495  h.header.type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_mtu;
1496  h.header.n_data_u64s = 1;
1497 
1498  payload_length +=
1499  sizeof (icmp6_neighbor_discovery_mtu_option_t);
1500 
1502  p0->free_list_index,
1503  bi0,
1504  (void *) &h,
1505  sizeof
1506  (icmp6_neighbor_discovery_mtu_option_t));
1507  }
1508 
1509  /* add advertised prefix options */
1510  ip6_radv_prefix_t *pr_info;
1511 
1512  /* *INDENT-OFF* */
1513  pool_foreach (pr_info, radv_info->adv_prefixes_pool,
1514  ({
1515  if(pr_info->enabled &&
1516  (!pr_info->decrement_lifetime_flag
1517  || (pr_info->pref_lifetime_expires >0)))
1518  {
1519  /* advertise this prefix */
1520  icmp6_neighbor_discovery_prefix_information_option_t h;
1521 
1522  h.header.type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_prefix_information;
1523  h.header.n_data_u64s = (sizeof(icmp6_neighbor_discovery_prefix_information_option_t) >> 3);
1524 
1525  h.dst_address_length = pr_info->prefix_len;
1526 
1527  h.flags = (pr_info->adv_on_link_flag) ? ICMP6_NEIGHBOR_DISCOVERY_PREFIX_INFORMATION_FLAG_ON_LINK : 0;
1528  h.flags |= (pr_info->adv_autonomous_flag) ? ICMP6_NEIGHBOR_DISCOVERY_PREFIX_INFORMATION_AUTO : 0;
1529 
1530  if(radv_info->cease_radv && pr_info->deprecated_prefix_flag)
1531  {
1532  h.valid_time = clib_host_to_net_u32(MIN_ADV_VALID_LIFETIME);
1533  h.preferred_time = 0;
1534  }
1535  else
1536  {
1537  if(pr_info->decrement_lifetime_flag)
1538  {
1539  pr_info->adv_valid_lifetime_in_secs = ((pr_info->valid_lifetime_expires > now)) ?
1540  (pr_info->valid_lifetime_expires - now) : 0;
1541 
1542  pr_info->adv_pref_lifetime_in_secs = ((pr_info->pref_lifetime_expires > now)) ?
1543  (pr_info->pref_lifetime_expires - now) : 0;
1544  }
1545 
1546  h.valid_time = clib_host_to_net_u32(pr_info->adv_valid_lifetime_in_secs);
1547  h.preferred_time = clib_host_to_net_u32(pr_info->adv_pref_lifetime_in_secs) ;
1548  }
1549  h.unused = 0;
1550 
1551  clib_memcpy(&h.dst_address, &pr_info->prefix, sizeof(ip6_address_t));
1552 
1553  payload_length += sizeof( icmp6_neighbor_discovery_prefix_information_option_t);
1554 
1555  vlib_buffer_add_data (vm,
1556  p0->free_list_index,
1557  bi0,
1558  (void *)&h, sizeof(icmp6_neighbor_discovery_prefix_information_option_t));
1559 
1560  }
1561  }));
1562  /* *INDENT-ON* */
1563 
1564  /* add additional options before here */
1565 
1566  /* finish building the router advertisement... */
1567  if (!is_unspecified && radv_info->send_unicast)
1568  {
1569  ip0->dst_address = ip0->src_address;
1570  }
1571  else
1572  {
1573  /* target address is all-nodes mcast addr */
1575  (&ip0->dst_address,
1576  IP6_MULTICAST_SCOPE_link_local,
1577  IP6_MULTICAST_GROUP_ID_all_hosts);
1578  }
1579 
1580  /* source address MUST be the link-local address */
1581  ip0->src_address = radv_info->link_local_address;
1582 
1583  ip0->hop_limit = 255;
1584  ip0->payload_length =
1585  clib_host_to_net_u16 (payload_length);
1586 
1587  icmp6_router_advertisement_header_t *rh0 =
1588  (icmp6_router_advertisement_header_t *) (ip0 + 1);
1589  rh0->icmp.checksum =
1590  ip6_tcp_udp_icmp_compute_checksum (vm, p0, ip0,
1591  &bogus_length);
1592  ASSERT (bogus_length == 0);
1593 
1594  /* setup output if and adjacency */
1595  vnet_buffer (p0)->sw_if_index[VLIB_RX] =
1597 
1598  if (is_solicitation)
1599  {
1600  ethernet_header_t *eth0;
1601  /* Reuse current MAC header, copy SMAC to DMAC and
1602  * interface MAC to SMAC */
1603  vlib_buffer_reset (p0);
1604  eth0 = vlib_buffer_get_current (p0);
1605  clib_memcpy (eth0->dst_address, eth0->src_address,
1606  6);
1607  clib_memcpy (eth0->src_address, eth_if0->address,
1608  6);
1609  next0 =
1610  is_dropped ? next0 :
1612  vnet_buffer (p0)->sw_if_index[VLIB_TX] =
1613  sw_if_index0;
1614  }
1615  else
1616  {
1617  adj_index0 = radv_info->mcast_adj_index;
1618  if (adj_index0 == 0)
1619  error0 = ICMP6_ERROR_DST_LOOKUP_MISS;
1620  else
1621  {
1622  next0 =
1623  is_dropped ? next0 :
1625  vnet_buffer (p0)->ip.adj_index[VLIB_TX] =
1626  adj_index0;
1627  }
1628  }
1630 
1631  radv_info->n_solicitations_dropped += is_dropped;
1632  radv_info->n_solicitations_rcvd += is_solicitation;
1633 
1634  if ((error0 == ICMP6_ERROR_NONE) && !is_dropped)
1635  {
1636  radv_info->n_advertisements_sent++;
1637  n_advertisements_sent++;
1638  }
1639  }
1640  }
1641  }
1642 
1643  p0->error = error_node->errors[error0];
1644 
1645  if (error0 != ICMP6_ERROR_NONE)
1646  vlib_error_count (vm, error_node->node_index, error0, 1);
1647 
1648  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1649  to_next, n_left_to_next,
1650  bi0, next0);
1651 
1652  }
1653 
1654  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1655  }
1656 
1657  /* Account for router advertisements sent. */
1658  vlib_error_count (vm, error_node->node_index,
1659  ICMP6_ERROR_ROUTER_ADVERTISEMENTS_TX,
1660  n_advertisements_sent);
1661 
1662  return frame->n_vectors;
1663 }
1664 
1665  /* validate advertised info for consistancy (see RFC-4861 section 6.2.7) - log any inconsistencies, packet will always be dropped */
1668  vlib_node_runtime_t * node, vlib_frame_t * frame)
1669 {
1670  vnet_main_t *vnm = vnet_get_main ();
1672  uword n_packets = frame->n_vectors;
1673  u32 *from, *to_next;
1674  u32 n_left_from, n_left_to_next, next_index;
1675  u32 n_advertisements_rcvd = 0;
1676 
1677  vlib_node_runtime_t *error_node =
1679 
1680  from = vlib_frame_vector_args (frame);
1681  n_left_from = n_packets;
1682  next_index = node->cached_next_index;
1683 
1684  if (node->flags & VLIB_NODE_FLAG_TRACE)
1685  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
1686  /* stride */ 1,
1687  sizeof (icmp6_input_trace_t));
1688 
1689  while (n_left_from > 0)
1690  {
1691  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1692 
1693  while (n_left_from > 0 && n_left_to_next > 0)
1694  {
1695  vlib_buffer_t *p0;
1696  ip6_header_t *ip0;
1697  ip6_radv_t *radv_info = 0;
1698  icmp6_router_advertisement_header_t *h0;
1699  u32 bi0, options_len0, sw_if_index0, next0, error0;
1700 
1701  bi0 = to_next[0] = from[0];
1702 
1703  from += 1;
1704  to_next += 1;
1705  n_left_from -= 1;
1706  n_left_to_next -= 1;
1707 
1708  p0 = vlib_get_buffer (vm, bi0);
1709  ip0 = vlib_buffer_get_current (p0);
1710  h0 = ip6_next_header (ip0);
1711  options_len0 =
1712  clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]);
1713 
1714  error0 = ICMP6_ERROR_NONE;
1715  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1716 
1717  /* Check that source address is link-local */
1718  error0 = (!ip6_address_is_link_local_unicast (&ip0->src_address)) ?
1719  ICMP6_ERROR_ROUTER_ADVERTISEMENT_SOURCE_NOT_LINK_LOCAL : error0;
1720 
1721  /* default is to drop */
1723 
1724  n_advertisements_rcvd++;
1725 
1726  if (error0 == ICMP6_ERROR_NONE)
1727  {
1728  vnet_sw_interface_t *sw_if0;
1729  ethernet_interface_t *eth_if0;
1730 
1731  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index0);
1733  eth_if0 =
1735 
1736  /* only support ethernet interface type for now */
1737  error0 =
1738  (!eth_if0) ? ICMP6_ERROR_ROUTER_SOLICITATION_UNSUPPORTED_INTF
1739  : error0;
1740 
1741  if (error0 == ICMP6_ERROR_NONE)
1742  {
1743  u32 ri;
1744 
1745  /* look up the radv_t information for this interface */
1747  (nm->if_radv_pool_index_by_sw_if_index, sw_if_index0, ~0);
1748 
1749  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index0];
1750 
1751  if (ri != ~0)
1752  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
1753 
1754  error0 =
1755  ((!radv_info) ?
1756  ICMP6_ERROR_ROUTER_SOLICITATION_RADV_NOT_CONFIG :
1757  error0);
1758 
1759  if (error0 == ICMP6_ERROR_NONE)
1760  {
1761  /* validate advertised information */
1762  if ((h0->current_hop_limit && radv_info->curr_hop_limit)
1763  && (h0->current_hop_limit !=
1764  radv_info->curr_hop_limit))
1765  {
1766  ip6_neighbor_syslog (vm, LOG_WARNING,
1767  "our AdvCurHopLimit on %U doesn't agree with %U",
1769  vnm, sw_if_index0,
1771  &ip0->src_address);
1772  }
1773 
1774  if ((h0->flags &
1776  != radv_info->adv_managed_flag)
1777  {
1778  ip6_neighbor_syslog (vm, LOG_WARNING,
1779  "our AdvManagedFlag on %U doesn't agree with %U",
1781  vnm, sw_if_index0,
1783  &ip0->src_address);
1784  }
1785 
1786  if ((h0->flags &
1788  != radv_info->adv_other_flag)
1789  {
1790  ip6_neighbor_syslog (vm, LOG_WARNING,
1791  "our AdvOtherConfigFlag on %U doesn't agree with %U",
1793  vnm, sw_if_index0,
1795  &ip0->src_address);
1796  }
1797 
1798  if ((h0->
1799  time_in_msec_between_retransmitted_neighbor_solicitations
1800  && radv_info->
1801  adv_time_in_msec_between_retransmitted_neighbor_solicitations)
1802  && (h0->
1803  time_in_msec_between_retransmitted_neighbor_solicitations
1804  !=
1805  clib_host_to_net_u32 (radv_info->
1806  adv_time_in_msec_between_retransmitted_neighbor_solicitations)))
1807  {
1808  ip6_neighbor_syslog (vm, LOG_WARNING,
1809  "our AdvRetransTimer on %U doesn't agree with %U",
1811  vnm, sw_if_index0,
1813  &ip0->src_address);
1814  }
1815 
1816  if ((h0->neighbor_reachable_time_in_msec &&
1818  (h0->neighbor_reachable_time_in_msec !=
1819  clib_host_to_net_u32
1821  {
1822  ip6_neighbor_syslog (vm, LOG_WARNING,
1823  "our AdvReachableTime on %U doesn't agree with %U",
1825  vnm, sw_if_index0,
1827  &ip0->src_address);
1828  }
1829 
1830  /* check for MTU or prefix options or .. */
1831  u8 *opt_hdr = (u8 *) (h0 + 1);
1832  while (options_len0 > 0)
1833  {
1834  icmp6_neighbor_discovery_option_header_t *o0 =
1835  (icmp6_neighbor_discovery_option_header_t *)
1836  opt_hdr;
1837  int opt_len = o0->n_data_u64s << 3;
1839  o0->type;
1840 
1841  if (options_len0 < 2)
1842  {
1843  ip6_neighbor_syslog (vm, LOG_ERR,
1844  "malformed RA packet on %U from %U",
1846  vnm, sw_if_index0,
1848  &ip0->src_address);
1849  break;
1850  }
1851 
1852  if (opt_len == 0)
1853  {
1854  ip6_neighbor_syslog (vm, LOG_ERR,
1855  " zero length option in RA on %U from %U",
1857  vnm, sw_if_index0,
1859  &ip0->src_address);
1860  break;
1861  }
1862  else if (opt_len > options_len0)
1863  {
1864  ip6_neighbor_syslog (vm, LOG_ERR,
1865  "option length in RA packet greater than total length on %U from %U",
1867  vnm, sw_if_index0,
1869  &ip0->src_address);
1870  break;
1871  }
1872 
1873  options_len0 -= opt_len;
1874  opt_hdr += opt_len;
1875 
1876  switch (option_type)
1877  {
1878  case ICMP6_NEIGHBOR_DISCOVERY_OPTION_mtu:
1879  {
1880  icmp6_neighbor_discovery_mtu_option_t *h =
1881  (icmp6_neighbor_discovery_mtu_option_t
1882  *) (o0);
1883 
1884  if (opt_len < sizeof (*h))
1885  break;
1886 
1887  if ((h->mtu && radv_info->adv_link_mtu) &&
1888  (h->mtu !=
1889  clib_host_to_net_u32
1890  (radv_info->adv_link_mtu)))
1891  {
1892  ip6_neighbor_syslog (vm, LOG_WARNING,
1893  "our AdvLinkMTU on %U doesn't agree with %U",
1895  vnm, sw_if_index0,
1897  &ip0->src_address);
1898  }
1899  }
1900  break;
1901 
1902  case ICMP6_NEIGHBOR_DISCOVERY_OPTION_prefix_information:
1903  {
1904  icmp6_neighbor_discovery_prefix_information_option_t
1905  * h =
1906  (icmp6_neighbor_discovery_prefix_information_option_t
1907  *) (o0);
1908 
1909  /* validate advertised prefix options */
1910  ip6_radv_prefix_t *pr_info;
1911  u32 preferred, valid;
1912 
1913  if (opt_len < sizeof (*h))
1914  break;
1915 
1916  preferred =
1917  clib_net_to_host_u32 (h->preferred_time);
1918  valid = clib_net_to_host_u32 (h->valid_time);
1919 
1920  /* look for matching prefix - if we our advertising it, it better be consistant */
1921  /* *INDENT-OFF* */
1922  pool_foreach (pr_info, radv_info->adv_prefixes_pool,
1923  ({
1924 
1925  ip6_address_t mask;
1926  ip6_address_mask_from_width(&mask, pr_info->prefix_len);
1927 
1928  if(pr_info->enabled &&
1929  (pr_info->prefix_len == h->dst_address_length) &&
1930  ip6_address_is_equal_masked (&pr_info->prefix, &h->dst_address, &mask))
1931  {
1932  /* found it */
1933  if(!pr_info->decrement_lifetime_flag &&
1934  valid != pr_info->adv_valid_lifetime_in_secs)
1935  {
1936  ip6_neighbor_syslog(vm, LOG_WARNING,
1937  "our ADV validlifetime on %U for %U does not agree with %U",
1938  format_vnet_sw_if_index_name, vnm, sw_if_index0,format_ip6_address, &pr_info->prefix,
1939  format_ip6_address, &h->dst_address);
1940  }
1941  if(!pr_info->decrement_lifetime_flag &&
1942  preferred != pr_info->adv_pref_lifetime_in_secs)
1943  {
1944  ip6_neighbor_syslog(vm, LOG_WARNING,
1945  "our ADV preferredlifetime on %U for %U does not agree with %U",
1946  format_vnet_sw_if_index_name, vnm, sw_if_index0,format_ip6_address, &pr_info->prefix,
1947  format_ip6_address, &h->dst_address);
1948  }
1949  }
1950  break;
1951  }));
1952  /* *INDENT-ON* */
1953  break;
1954  }
1955  default:
1956  /* skip this one */
1957  break;
1958  }
1959  }
1960  }
1961  }
1962  }
1963 
1964  p0->error = error_node->errors[error0];
1965 
1966  if (error0 != ICMP6_ERROR_NONE)
1967  vlib_error_count (vm, error_node->node_index, error0, 1);
1968 
1969  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1970  to_next, n_left_to_next,
1971  bi0, next0);
1972  }
1973 
1974  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1975  }
1976 
1977  /* Account for router advertisements sent. */
1978  vlib_error_count (vm, error_node->node_index,
1979  ICMP6_ERROR_ROUTER_ADVERTISEMENTS_RX,
1980  n_advertisements_rcvd);
1981 
1982  return frame->n_vectors;
1983 }
1984 
1985 /**
1986  * @brief Add a multicast Address to the advertised MLD set
1987  */
1988 static void
1990 {
1991  ip6_mldp_group_t *mcast_group_info;
1992  uword *p;
1993 
1994  /* lookup mldp info for this interface */
1995  p = mhash_get (&radv_info->address_to_mldp_index, &addr);
1996  mcast_group_info =
1997  p ? pool_elt_at_index (radv_info->mldp_group_pool, p[0]) : 0;
1998 
1999  /* add address */
2000  if (!mcast_group_info)
2001  {
2002  /* add */
2003  u32 mi;
2004  pool_get (radv_info->mldp_group_pool, mcast_group_info);
2005 
2006  mi = mcast_group_info - radv_info->mldp_group_pool;
2007  mhash_set (&radv_info->address_to_mldp_index, &addr, mi, /* old_value */
2008  0);
2009 
2010  mcast_group_info->type = 4;
2011  mcast_group_info->mcast_source_address_pool = 0;
2012  mcast_group_info->num_sources = 0;
2013  clib_memcpy (&mcast_group_info->mcast_address, &addr,
2014  sizeof (ip6_address_t));
2015  }
2016 }
2017 
2018 /**
2019  * @brief Delete a multicast Address from the advertised MLD set
2020  */
2021 static void
2023 {
2024  ip6_mldp_group_t *mcast_group_info;
2025  uword *p;
2026 
2027  p = mhash_get (&radv_info->address_to_mldp_index, &addr);
2028  mcast_group_info =
2029  p ? pool_elt_at_index (radv_info->mldp_group_pool, p[0]) : 0;
2030 
2031  if (mcast_group_info)
2032  {
2033  mhash_unset (&radv_info->address_to_mldp_index, &addr,
2034  /* old_value */ 0);
2035  pool_put (radv_info->mldp_group_pool, mcast_group_info);
2036  }
2037 }
2038 
2039 /**
2040  * @brief Add a multicast Address to the advertised MLD set
2041  */
2042 static void
2046 {
2048 
2049  ip6_set_reserved_multicast_address (&addr, scope, group);
2050 
2051  ip6_neighbor_add_mld_prefix (a, &addr);
2052 }
2053 
2054 /**
2055  * @brief create and initialize router advertisement parameters with default
2056  * values for this intfc
2057  */
2058 static u32
2060  u32 sw_if_index, u32 is_add)
2061 {
2063  ip6_radv_t *a = 0;
2064  u32 ri = ~0;
2065  vnet_sw_interface_t *sw_if0;
2066  ethernet_interface_t *eth_if0 = 0;
2067 
2068  /* lookup radv container - ethernet interfaces only */
2069  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index);
2070  if (sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
2071  eth_if0 = ethernet_get_interface (&ethernet_main, sw_if0->hw_if_index);
2072 
2073  if (!eth_if0)
2074  return ri;
2075 
2077  ~0);
2078  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
2079 
2080  if (ri != ~0)
2081  {
2082  a = pool_elt_at_index (nm->if_radv_pool, ri);
2083 
2084  if (!is_add)
2085  {
2086  ip6_radv_prefix_t *p;
2087  ip6_mldp_group_t *m;
2088 
2089  /* release the lock on the interface's mcast adj */
2091 
2092  /* clean up prefix and MDP pools */
2093  /* *INDENT-OFF* */
2095  ({
2096  mhash_unset (&a->address_to_prefix_index, &p->prefix, 0);
2097  }));
2098  pool_flush (m, a->mldp_group_pool,
2099  ({
2100  mhash_unset (&a->address_to_mldp_index, &m->mcast_address, 0);
2101  }));
2102  /* *INDENT-ON* */
2103 
2106 
2109 
2110  pool_put (nm->if_radv_pool, a);
2111  nm->if_radv_pool_index_by_sw_if_index[sw_if_index] = ~0;
2112  ri = ~0;
2113  }
2114  }
2115  else
2116  {
2117  if (is_add)
2118  {
2119  vnet_hw_interface_t *hw_if0;
2120 
2121  hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index);
2122 
2123  pool_get (nm->if_radv_pool, a);
2124 
2125  ri = a - nm->if_radv_pool;
2126  nm->if_radv_pool_index_by_sw_if_index[sw_if_index] = ri;
2127 
2128  /* initialize default values (most of which are zero) */
2129  memset (a, 0, sizeof (a[0]));
2130 
2131  a->sw_if_index = sw_if_index;
2136 
2137  /* send ll address source address option */
2138  a->adv_link_layer_address = 1;
2139 
2143  a->seed = (u32) clib_cpu_time_now ();
2144  (void) random_u32 (&a->seed);
2145  a->randomizer = clib_cpu_time_now ();
2146  (void) random_u64 (&a->randomizer);
2147 
2151 
2152  /* deafult is to send */
2153  a->send_radv = 1;
2154 
2155  /* fill in radv_info for this interface that will be needed later */
2157 
2158  clib_memcpy (a->link_layer_address, eth_if0->address, 6);
2159 
2160  /* fill in default link-local address (this may be overridden) */
2162  (&a->link_local_address, eth_if0->address);
2163 
2164  mhash_init (&a->address_to_prefix_index, sizeof (uword),
2165  sizeof (ip6_address_t));
2166  mhash_init (&a->address_to_mldp_index, sizeof (uword),
2167  sizeof (ip6_address_t));
2168 
2170  VNET_LINK_IP6,
2171  sw_if_index);
2172 
2173  /* add multicast groups we will always be reporting */
2175  IP6_MULTICAST_SCOPE_link_local,
2176  IP6_MULTICAST_GROUP_ID_all_hosts);
2178  IP6_MULTICAST_SCOPE_link_local,
2179  IP6_MULTICAST_GROUP_ID_all_routers);
2181  IP6_MULTICAST_SCOPE_link_local,
2182  IP6_MULTICAST_GROUP_ID_mldv2_routers);
2183  }
2184  }
2185  return ri;
2186 }
2187 
2188 /* send an mldpv2 report */
2189 static void
2191 {
2192  vnet_main_t *vnm = vnet_get_main ();
2193  vlib_main_t *vm = vnm->vlib_main;
2195  vnet_sw_interface_t *sw_if0;
2196  ethernet_interface_t *eth_if0;
2197  u32 ri;
2198  int bogus_length;
2199 
2200  ip6_radv_t *radv_info;
2201  u16 payload_length;
2202  vlib_buffer_t *b0;
2203  ip6_header_t *ip0;
2204  u32 *to_next;
2205  vlib_frame_t *f;
2206  u32 bo0;
2207  u32 n_to_alloc = 1;
2208  u32 n_allocated;
2209 
2210  icmp6_multicast_listener_report_header_t *rh0;
2211  icmp6_multicast_listener_report_packet_t *rp0;
2212 
2213  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index);
2215  eth_if0 = ethernet_get_interface (&ethernet_main, sw_if0->hw_if_index);
2216 
2217  if (!eth_if0 || !vnet_sw_interface_is_admin_up (vnm, sw_if_index))
2218  return;
2219 
2220  /* look up the radv_t information for this interface */
2222  ~0);
2223 
2224  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
2225 
2226  if (ri == ~0)
2227  return;
2228 
2229  /* send report now - build a mldpv2 report packet */
2230  n_allocated = vlib_buffer_alloc_from_free_list (vm,
2231  &bo0,
2232  n_to_alloc,
2234  if (PREDICT_FALSE (n_allocated == 0))
2235  {
2236  clib_warning ("buffer allocation failure");
2237  return;
2238  }
2239 
2240  b0 = vlib_get_buffer (vm, bo0);
2241 
2242  /* adjust the sizeof the buffer to just include the ipv6 header */
2243  b0->current_length = sizeof (icmp6_multicast_listener_report_packet_t);
2244 
2245  payload_length = sizeof (icmp6_multicast_listener_report_header_t);
2246 
2247  b0->error = ICMP6_ERROR_NONE;
2248 
2249  rp0 = vlib_buffer_get_current (b0);
2250  ip0 = (ip6_header_t *) & rp0->ip;
2251  rh0 = (icmp6_multicast_listener_report_header_t *) & rp0->report_hdr;
2252 
2253  memset (rp0, 0x0, sizeof (icmp6_multicast_listener_report_packet_t));
2254 
2256  clib_host_to_net_u32 (0x6 << 28);
2257 
2258  ip0->protocol = IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS;
2259  /* for DEBUG - vnet driver won't seem to emit router alerts */
2260  /* ip0->protocol = IP_PROTOCOL_ICMP6; */
2261  ip0->hop_limit = 1;
2262 
2263  rh0->icmp.type = ICMP6_multicast_listener_report_v2;
2264 
2265  /* source address MUST be the link-local address */
2266  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
2267  ip0->src_address = radv_info->link_local_address;
2268 
2269  /* destination is all mldpv2 routers */
2271  IP6_MULTICAST_SCOPE_link_local,
2272  IP6_MULTICAST_GROUP_ID_mldv2_routers);
2273 
2274  /* add reports here */
2275  ip6_mldp_group_t *m;
2276  int num_addr_records = 0;
2277  icmp6_multicast_address_record_t rr;
2278 
2279  /* fill in the hop-by-hop extension header (router alert) info */
2280  rh0->ext_hdr.next_hdr = IP_PROTOCOL_ICMP6;
2281  rh0->ext_hdr.n_data_u64s = 0;
2282 
2283  rh0->alert.type = IP6_MLDP_ALERT_TYPE;
2284  rh0->alert.len = 2;
2285  rh0->alert.value = 0;
2286 
2287  rh0->pad.type = 1;
2288  rh0->pad.len = 0;
2289 
2290  rh0->icmp.checksum = 0;
2291 
2292  /* *INDENT-OFF* */
2293  pool_foreach (m, radv_info->mldp_group_pool,
2294  ({
2295  rr.type = m->type;
2296  rr.aux_data_len_u32s = 0;
2297  rr.num_sources = clib_host_to_net_u16 (m->num_sources);
2298  clib_memcpy(&rr.mcast_addr, &m->mcast_address, sizeof(ip6_address_t));
2299 
2300  num_addr_records++;
2301 
2302  vlib_buffer_add_data
2303  (vm, b0->free_list_index, bo0,
2304  (void *)&rr, sizeof(icmp6_multicast_address_record_t));
2305 
2306  payload_length += sizeof( icmp6_multicast_address_record_t);
2307  }));
2308  /* *INDENT-ON* */
2309 
2310  rh0->rsvd = 0;
2311  rh0->num_addr_records = clib_host_to_net_u16 (num_addr_records);
2312 
2313  /* update lengths */
2314  ip0->payload_length = clib_host_to_net_u16 (payload_length);
2315 
2316  rh0->icmp.checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0,
2317  &bogus_length);
2318  ASSERT (bogus_length == 0);
2319 
2320  /*
2321  * OK to override w/ no regard for actual FIB, because
2322  * ip6-rewrite only looks at the adjacency.
2323  */
2324  vnet_buffer (b0)->sw_if_index[VLIB_RX] =
2326 
2327  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = radv_info->mcast_adj_index;
2329 
2330  vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "ip6-rewrite-mcast");
2331 
2332  f = vlib_get_frame_to_node (vm, node->index);
2333  to_next = vlib_frame_vector_args (f);
2334  to_next[0] = bo0;
2335  f->n_vectors = 1;
2336 
2337  vlib_put_frame_to_node (vm, node->index, f);
2338  return;
2339 }
2340 
2341 /* *INDENT-OFF* */
2343 {
2344  .function = icmp6_router_solicitation,
2345  .name = "icmp6-router-solicitation",
2346 
2347  .vector_size = sizeof (u32),
2348 
2349  .format_trace = format_icmp6_input_trace,
2350 
2351  .n_next_nodes = ICMP6_ROUTER_SOLICITATION_N_NEXT,
2352  .next_nodes = {
2353  [ICMP6_ROUTER_SOLICITATION_NEXT_DROP] = "error-drop",
2354  [ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_RW] = "ip6-rewrite-mcast",
2355  [ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_TX] = "interface-output",
2356  },
2357 };
2358 /* *INDENT-ON* */
2359 
2360 /* send a RA or update the timer info etc.. */
2361 static uword
2363  vlib_node_runtime_t * node,
2364  vlib_frame_t * frame)
2365 {
2366  vnet_main_t *vnm = vnet_get_main ();
2368  ip6_radv_t *radv_info;
2369  vlib_frame_t *f = 0;
2370  u32 n_this_frame = 0;
2371  u32 n_left_to_next = 0;
2372  u32 *to_next = 0;
2373  u32 bo0;
2374  icmp6_router_solicitation_header_t *h0;
2375  vlib_buffer_t *b0;
2376  f64 now = vlib_time_now (vm);
2377 
2378  /* Interface ip6 radv info list */
2379  /* *INDENT-OFF* */
2380  pool_foreach (radv_info, nm->if_radv_pool,
2381  ({
2382  if( !vnet_sw_interface_is_admin_up (vnm, radv_info->sw_if_index))
2383  {
2384  radv_info->initial_adverts_sent = radv_info->initial_adverts_count-1;
2385  radv_info->next_multicast_time = now;
2386  radv_info->last_multicast_time = now;
2387  radv_info->last_radv_time = 0;
2388  radv_info->all_routers_mcast = 0;
2389  continue;
2390  }
2391 
2392  /* Make sure that we've joined the all-routers multicast group */
2393  if(!radv_info->all_routers_mcast)
2394  {
2395  /* send MDLP_REPORT_EVENT message */
2396  ip6_neighbor_send_mldpv2_report(radv_info->sw_if_index);
2397  radv_info->all_routers_mcast = 1;
2398  }
2399 
2400  /* is it time to send a multicast RA on this interface? */
2401  if(radv_info->send_radv && (now >= radv_info->next_multicast_time))
2402  {
2403  u32 n_to_alloc = 1;
2404  u32 n_allocated;
2405 
2406  f64 rfn = (radv_info->max_radv_interval - radv_info->min_radv_interval) *
2407  random_f64 (&radv_info->seed) + radv_info->min_radv_interval;
2408 
2409  /* multicast send - compute next multicast send time */
2410  if( radv_info->initial_adverts_sent > 0)
2411  {
2412  radv_info->initial_adverts_sent--;
2413  if(rfn > radv_info-> initial_adverts_interval)
2414  rfn = radv_info-> initial_adverts_interval;
2415 
2416  /* check to see if we are ceasing to send */
2417  if( radv_info->initial_adverts_sent == 0)
2418  if(radv_info->cease_radv)
2419  radv_info->send_radv = 0;
2420  }
2421 
2422  radv_info->next_multicast_time = rfn + now;
2423  radv_info->last_multicast_time = now;
2424 
2425  /* send advert now - build a "solicted" router advert with unspecified source address */
2426  n_allocated = vlib_buffer_alloc_from_free_list
2427  (vm, &bo0, n_to_alloc, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
2428 
2429  if (PREDICT_FALSE(n_allocated == 0))
2430  {
2431  clib_warning ("buffer allocation failure");
2432  continue;
2433  }
2434  b0 = vlib_get_buffer (vm, bo0);
2435  b0->current_length = sizeof( icmp6_router_solicitation_header_t);
2436  b0->error = ICMP6_ERROR_NONE;
2437  vnet_buffer (b0)->sw_if_index[VLIB_RX] = radv_info->sw_if_index;
2438 
2439  h0 = vlib_buffer_get_current (b0);
2440 
2441  memset (h0, 0, sizeof (icmp6_router_solicitation_header_t));
2442 
2443  h0->ip.ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0x6 << 28);
2444  h0->ip.payload_length = clib_host_to_net_u16 (sizeof (icmp6_router_solicitation_header_t)
2445  - STRUCT_OFFSET_OF (icmp6_router_solicitation_header_t, neighbor));
2446  h0->ip.protocol = IP_PROTOCOL_ICMP6;
2447  h0->ip.hop_limit = 255;
2448 
2449  /* set src/dst address as "unspecified" this marks this packet as internally generated rather than recieved */
2450  h0->ip.src_address.as_u64[0] = 0;
2451  h0->ip.src_address.as_u64[1] = 0;
2452 
2453  h0->ip.dst_address.as_u64[0] = 0;
2454  h0->ip.dst_address.as_u64[1] = 0;
2455 
2456  h0->neighbor.icmp.type = ICMP6_router_solicitation;
2457 
2458  if (PREDICT_FALSE(f == 0))
2459  {
2461  to_next = vlib_frame_vector_args (f);
2462  n_left_to_next = VLIB_FRAME_SIZE;
2463  n_this_frame = 0;
2464  }
2465 
2466  n_this_frame++;
2467  n_left_to_next--;
2468  to_next[0] = bo0;
2469  to_next += 1;
2470 
2471  if (PREDICT_FALSE(n_left_to_next == 0))
2472  {
2473  f->n_vectors = n_this_frame;
2475  f = 0;
2476  }
2477  }
2478  }));
2479  /* *INDENT-ON* */
2480 
2481  if (f)
2482  {
2483  ASSERT (n_this_frame);
2484  f->n_vectors = n_this_frame;
2486  }
2487  return 0;
2488 }
2489 
2490 static uword
2492  vlib_node_runtime_t * node,
2493  vlib_frame_t * frame)
2494 {
2495  uword event_type;
2497 
2498  /* init code here */
2499 
2500  while (1)
2501  {
2502  vlib_process_wait_for_event_or_clock (vm, 1. /* seconds */ );
2503 
2504  event_data = vlib_process_get_event_data (vm, &event_type);
2505 
2506  if (!event_data)
2507  {
2508  /* No events found: timer expired. */
2509  /* process interface list and send RAs as appropriate, update timer info */
2510  ip6_neighbor_process_timer_event (vm, node, frame);
2511  }
2512  else
2513  {
2514  switch (event_type)
2515  {
2516 
2517  case ICMP6_ND_EVENT_INIT:
2518  break;
2519 
2520  case ~0:
2521  break;
2522 
2523  default:
2524  ASSERT (0);
2525  }
2526 
2527  if (event_data)
2528  _vec_len (event_data) = 0;
2529  }
2530  }
2531  return frame->n_vectors;
2532 }
2533 
2534 /* *INDENT-OFF* */
2536 {
2537  .function = icmp6_router_advertisement,
2538  .name = "icmp6-router-advertisement",
2539 
2540  .vector_size = sizeof (u32),
2541 
2542  .format_trace = format_icmp6_input_trace,
2543 
2544  .n_next_nodes = 1,
2545  .next_nodes = {
2546  [0] = "error-drop",
2547  },
2548 };
2549 /* *INDENT-ON* */
2550 
2552 
2554  .name = "ip6-icmp-neighbor-discovery-event-process",
2555  .type = VLIB_NODE_TYPE_PROCESS,
2556 };
2557 
2558 static uword
2560  vlib_node_runtime_t * node, vlib_frame_t * frame)
2561 {
2562  return icmp6_neighbor_solicitation_or_advertisement (vm, node, frame,
2563  /* is_solicitation */
2564  1);
2565 }
2566 
2567 static uword
2569  vlib_node_runtime_t * node,
2570  vlib_frame_t * frame)
2571 {
2572  return icmp6_neighbor_solicitation_or_advertisement (vm, node, frame,
2573  /* is_solicitation */
2574  0);
2575 }
2576 
2577 /* *INDENT-OFF* */
2579 {
2580  .function = icmp6_neighbor_solicitation,
2581  .name = "icmp6-neighbor-solicitation",
2582 
2583  .vector_size = sizeof (u32),
2584 
2585  .format_trace = format_icmp6_input_trace,
2586 
2587  .n_next_nodes = ICMP6_NEIGHBOR_SOLICITATION_N_NEXT,
2588  .next_nodes = {
2589  [ICMP6_NEIGHBOR_SOLICITATION_NEXT_DROP] = "error-drop",
2590  [ICMP6_NEIGHBOR_SOLICITATION_NEXT_REPLY] = "interface-output",
2591  },
2592 };
2593 /* *INDENT-ON* */
2594 
2595 /* *INDENT-OFF* */
2597 {
2598  .function = icmp6_neighbor_advertisement,
2599  .name = "icmp6-neighbor-advertisement",
2600 
2601  .vector_size = sizeof (u32),
2602 
2603  .format_trace = format_icmp6_input_trace,
2604 
2605  .n_next_nodes = 1,
2606  .next_nodes = {
2607  [0] = "error-drop",
2608  },
2609 };
2610 /* *INDENT-ON* */
2611 
2612 /* API support functions */
2613 int
2615  u8 suppress, u8 managed, u8 other,
2616  u8 ll_option, u8 send_unicast, u8 cease,
2617  u8 use_lifetime, u32 lifetime,
2618  u32 initial_count, u32 initial_interval,
2619  u32 max_interval, u32 min_interval, u8 is_no)
2620 {
2622  int error;
2623  u32 ri;
2624 
2625  /* look up the radv_t information for this interface */
2627  ~0);
2628  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
2629  error = (ri != ~0) ? 0 : VNET_API_ERROR_INVALID_SW_IF_INDEX;
2630 
2631  if (!error)
2632  {
2633 
2634  ip6_radv_t *radv_info;
2635  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
2636 
2637  if ((max_interval != 0) && (min_interval == 0))
2638  min_interval = .75 * max_interval;
2639 
2640  max_interval =
2641  (max_interval !=
2642  0) ? ((is_no) ? DEF_MAX_RADV_INTERVAL : max_interval) :
2643  radv_info->max_radv_interval;
2644  min_interval =
2645  (min_interval !=
2646  0) ? ((is_no) ? DEF_MIN_RADV_INTERVAL : min_interval) :
2647  radv_info->min_radv_interval;
2648  lifetime =
2649  (use_lifetime !=
2650  0) ? ((is_no) ? DEF_DEF_RTR_LIFETIME : lifetime) :
2651  radv_info->adv_router_lifetime_in_sec;
2652 
2653  if (lifetime)
2654  {
2655  if (lifetime > MAX_DEF_RTR_LIFETIME)
2656  lifetime = MAX_DEF_RTR_LIFETIME;
2657 
2658  if (lifetime <= max_interval)
2659  return VNET_API_ERROR_INVALID_VALUE;
2660  }
2661 
2662  if (min_interval != 0)
2663  {
2664  if ((min_interval > .75 * max_interval) || (min_interval < 3))
2665  return VNET_API_ERROR_INVALID_VALUE;
2666  }
2667 
2668  if ((initial_count > MAX_INITIAL_RTR_ADVERTISEMENTS) ||
2669  (initial_interval > MAX_INITIAL_RTR_ADVERT_INTERVAL))
2670  return VNET_API_ERROR_INVALID_VALUE;
2671 
2672  /*
2673  if "flag" is set and is_no is true then restore default value else set value corresponding to "flag"
2674  if "flag" is clear don't change corresponding value
2675  */
2676  radv_info->send_radv =
2677  (suppress != 0) ? ((is_no != 0) ? 1 : 0) : radv_info->send_radv;
2678  radv_info->adv_managed_flag =
2679  (managed != 0) ? ((is_no) ? 0 : 1) : radv_info->adv_managed_flag;
2680  radv_info->adv_other_flag =
2681  (other != 0) ? ((is_no) ? 0 : 1) : radv_info->adv_other_flag;
2682  radv_info->adv_link_layer_address =
2683  (ll_option !=
2684  0) ? ((is_no) ? 1 : 0) : radv_info->adv_link_layer_address;
2685  radv_info->send_unicast =
2686  (send_unicast != 0) ? ((is_no) ? 0 : 1) : radv_info->send_unicast;
2687  radv_info->cease_radv =
2688  (cease != 0) ? ((is_no) ? 0 : 1) : radv_info->cease_radv;
2689 
2690  radv_info->min_radv_interval = min_interval;
2691  radv_info->max_radv_interval = max_interval;
2692  radv_info->adv_router_lifetime_in_sec = lifetime;
2693 
2694  radv_info->initial_adverts_count =
2695  (initial_count !=
2696  0) ? ((is_no) ? MAX_INITIAL_RTR_ADVERTISEMENTS : initial_count) :
2697  radv_info->initial_adverts_count;
2698  radv_info->initial_adverts_interval =
2699  (initial_interval !=
2700  0) ? ((is_no) ? MAX_INITIAL_RTR_ADVERT_INTERVAL : initial_interval) :
2701  radv_info->initial_adverts_interval;
2702 
2703  /* restart */
2704  if ((cease != 0) && (is_no))
2705  radv_info->send_radv = 1;
2706 
2707  radv_info->initial_adverts_sent = radv_info->initial_adverts_count - 1;
2708  radv_info->next_multicast_time = vlib_time_now (vm);
2709  radv_info->last_multicast_time = vlib_time_now (vm);
2710  radv_info->last_radv_time = 0;
2711  }
2712  return (error);
2713 }
2714 
2715 int
2717  ip6_address_t * prefix_addr, u8 prefix_len,
2718  u8 use_default, u32 val_lifetime, u32 pref_lifetime,
2719  u8 no_advertise, u8 off_link, u8 no_autoconfig,
2720  u8 no_onlink, u8 is_no)
2721 {
2723  int error;
2724 
2725  u32 ri;
2726 
2727  /* look up the radv_t information for this interface */
2729  ~0);
2730 
2731  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
2732 
2733  error = (ri != ~0) ? 0 : VNET_API_ERROR_INVALID_SW_IF_INDEX;
2734 
2735  if (!error)
2736  {
2737  f64 now = vlib_time_now (vm);
2738  ip6_radv_t *radv_info;
2739  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
2740 
2741  /* prefix info add, delete or update */
2742  ip6_radv_prefix_t *prefix;
2743 
2744  /* lookup prefix info for this address on this interface */
2745  uword *p = mhash_get (&radv_info->address_to_prefix_index, prefix_addr);
2746 
2747  prefix = p ? pool_elt_at_index (radv_info->adv_prefixes_pool, p[0]) : 0;
2748 
2749  if (is_no)
2750  {
2751  /* delete */
2752  if (!prefix)
2753  return VNET_API_ERROR_INVALID_VALUE; /* invalid prefix */
2754 
2755  if (prefix->prefix_len != prefix_len)
2756  return VNET_API_ERROR_INVALID_VALUE_2;
2757 
2758  /* FIXME - Should the DP do this or the CP ? */
2759  /* do specific delete processing here before returning */
2760  /* try to remove from routing table */
2761 
2762  mhash_unset (&radv_info->address_to_prefix_index, prefix_addr,
2763  /* old_value */ 0);
2764  pool_put (radv_info->adv_prefixes_pool, prefix);
2765 
2766  radv_info->initial_adverts_sent =
2767  radv_info->initial_adverts_count - 1;
2768  radv_info->next_multicast_time = vlib_time_now (vm);
2769  radv_info->last_multicast_time = vlib_time_now (vm);
2770  radv_info->last_radv_time = 0;
2771  return (error);
2772  }
2773 
2774  /* adding or changing */
2775  if (!prefix)
2776  {
2777  /* add */
2778  u32 pi;
2779  pool_get (radv_info->adv_prefixes_pool, prefix);
2780  pi = prefix - radv_info->adv_prefixes_pool;
2781  mhash_set (&radv_info->address_to_prefix_index, prefix_addr, pi,
2782  /* old_value */ 0);
2783 
2784  memset (prefix, 0x0, sizeof (ip6_radv_prefix_t));
2785 
2786  prefix->prefix_len = prefix_len;
2787  clib_memcpy (&prefix->prefix, prefix_addr, sizeof (ip6_address_t));
2788 
2789  /* initialize default values */
2790  prefix->adv_on_link_flag = 1; /* L bit set */
2791  prefix->adv_autonomous_flag = 1; /* A bit set */
2794  prefix->enabled = 1;
2795  prefix->decrement_lifetime_flag = 1;
2796  prefix->deprecated_prefix_flag = 1;
2797 
2798  if (off_link == 0)
2799  {
2800  /* FIXME - Should the DP do this or the CP ? */
2801  /* insert prefix into routing table as a connected prefix */
2802  }
2803 
2804  if (use_default)
2805  goto restart;
2806  }
2807  else
2808  {
2809 
2810  if (prefix->prefix_len != prefix_len)
2811  return VNET_API_ERROR_INVALID_VALUE_2;
2812 
2813  if (off_link != 0)
2814  {
2815  /* FIXME - Should the DP do this or the CP ? */
2816  /* remove from routing table if already there */
2817  }
2818  }
2819 
2820  if ((val_lifetime == ~0) || (pref_lifetime == ~0))
2821  {
2822  prefix->adv_valid_lifetime_in_secs = ~0;
2823  prefix->adv_pref_lifetime_in_secs = ~0;
2824  prefix->decrement_lifetime_flag = 0;
2825  }
2826  else
2827  {
2828  prefix->adv_valid_lifetime_in_secs = val_lifetime;;
2829  prefix->adv_pref_lifetime_in_secs = pref_lifetime;
2830  }
2831 
2832  /* copy remaining */
2833  prefix->enabled = !(no_advertise != 0);
2834  prefix->adv_on_link_flag = !((off_link != 0) || (no_onlink != 0));
2835  prefix->adv_autonomous_flag = !(no_autoconfig != 0);
2836 
2837  restart:
2838  /* restart */
2839  /* fill in the expiration times */
2840  prefix->valid_lifetime_expires =
2841  now + prefix->adv_valid_lifetime_in_secs;
2842  prefix->pref_lifetime_expires = now + prefix->adv_pref_lifetime_in_secs;
2843 
2844  radv_info->initial_adverts_sent = radv_info->initial_adverts_count - 1;
2845  radv_info->next_multicast_time = vlib_time_now (vm);
2846  radv_info->last_multicast_time = vlib_time_now (vm);
2847  radv_info->last_radv_time = 0;
2848  }
2849  return (error);
2850 }
2851 
2852 clib_error_t *
2854  vlib_cli_command_t * cmd)
2855 {
2856  vnet_main_t *vnm = vnet_get_main ();
2858  clib_error_t *error = 0;
2859  u8 is_no = 0;
2860  u8 suppress = 0, managed = 0, other = 0;
2861  u8 suppress_ll_option = 0, send_unicast = 0, cease = 0;
2862  u8 use_lifetime = 0;
2863  u32 sw_if_index, ra_lifetime = 0, ra_initial_count =
2864  0, ra_initial_interval = 0;
2865  u32 ra_max_interval = 0, ra_min_interval = 0;
2866 
2867  unformat_input_t _line_input, *line_input = &_line_input;
2868  vnet_sw_interface_t *sw_if0;
2869 
2870  int add_radv_info = 1;
2871  __attribute__ ((unused)) ip6_radv_t *radv_info = 0;
2872  ip6_address_t ip6_addr;
2873  u32 addr_len;
2874 
2875 
2876  /* Get a line of input. */
2877  if (!unformat_user (main_input, unformat_line_input, line_input))
2878  return 0;
2879 
2880  /* get basic radv info for this interface */
2881  if (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2882  {
2883 
2884  if (unformat_user (line_input,
2885  unformat_vnet_sw_interface, vnm, &sw_if_index))
2886  {
2887  u32 ri;
2888  ethernet_interface_t *eth_if0 = 0;
2889 
2890  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index);
2891  if (sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
2892  eth_if0 =
2894 
2895  if (!eth_if0)
2896  {
2897  error =
2898  clib_error_return (0, "Interface must be of ethernet type");
2899  goto done;
2900  }
2901 
2902  /* look up the radv_t information for this interface */
2904  sw_if_index, ~0);
2905 
2906  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
2907 
2908  if (ri != ~0)
2909  {
2910  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
2911  }
2912  else
2913  {
2914  error = clib_error_return (0, "unknown interface %U'",
2915  format_unformat_error, line_input);
2916  goto done;
2917  }
2918  }
2919  else
2920  {
2921  error = clib_error_return (0, "invalid interface name %U'",
2922  format_unformat_error, line_input);
2923  goto done;
2924  }
2925  }
2926 
2927  /* get the rest of the command */
2928  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2929  {
2930  if (unformat (line_input, "no"))
2931  is_no = 1;
2932  else if (unformat (line_input, "prefix %U/%d",
2933  unformat_ip6_address, &ip6_addr, &addr_len))
2934  {
2935  add_radv_info = 0;
2936  break;
2937  }
2938  else if (unformat (line_input, "ra-managed-config-flag"))
2939  {
2940  managed = 1;
2941  break;
2942  }
2943  else if (unformat (line_input, "ra-other-config-flag"))
2944  {
2945  other = 1;
2946  break;
2947  }
2948  else if (unformat (line_input, "ra-suppress") ||
2949  unformat (line_input, "ra-surpress"))
2950  {
2951  suppress = 1;
2952  break;
2953  }
2954  else if (unformat (line_input, "ra-suppress-link-layer") ||
2955  unformat (line_input, "ra-surpress-link-layer"))
2956  {
2957  suppress_ll_option = 1;
2958  break;
2959  }
2960  else if (unformat (line_input, "ra-send-unicast"))
2961  {
2962  send_unicast = 1;
2963  break;
2964  }
2965  else if (unformat (line_input, "ra-lifetime"))
2966  {
2967  if (!unformat (line_input, "%d", &ra_lifetime))
2968  {
2969  error = unformat_parse_error (line_input);
2970  goto done;
2971  }
2972  use_lifetime = 1;
2973  break;
2974  }
2975  else if (unformat (line_input, "ra-initial"))
2976  {
2977  if (!unformat
2978  (line_input, "%d %d", &ra_initial_count, &ra_initial_interval))
2979  {
2980  error = unformat_parse_error (line_input);
2981  goto done;
2982  }
2983  break;
2984  }
2985  else if (unformat (line_input, "ra-interval"))
2986  {
2987  if (!unformat (line_input, "%d", &ra_max_interval))
2988  {
2989  error = unformat_parse_error (line_input);
2990  goto done;
2991  }
2992 
2993  if (!unformat (line_input, "%d", &ra_min_interval))
2994  ra_min_interval = 0;
2995  break;
2996  }
2997  else if (unformat (line_input, "ra-cease"))
2998  {
2999  cease = 1;
3000  break;
3001  }
3002  else
3003  {
3004  error = unformat_parse_error (line_input);
3005  goto done;
3006  }
3007  }
3008 
3009  if (add_radv_info)
3010  {
3011  ip6_neighbor_ra_config (vm, sw_if_index,
3012  suppress, managed, other,
3013  suppress_ll_option, send_unicast, cease,
3014  use_lifetime, ra_lifetime,
3015  ra_initial_count, ra_initial_interval,
3016  ra_max_interval, ra_min_interval, is_no);
3017  }
3018  else
3019  {
3020  u32 valid_lifetime_in_secs = 0;
3021  u32 pref_lifetime_in_secs = 0;
3022  u8 use_prefix_default_values = 0;
3023  u8 no_advertise = 0;
3024  u8 off_link = 0;
3025  u8 no_autoconfig = 0;
3026  u8 no_onlink = 0;
3027 
3028  /* get the rest of the command */
3029  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3030  {
3031  if (unformat (line_input, "default"))
3032  {
3033  use_prefix_default_values = 1;
3034  break;
3035  }
3036  else if (unformat (line_input, "infinite"))
3037  {
3038  valid_lifetime_in_secs = ~0;
3039  pref_lifetime_in_secs = ~0;
3040  break;
3041  }
3042  else if (unformat (line_input, "%d %d", &valid_lifetime_in_secs,
3043  &pref_lifetime_in_secs))
3044  break;
3045  else
3046  break;
3047  }
3048 
3049 
3050  /* get the rest of the command */
3051  while (!use_prefix_default_values &&
3053  {
3054  if (unformat (line_input, "no-advertise"))
3055  no_advertise = 1;
3056  else if (unformat (line_input, "off-link"))
3057  off_link = 1;
3058  else if (unformat (line_input, "no-autoconfig"))
3059  no_autoconfig = 1;
3060  else if (unformat (line_input, "no-onlink"))
3061  no_onlink = 1;
3062  else
3063  {
3064  error = unformat_parse_error (line_input);
3065  goto done;
3066  }
3067  }
3068 
3069  ip6_neighbor_ra_prefix (vm, sw_if_index,
3070  &ip6_addr, addr_len,
3071  use_prefix_default_values,
3072  valid_lifetime_in_secs,
3073  pref_lifetime_in_secs,
3074  no_advertise,
3075  off_link, no_autoconfig, no_onlink, is_no);
3076  }
3077 
3078 done:
3079  unformat_free (line_input);
3080 
3081  return error;
3082 }
3083 
3084 static void
3086 {
3088  u32 i;
3089 
3090  for (i = 0; i < vec_len (addrs); i++)
3091  {
3093  pool_elt_at_index (lm->if_address_pool, addrs[i]);
3095 
3096  vlib_cli_output (vm, "\t\t%U/%d",
3097  format_ip6_address, address, a->address_length);
3098  }
3099 }
3100 
3101 static clib_error_t *
3103  unformat_input_t * input, vlib_cli_command_t * cmd)
3104 {
3105  vnet_main_t *vnm = vnet_get_main ();
3107  clib_error_t *error = 0;
3108  u32 sw_if_index;
3109 
3110  sw_if_index = ~0;
3111 
3112  if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
3113  {
3114  u32 ri;
3115 
3116  /* look up the radv_t information for this interface */
3118  sw_if_index, ~0);
3119 
3120  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
3121 
3122  if (ri != ~0)
3123  {
3125  ip6_radv_t *radv_info;
3126  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
3127 
3128  vlib_cli_output (vm, "%U is admin %s\n",
3130  vnet_get_sw_interface (vnm, sw_if_index),
3131  (vnet_sw_interface_is_admin_up (vnm, sw_if_index) ?
3132  "up" : "down"));
3133 
3134  u32 ai;
3135  u32 *link_scope = 0, *global_scope = 0;
3136  u32 *local_scope = 0, *unknown_scope = 0;
3138 
3140  sw_if_index, ~0);
3141  ai = lm->if_address_pool_index_by_sw_if_index[sw_if_index];
3142 
3143  while (ai != (u32) ~ 0)
3144  {
3145  a = pool_elt_at_index (lm->if_address_pool, ai);
3146  ip6_address_t *address =
3148 
3149  if (ip6_address_is_link_local_unicast (address))
3150  vec_add1 (link_scope, ai);
3151  else if (ip6_address_is_global_unicast (address))
3152  vec_add1 (global_scope, ai);
3153  else if (ip6_address_is_local_unicast (address))
3154  vec_add1 (local_scope, ai);
3155  else
3156  vec_add1 (unknown_scope, ai);
3157 
3158  ai = a->next_this_sw_interface;
3159  }
3160 
3161  if (vec_len (link_scope))
3162  {
3163  vlib_cli_output (vm, "\tLink-local address(es):\n");
3164  ip6_print_addrs (vm, link_scope);
3165  vec_free (link_scope);
3166  }
3167 
3168  if (vec_len (local_scope))
3169  {
3170  vlib_cli_output (vm, "\tLocal unicast address(es):\n");
3171  ip6_print_addrs (vm, local_scope);
3172  vec_free (local_scope);
3173  }
3174 
3175  if (vec_len (global_scope))
3176  {
3177  vlib_cli_output (vm, "\tGlobal unicast address(es):\n");
3178  ip6_print_addrs (vm, global_scope);
3179  vec_free (global_scope);
3180  }
3181 
3182  if (vec_len (unknown_scope))
3183  {
3184  vlib_cli_output (vm, "\tOther-scope address(es):\n");
3185  ip6_print_addrs (vm, unknown_scope);
3186  vec_free (unknown_scope);
3187  }
3188 
3189  vlib_cli_output (vm, "\tJoined group address(es):\n");
3190  ip6_mldp_group_t *m;
3191  /* *INDENT-OFF* */
3192  pool_foreach (m, radv_info->mldp_group_pool,
3193  ({
3194  vlib_cli_output (vm, "\t\t%U\n", format_ip6_address,
3195  &m->mcast_address);
3196  }));
3197  /* *INDENT-ON* */
3198 
3199  vlib_cli_output (vm, "\tAdvertised Prefixes:\n");
3200  ip6_radv_prefix_t *p;
3201  /* *INDENT-OFF* */
3202  pool_foreach (p, radv_info->adv_prefixes_pool,
3203  ({
3204  vlib_cli_output (vm, "\t\tprefix %U, length %d\n",
3205  format_ip6_address, &p->prefix, p->prefix_len);
3206  }));
3207  /* *INDENT-ON* */
3208 
3209  vlib_cli_output (vm, "\tMTU is %d\n", radv_info->adv_link_mtu);
3210  vlib_cli_output (vm, "\tICMP error messages are unlimited\n");
3211  vlib_cli_output (vm, "\tICMP redirects are disabled\n");
3212  vlib_cli_output (vm, "\tICMP unreachables are not sent\n");
3213  vlib_cli_output (vm, "\tND DAD is disabled\n");
3214  //vlib_cli_output (vm, "\tND reachable time is %d milliseconds\n",);
3215  vlib_cli_output (vm, "\tND advertised reachable time is %d\n",
3217  vlib_cli_output (vm,
3218  "\tND advertised retransmit interval is %d (msec)\n",
3219  radv_info->
3220  adv_time_in_msec_between_retransmitted_neighbor_solicitations);
3221 
3222  u32 ra_interval = radv_info->max_radv_interval;
3223  u32 ra_interval_min = radv_info->min_radv_interval;
3224  vlib_cli_output (vm,
3225  "\tND router advertisements are sent every %d seconds (min interval is %d)\n",
3226  ra_interval, ra_interval_min);
3227  vlib_cli_output (vm,
3228  "\tND router advertisements live for %d seconds\n",
3229  radv_info->adv_router_lifetime_in_sec);
3230  vlib_cli_output (vm,
3231  "\tHosts %s stateless autoconfig for addresses\n",
3232  (radv_info->adv_managed_flag) ? "use" :
3233  " don't use");
3234  vlib_cli_output (vm, "\tND router advertisements sent %d\n",
3235  radv_info->n_advertisements_sent);
3236  vlib_cli_output (vm, "\tND router solicitations received %d\n",
3237  radv_info->n_solicitations_rcvd);
3238  vlib_cli_output (vm, "\tND router solicitations dropped %d\n",
3239  radv_info->n_solicitations_dropped);
3240  }
3241  else
3242  {
3243  error = clib_error_return (0, "IPv6 not enabled on interface",
3244  format_unformat_error, input);
3245 
3246  }
3247  }
3248  return error;
3249 }
3250 
3251 /*?
3252  * This command is used to display various IPv6 attributes on a given
3253  * interface.
3254  *
3255  * @cliexpar
3256  * Example of how to display IPv6 settings:
3257  * @cliexstart{show ip6 interface GigabitEthernet2/0/0}
3258  * GigabitEthernet2/0/0 is admin up
3259  * Link-local address(es):
3260  * fe80::ab8/64
3261  * Joined group address(es):
3262  * ff02::1
3263  * ff02::2
3264  * ff02::16
3265  * ff02::1:ff00:ab8
3266  * Advertised Prefixes:
3267  * prefix fe80::fe:28ff:fe9c:75b3, length 64
3268  * MTU is 1500
3269  * ICMP error messages are unlimited
3270  * ICMP redirects are disabled
3271  * ICMP unreachables are not sent
3272  * ND DAD is disabled
3273  * ND advertised reachable time is 0
3274  * ND advertised retransmit interval is 0 (msec)
3275  * ND router advertisements are sent every 200 seconds (min interval is 150)
3276  * ND router advertisements live for 600 seconds
3277  * Hosts use stateless autoconfig for addresses
3278  * ND router advertisements sent 19336
3279  * ND router solicitations received 0
3280  * ND router solicitations dropped 0
3281  * @cliexend
3282  * Example of output if IPv6 is not enabled on the interface:
3283  * @cliexstart{show ip6 interface GigabitEthernet2/0/0}
3284  * show ip6 interface: IPv6 not enabled on interface
3285  * @cliexend
3286 ?*/
3287 /* *INDENT-OFF* */
3288 VLIB_CLI_COMMAND (show_ip6_interface_command, static) =
3289 {
3290  .path = "show ip6 interface",
3291  .function = show_ip6_interface_cmd,
3292  .short_help = "show ip6 interface <interface>",
3293 };
3294 /* *INDENT-ON* */
3295 
3296 clib_error_t *
3298 {
3299  clib_error_t *error = 0;
3301  u32 ri;
3302 
3303  /* look up the radv_t information for this interface */
3305  ~0);
3306  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
3307 
3308  /* if not created - do nothing */
3309  if (ri != ~0)
3310  {
3311  vnet_main_t *vnm = vnet_get_main ();
3312  ip6_radv_t *radv_info;
3313 
3314  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
3315 
3316  /* check radv_info ref count for other ip6 addresses on this interface */
3317  /* This implicitly excludes the link local address */
3318  if (radv_info->ref_count == 0)
3319  {
3320  /* essentially "disables" ipv6 on this interface */
3321  error = ip6_add_del_interface_address (vm, sw_if_index,
3322  &radv_info->
3323  link_local_address, 128,
3324  1 /* is_del */ );
3325 
3326  ip6_neighbor_sw_interface_add_del (vnm, sw_if_index,
3327  0 /* is_add */ );
3328  ip6_mfib_interface_enable_disable (sw_if_index, 0);
3329  }
3330  }
3331  return error;
3332 }
3333 
3334 int
3336 {
3338  u32 ri = ~0;
3339 
3340  /* look up the radv_t information for this interface */
3342  ~0);
3343 
3344  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
3345 
3346  return ri != ~0;
3347 }
3348 
3349 clib_error_t *
3351 {
3352  clib_error_t *error = 0;
3354  u32 ri;
3355  int is_add = 1;
3356 
3357  /* look up the radv_t information for this interface */
3359  ~0);
3360 
3361  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
3362 
3363  /* if not created yet */
3364  if (ri == ~0)
3365  {
3366  vnet_main_t *vnm = vnet_get_main ();
3367  vnet_sw_interface_t *sw_if0;
3368 
3369  sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index);
3370  if (sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
3371  {
3372  ethernet_interface_t *eth_if0;
3373 
3374  eth_if0 =
3376  if (eth_if0)
3377  {
3378  /* create radv_info. for this interface. This holds all the info needed for router adverts */
3379  ri =
3380  ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, is_add);
3381 
3382  if (ri != ~0)
3383  {
3384  ip6_radv_t *radv_info;
3385  ip6_address_t link_local_address;
3386 
3387  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
3388 
3390  (&link_local_address, eth_if0->address);
3391 
3392  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index);
3393  if (sw_if0->type == VNET_SW_INTERFACE_TYPE_SUB)
3394  {
3395  /* make up an interface id */
3396  md5_context_t m;
3397  u8 digest[16];
3398 
3399  link_local_address.as_u64[0] = radv_info->randomizer;
3400 
3401  md5_init (&m);
3402  md5_add (&m, &link_local_address, 16);
3403  md5_finish (&m, digest);
3404 
3405  clib_memcpy (&link_local_address, digest, 16);
3406 
3407  radv_info->randomizer = link_local_address.as_u64[0];
3408 
3409  link_local_address.as_u64[0] =
3410  clib_host_to_net_u64 (0xFE80000000000000ULL);
3411  /* clear u bit */
3412  link_local_address.as_u8[8] &= 0xfd;
3413  }
3414 
3415  ip6_mfib_interface_enable_disable (sw_if_index, 1);
3416 
3417  /* essentially "enables" ipv6 on this interface */
3418  error = ip6_add_del_interface_address (vm, sw_if_index,
3419  &link_local_address,
3420  128
3421  /* address width */ ,
3422  0 /* is_del */ );
3423 
3424  if (error)
3425  ip6_neighbor_sw_interface_add_del (vnm, sw_if_index,
3426  !is_add);
3427  else
3428  {
3429  radv_info->link_local_address = link_local_address;
3430  }
3431  }
3432  }
3433  }
3434  }
3435  return error;
3436 }
3437 
3438 static clib_error_t *
3440  unformat_input_t * input, vlib_cli_command_t * cmd)
3441 {
3442  vnet_main_t *vnm = vnet_get_main ();
3443  clib_error_t *error = 0;
3444  u32 sw_if_index;
3445 
3446  sw_if_index = ~0;
3447 
3448  if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
3449  {
3450  enable_ip6_interface (vm, sw_if_index);
3451  }
3452  else
3453  {
3454  error = clib_error_return (0, "unknown interface\n'",
3455  format_unformat_error, input);
3456 
3457  }
3458  return error;
3459 }
3460 
3461 /*?
3462  * This command is used to enable IPv6 on a given interface.
3463  *
3464  * @cliexpar
3465  * Example of how enable IPv6 on a given interface:
3466  * @cliexcmd{enable ip6 interface GigabitEthernet2/0/0}
3467 ?*/
3468 /* *INDENT-OFF* */
3469 VLIB_CLI_COMMAND (enable_ip6_interface_command, static) =
3470 {
3471  .path = "enable ip6 interface",
3472  .function = enable_ip6_interface_cmd,
3473  .short_help = "enable ip6 interface <interface>",
3474 };
3475 /* *INDENT-ON* */
3476 
3477 static clib_error_t *
3479  unformat_input_t * input, vlib_cli_command_t * cmd)
3480 {
3481  vnet_main_t *vnm = vnet_get_main ();
3482  clib_error_t *error = 0;
3483  u32 sw_if_index;
3484 
3485  sw_if_index = ~0;
3486 
3487  if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
3488  {
3489  error = disable_ip6_interface (vm, sw_if_index);
3490  }
3491  else
3492  {
3493  error = clib_error_return (0, "unknown interface\n'",
3494  format_unformat_error, input);
3495 
3496  }
3497  return error;
3498 }
3499 
3500 /*?
3501  * This command is used to disable IPv6 on a given interface.
3502  *
3503  * @cliexpar
3504  * Example of how disable IPv6 on a given interface:
3505  * @cliexcmd{disable ip6 interface GigabitEthernet2/0/0}
3506 ?*/
3507 /* *INDENT-OFF* */
3508 VLIB_CLI_COMMAND (disable_ip6_interface_command, static) =
3509 {
3510  .path = "disable ip6 interface",
3511  .function = disable_ip6_interface_cmd,
3512  .short_help = "disable ip6 interface <interface>",
3513 };
3514 /* *INDENT-ON* */
3515 
3516 /*?
3517  * This command is used to configure the neighbor discovery
3518  * parameters on a given interface. Use the '<em>show ip6 interface</em>'
3519  * command to display some of the current neighbor discovery parameters
3520  * on a given interface. This command has three formats:
3521  *
3522  *
3523  * <b>Format 1 - Router Advertisement Options:</b> (Only one can be entered in a single command)
3524  *
3525  * '<em><b>ip6 nd <interface> [no] [ra-managed-config-flag] | [ra-other-config-flag] | [ra-suppress] | [ra-suppress-link-layer] | [ra-send-unicast] | [ra-lifetime <lifetime>] | [ra-initial <cnt> <interval>] | [ra-interval <max-interval> [<min-interval>]] | [ra-cease]</b></em>'
3526  *
3527  * Where:
3528  *
3529  * <em>[no] ra-managed-config-flag</em> - Advertises in ICMPv6
3530  * router-advertisement messages to use stateful address
3531  * auto-configuration to obtain address information (sets the M-bit).
3532  * Default is the M-bit is not set and the '<em>no</em>' option
3533  * returns it to this default state.
3534  *
3535  * <em>[no] ra-other-config-flag</em> - Indicates in ICMPv6
3536  * router-advertisement messages that hosts use stateful auto
3537  * configuration to obtain nonaddress related information (sets
3538  * the O-bit). Default is the O-bit is not set and the '<em>no</em>'
3539  * option returns it to this default state.
3540  *
3541  * <em>[no] ra-suppress</em> - Disables sending ICMPv6 router-advertisement
3542  * messages. The '<em>no</em>' option implies to enable sending ICMPv6
3543  * router-advertisement messages.
3544  *
3545  * <em>[no] ra-suppress-link-layer</em> - Indicates not to include the
3546  * optional source link-layer address in the ICMPv6 router-advertisement
3547  * messages. Default is to include the optional source link-layer address
3548  * and the '<em>no</em>' option returns it to this default state.
3549  *
3550  * <em>[no] ra-send-unicast</em> - Use the source address of the
3551  * router-solicitation message if availiable. The default is to use
3552  * multicast address of all nodes, and the '<em>no</em>' option returns
3553  * it to this default state.
3554  *
3555  * <em>[no] ra-lifetime <lifetime></em> - Advertises the lifetime of a
3556  * default router in ICMPv6 router-advertisement messages. The range is
3557  * from 0 to 9000 seconds. '<em><lifetime></em>' must be greater than
3558  * '<em><max-interval></em>'. The default value is 600 seconds and the
3559  * '<em>no</em>' option returns it to this default value.
3560  *
3561  * <em>[no] ra-initial <cnt> <interval></em> - Number of initial ICMPv6
3562  * router-advertisement messages sent and the interval between each
3563  * message. Range for count is 1 - 3 and default is 3. Range for interval
3564  * is 1 to 16 seconds, and default is 16 seconds. The '<em>no</em>' option
3565  * returns both to their default value.
3566  *
3567  * <em>[no] ra-interval <max-interval> [<min-interval>]</em> - Configures the
3568  * interval between sending ICMPv6 router-advertisement messages. The
3569  * range for max-interval is from 4 to 200 seconds. min-interval can not
3570  * be more than 75% of max-interval. If not set, min-interval will be
3571  * set to 75% of max-interval. The range for min-interval is from 3 to
3572  * 150 seconds. The '<em>no</em>' option returns both to their default
3573  * value.
3574  *
3575  * <em>[no] ra-cease</em> - Cease sending ICMPv6 router-advertisement messages.
3576  * The '<em>no</em>' options implies to start (or restart) sending
3577  * ICMPv6 router-advertisement messages.
3578  *
3579  *
3580  * <b>Format 2 - Prefix Options:</b>
3581  *
3582  * '<em><b>ip6 nd <interface> [no] prefix <ip6-address>/<width> [<valid-lifetime> <pref-lifetime> | infinite] [no-advertise] [off-link] [no-autoconfig] [no-onlink]</b></em>'
3583  *
3584  * Where:
3585  *
3586  * <em>no</em> - All additional flags are ignored and the prefix is deleted.
3587  *
3588  * <em><valid-lifetime> <pref-lifetime></em> - '<em><valid-lifetime></em>' is the
3589  * length of time in seconds during what the prefix is valid for the purpose of
3590  * on-link determination. Range is 7203 to 2592000 seconds and default is 2592000
3591  * seconds (30 days). '<em><pref-lifetime></em>' is the prefered-lifetime and is the
3592  * length of time in seconds during what addresses generated from the prefix remain
3593  * preferred. Range is 0 to 604800 seconds and default is 604800 seconds (7 days).
3594  *
3595  * <em>infinite</em> - Both '<em><valid-lifetime></em>' and '<em><<pref-lifetime></em>'
3596  * are inifinte, no timeout.
3597  *
3598  * <em>no-advertise</em> - Do not send full router address in prefix
3599  * advertisement. Default is to advertise (i.e. - This flag is off by default).
3600  *
3601  * <em>off-link</em> - Prefix is off-link, clear L-bit in packet. Default is on-link
3602  * (i.e. - This flag is off and L-bit in packet is set by default and this prefix can
3603  * be used for on-link determination). '<em>no-onlink</em>' also controls the L-bit.
3604  *
3605  * <em>no-autoconfig</em> - Do not use prefix for autoconfiguration, clear A-bit in packet.
3606  * Default is autoconfig (i.e. - This flag is off and A-bit in packet is set by default.
3607  *
3608  * <em>no-onlink</em> - Do not use prefix for onlink determination, clear L-bit in packet.
3609  * Default is on-link (i.e. - This flag is off and L-bit in packet is set by default and
3610  * this prefix can be used for on-link determination). '<em>off-link</em>' also controls
3611  * the L-bit.
3612  *
3613  *
3614  * <b>Format 3: - Default of Prefix:</b>
3615  *
3616  * '<em><b>ip6 nd <interface> [no] prefix <ip6-address>/<width> default</b></em>'
3617  *
3618  * When a new prefix is added (or existing one is being overwritten) <em>default</em>
3619  * uses default values for the prefix. If <em>no</em> is used, the <em>default</em>
3620  * is ignored and the prefix is deleted.
3621  *
3622  *
3623  * @cliexpar
3624  * Example of how set a router advertisement option:
3625  * @cliexcmd{ip6 nd GigabitEthernet2/0/0 ra-interval 100 20}
3626  * Example of how to add a prefix:
3627  * @cliexcmd{ip6 nd GigabitEthernet2/0/0 prefix fe80::fe:28ff:fe9c:75b3/64 infinite no-advertise}
3628  * Example of how to delete a prefix:
3629  * @cliexcmd{ip6 nd GigabitEthernet2/0/0 no prefix fe80::fe:28ff:fe9c:75b3/64}
3630 ?*/
3631 /* *INDENT-OFF* */
3632 VLIB_CLI_COMMAND (ip6_nd_command, static) =
3633 {
3634  .path = "ip6 nd",
3635  .short_help = "ip6 nd <interface> ...",
3636  .function = ip6_neighbor_cmd,
3637 };
3638 /* *INDENT-ON* */
3639 
3640 clib_error_t *
3642  u32 sw_if_index, ip6_address_t * address)
3643 {
3644  clib_error_t *error = 0;
3646  u32 ri;
3647  ip6_radv_t *radv_info;
3648  vnet_main_t *vnm = vnet_get_main ();
3649 
3650  if (!ip6_address_is_link_local_unicast (address))
3651  {
3652  vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_LINK_LOCAL;
3653  return (error = clib_error_return (0, "address not link-local",
3655  }
3656 
3657  /* call enable ipv6 */
3658  enable_ip6_interface (vm, sw_if_index);
3659 
3660  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
3661 
3662  if (ri != ~0)
3663  {
3664  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
3665 
3666  /* save if link local address (overwrite default) */
3667 
3668  /* delete the old one */
3669  error = ip6_add_del_interface_address (vm, sw_if_index,
3670  &radv_info->link_local_address,
3671  128, 1 /* is_del */ );
3672 
3673  if (!error)
3674  {
3675  /* add the new one */
3676  error = ip6_add_del_interface_address (vm, sw_if_index,
3677  address, 128,
3678  0 /* is_del */ );
3679 
3680  if (!error)
3681  {
3682  radv_info->link_local_address = *address;
3683  }
3684  }
3685  }
3686  else
3687  {
3688  vnm->api_errno = VNET_API_ERROR_IP6_NOT_ENABLED;
3689  error = clib_error_return (0, "ip6 not enabled for interface",
3691  }
3692  return error;
3693 }
3694 
3695 clib_error_t *
3697  unformat_input_t * input,
3698  vlib_cli_command_t * cmd)
3699 {
3700  vnet_main_t *vnm = vnet_get_main ();
3701  clib_error_t *error = 0;
3702  u32 sw_if_index;
3703  ip6_address_t ip6_addr;
3704 
3705  if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
3706  {
3707  /* get the rest of the command */
3708  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3709  {
3710  if (unformat (input, "%U", unformat_ip6_address, &ip6_addr))
3711  break;
3712  else
3713  return (unformat_parse_error (input));
3714  }
3715  }
3716  error = set_ip6_link_local_address (vm, sw_if_index, &ip6_addr);
3717  return error;
3718 }
3719 
3720 /*?
3721  * This command is used to assign an IPv6 Link-local address to an
3722  * interface. This command will enable IPv6 on an interface if it
3723  * is not already enabled. Use the '<em>show ip6 interface</em>' command
3724  * to display the assigned Link-local address.
3725  *
3726  * @cliexpar
3727  * Example of how to assign an IPv6 Link-local address to an interface:
3728  * @cliexcmd{set ip6 link-local address GigabitEthernet2/0/0 FE80::AB8}
3729 ?*/
3730 /* *INDENT-OFF* */
3731 VLIB_CLI_COMMAND (set_ip6_link_local_address_command, static) =
3732 {
3733  .path = "set ip6 link-local address",
3734  .short_help = "set ip6 link-local address <interface> <ip6-address>",
3735  .function = set_ip6_link_local_address_cmd,
3736 };
3737 /* *INDENT-ON* */
3738 
3739 /**
3740  * @brief callback when an interface address is added or deleted
3741  */
3742 static void
3744  uword opaque,
3745  u32 sw_if_index,
3746  ip6_address_t * address,
3747  u32 address_length,
3748  u32 if_address_index, u32 is_delete)
3749 {
3750  vnet_main_t *vnm = vnet_get_main ();
3752  u32 ri;
3753  vlib_main_t *vm = vnm->vlib_main;
3754  ip6_radv_t *radv_info;
3755  ip6_address_t a;
3756 
3757  /* create solicited node multicast address for this interface adddress */
3759 
3760  a.as_u8[0xd] = address->as_u8[0xd];
3761  a.as_u8[0xe] = address->as_u8[0xe];
3762  a.as_u8[0xf] = address->as_u8[0xf];
3763 
3764  if (!is_delete)
3765  {
3766  /* try to create radv_info - does nothing if ipv6 already enabled */
3767  enable_ip6_interface (vm, sw_if_index);
3768 
3769  /* look up the radv_t information for this interface */
3771  sw_if_index, ~0);
3772  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
3773  if (ri != ~0)
3774  {
3775  /* get radv_info */
3776  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
3777 
3778  /* add address */
3779  if (!ip6_address_is_link_local_unicast (address))
3780  radv_info->ref_count++;
3781 
3782  ip6_neighbor_add_mld_prefix (radv_info, &a);
3783  }
3784  }
3785  else
3786  {
3787 
3788  /* delete */
3789  /* look up the radv_t information for this interface */
3791  sw_if_index, ~0);
3792  ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index];
3793 
3794  if (ri != ~0)
3795  {
3796  /* get radv_info */
3797  radv_info = pool_elt_at_index (nm->if_radv_pool, ri);
3798 
3799  ip6_neighbor_del_mld_prefix (radv_info, &a);
3800 
3801  /* if interface up send MLDP "report" */
3802  radv_info->all_routers_mcast = 0;
3803 
3804  /* add address */
3805  if (!ip6_address_is_link_local_unicast (address))
3806  radv_info->ref_count--;
3807  }
3808  /* Ensure that IPv6 is disabled, and LL removed after ref_count reaches 0 */
3809  disable_ip6_interface (vm, sw_if_index);
3810  }
3811 }
3812 
3813 clib_error_t *
3814 ip6_set_neighbor_limit (u32 neighbor_limit)
3815 {
3817 
3818  nm->limit_neighbor_cache_size = neighbor_limit;
3819  return 0;
3820 }
3821 
3822 static clib_error_t *
3824 {
3826  ip6_main_t *im = &ip6_main;
3827 
3829  /* value size */ sizeof (uword),
3830  /* key size */ sizeof (ip6_neighbor_key_t));
3831 
3832  icmp6_register_type (vm, ICMP6_neighbor_solicitation,
3834  icmp6_register_type (vm, ICMP6_neighbor_advertisement,
3836  icmp6_register_type (vm, ICMP6_router_solicitation,
3838  icmp6_register_type (vm, ICMP6_router_advertisement,
3840 
3841  /* handler node for ip6 neighbor discovery events and timers */
3843 
3844  /* add call backs */
3846  memset (&cb, 0x0, sizeof (ip6_add_del_interface_address_callback_t));
3847 
3848  /* when an interface address changes... */
3850  cb.function_opaque = 0;
3852 
3854  /* value size */ sizeof (uword),
3855  /* key size */ sizeof (ip6_address_t));
3856 
3858  /* value size */ sizeof (uword),
3859  /* key size */ sizeof (ip6_address_t));
3860 
3861  /* default, configurable */
3862  nm->limit_neighbor_cache_size = 50000;
3863 
3864 #if 0
3865  /* $$$$ Hack fix for today */
3867  (im->discover_neighbor_next_index_by_hw_if_index, 32, 0 /* drop */ );
3868 #endif
3869 
3870  return 0;
3871 }
3872 
3874 
3875 
3876 void
3878  void *address_arg,
3879  uword node_index,
3880  uword type_opaque, uword data)
3881 {
3883  ip6_address_t *address = address_arg;
3884  uword *p;
3886 
3887  pool_get (nm->pending_resolutions, pr);
3888 
3889  pr->next_index = ~0;
3890  pr->node_index = node_index;
3891  pr->type_opaque = type_opaque;
3892  pr->data = data;
3893 
3894  p = mhash_get (&nm->pending_resolutions_by_address, address);
3895  if (p)
3896  {
3897  /* Insert new resolution at the head of the list */
3898  pr->next_index = p[0];
3899  mhash_unset (&nm->pending_resolutions_by_address, address, 0);
3900  }
3901 
3903  pr - nm->pending_resolutions, 0 /* old value */ );
3904 }
3905 
3906 int
3908  void *data_callback,
3909  u32 pid,
3910  void *address_arg,
3911  uword node_index,
3912  uword type_opaque, uword data, int is_add)
3913 {
3915  ip6_address_t *address = address_arg;
3916  uword *p;
3918  void (*fp) (u32, u8 *) = data_callback;
3919 
3920  if (is_add)
3921  {
3922  pool_get (nm->mac_changes, mc);
3923 
3924  mc->next_index = ~0;
3925  mc->node_index = node_index;
3926  mc->type_opaque = type_opaque;
3927  mc->data = data;
3928  mc->data_callback = data_callback;
3929  mc->pid = pid;
3930 
3931  p = mhash_get (&nm->mac_changes_by_address, address);
3932  if (p)
3933  {
3934  /* Insert new resolution at the head of the list */
3935  mc->next_index = p[0];
3936  mhash_unset (&nm->mac_changes_by_address, address, 0);
3937  }
3938 
3939  mhash_set (&nm->mac_changes_by_address, address,
3940  mc - nm->mac_changes, 0);
3941  return 0;
3942  }
3943  else
3944  {
3945  u32 index;
3946  pending_resolution_t *mc_last = 0;
3947 
3948  p = mhash_get (&nm->mac_changes_by_address, address);
3949  if (p == 0)
3950  return VNET_API_ERROR_NO_SUCH_ENTRY;
3951 
3952  index = p[0];
3953 
3954  while (index != (u32) ~ 0)
3955  {
3956  mc = pool_elt_at_index (nm->mac_changes, index);
3957  if (mc->node_index == node_index &&
3958  mc->type_opaque == type_opaque && mc->pid == pid)
3959  {
3960  /* Clients may need to clean up pool entries, too */
3961  if (fp)
3962  (*fp) (mc->data, 0 /* no new mac addrs */ );
3963  if (index == p[0])
3964  {
3965  mhash_unset (&nm->mac_changes_by_address, address, 0);
3966  if (mc->next_index != ~0)
3967  mhash_set (&nm->mac_changes_by_address, address,
3968  mc->next_index, 0);
3969  pool_put (nm->mac_changes, mc);
3970  return 0;
3971  }
3972  else
3973  {
3974  ASSERT (mc_last);
3975  mc_last->next_index = mc->next_index;
3976  pool_put (nm->mac_changes, mc);
3977  return 0;
3978  }
3979  }
3980  mc_last = mc;
3981  index = mc->next_index;
3982  }
3983 
3984  return VNET_API_ERROR_NO_SUCH_ENTRY;
3985  }
3986 }
3987 
3988 int
3990  vlib_node_runtime_t * node,
3991  vlib_buffer_t * p0,
3992  ethernet_header_t * eth,
3993  ip6_header_t * ip, u32 sw_if_index, u16 bd_index)
3994 {
3996  icmp6_neighbor_solicitation_or_advertisement_header_t *ndh;
3998 
3999  ndh = ip6_next_header (ip);
4000  if (ndh->icmp.type != ICMP6_neighbor_solicitation &&
4001  ndh->icmp.type != ICMP6_neighbor_advertisement)
4002  return 0;
4003 
4004  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
4005  (p0->flags & VLIB_BUFFER_IS_TRACED)))
4006  {
4007  u8 *t0 = vlib_add_trace (vm, node, p0,
4008  sizeof (icmp6_input_trace_t));
4009  clib_memcpy (t0, ip, sizeof (icmp6_input_trace_t));
4010  }
4011 
4012  /* Check if anyone want ND events for L2 BDs */
4013  uword *p = mhash_get (&nm->mac_changes_by_address, &ip6a_zero);
4015  {
4016  u32 next_index = p[0];
4017  while (next_index != (u32) ~ 0)
4018  {
4019  int (*fp) (u32, u8 *, u32, ip6_address_t *);
4020  int rv = 1;
4021  mc = pool_elt_at_index (nm->mac_changes, next_index);
4022  fp = mc->data_callback;
4023  /* Call the callback, return 1 to suppress dup events */
4024  if (fp)
4025  rv = (*fp) (mc->data,
4026  eth->src_address, sw_if_index, &ip->src_address);
4027  /* Signal the resolver process */
4028  if (rv == 0)
4030  mc->type_opaque, mc->data);
4031  next_index = mc->next_index;
4032  }
4033  }
4034 
4035  /* Check if MAC entry exsist for solicited target IP */
4036  if (ndh->icmp.type == ICMP6_neighbor_solicitation)
4037  {
4038  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *opt;
4039  l2_bridge_domain_t *bd_config;
4040  u8 *macp;
4041 
4042  opt = (void *) (ndh + 1);
4043  if ((opt->header.type !=
4044  ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address) ||
4045  (opt->header.n_data_u64s != 1))
4046  return 0; /* source link layer address option not present */
4047 
4048  bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
4049  macp =
4050  (u8 *) hash_get_mem (bd_config->mac_by_ip6, &ndh->target_address);
4051  if (macp)
4052  { /* found ip-mac entry, generate eighbor advertisement response */
4053  int bogus_length;
4054  vlib_node_runtime_t *error_node =
4056  ip->dst_address = ip->src_address;
4057  ip->src_address = ndh->target_address;
4058  ip->hop_limit = 255;
4059  opt->header.type =
4060  ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address;
4061  clib_memcpy (opt->ethernet_address, macp, 6);
4062  ndh->icmp.type = ICMP6_neighbor_advertisement;
4063  ndh->advertisement_flags = clib_host_to_net_u32
4066  ndh->icmp.checksum = 0;
4067  ndh->icmp.checksum =
4068  ip6_tcp_udp_icmp_compute_checksum (vm, p0, ip, &bogus_length);
4069  clib_memcpy (eth->dst_address, eth->src_address, 6);
4070  clib_memcpy (eth->src_address, macp, 6);
4071  vlib_error_count (vm, error_node->node_index,
4072  ICMP6_ERROR_NEIGHBOR_ADVERTISEMENTS_TX, 1);
4073  return 1;
4074  }
4075  }
4076 
4077  return 0;
4078 
4079 }
4080 
4081 int
4083 {
4084  u32 fib_index;
4085 
4086  fib_prefix_t pfx = {
4087  .fp_len = 128,
4088  .fp_proto = FIB_PROTOCOL_IP6,
4089  .fp_addr = {
4090  .ip6 = *addr,
4091  },
4092  };
4093  ip46_address_t nh = {
4094  .ip6 = *addr,
4095  };
4096 
4097  fib_index = ip6_fib_table_get_index_for_sw_if_index (sw_if_index);
4098 
4099  if (~0 == fib_index)
4100  return VNET_API_ERROR_NO_SUCH_FIB;
4101 
4102  if (is_del)
4103  {
4104  fib_table_entry_path_remove (fib_index,
4105  &pfx,
4108  &nh,
4109  sw_if_index,
4110  ~0, 1, FIB_ROUTE_PATH_FLAG_NONE);
4111  /* flush the ND cache of this address if it's there */
4113  sw_if_index, addr, NULL, 0);
4114  }
4115  else
4116  {
4117  fib_table_entry_path_add (fib_index,
4118  &pfx,
4122  &nh,
4123  sw_if_index,
4124  ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
4125  }
4126  return (0);
4127 }
4128 
4129 static clib_error_t *
4131  unformat_input_t * input, vlib_cli_command_t * cmd)
4132 {
4133  vnet_main_t *vnm = vnet_get_main ();
4134  clib_error_t *error = 0;
4136  u32 sw_if_index;
4137  u8 is_del = 0;
4138 
4139  if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
4140  {
4141  /* get the rest of the command */
4142  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4143  {
4144  if (unformat (input, "%U", unformat_ip6_address, &addr))
4145  break;
4146  else if (unformat (input, "delete") || unformat (input, "del"))
4147  is_del = 1;
4148  else
4149  return (unformat_parse_error (input));
4150  }
4151  }
4152 
4153  ip6_neighbor_proxy_add_del (sw_if_index, &addr, is_del);
4154 
4155  return error;
4156 }
4157 
4158 /* *INDENT-OFF* */
4159 VLIB_CLI_COMMAND (set_ip6_nd_proxy_command, static) =
4160 {
4161  .path = "set ip6 nd proxy",
4162  .short_help = "set ip6 nd proxy <HOST> <INTERFACE>",
4163  .function = set_ip6_nd_proxy_cmd,
4164 };
4165 /* *INDENT-ON* */
4166 
4167 void
4169 {
4171  ip6_neighbor_t *n;
4172 
4173  /* *INDENT-OFF* */
4174  pool_foreach (n, nm->neighbor_pool,
4175  ({
4176  if (n->key.sw_if_index == sw_if_index)
4177  {
4178  adj_nbr_walk_nh6 (sw_if_index,
4179  &n->key.ip6_address,
4180  ip6_nd_mk_complete_walk, n);
4181  }
4182  }));
4183  /* *INDENT-ON* */
4184 }
4185 
4186 /*
4187  * fd.io coding-style-patch-verification: ON
4188  *
4189  * Local Variables:
4190  * eval: (c-set-style "gnu")
4191  * End:
4192  */
#define ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED
This packets follow a load-balance.
Definition: lookup.h:86
fib_node_index_t fib_table_entry_update_one_path(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, fib_protocol_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags)
Update the entry to have just one path.
Definition: fib_table.c:716
ip6_radv_t * if_radv_pool
Definition: ip6_neighbor.c:192
#define MIN_DELAY_BETWEEN_RAS
Definition: ip6_neighbor.c:131
#define vnet_rewrite_one_header(rw0, p0, most_likely_size)
Definition: rewrite.h:283
#define DEF_DEF_RTR_LIFETIME
Definition: ip6_neighbor.c:126
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
static void ip6_nd_mk_incomplete(adj_index_t ai)
Definition: ip6_neighbor.c:433
vmrglw vmrglh hi
#define pool_next_index(P, I)
Return next occupied pool index after i, useful for safe iteration.
Definition: pool.h:405
Definition: mhash.h:46
void md5_finish(md5_context_t *c, u8 *digest)
Definition: md5.c:290
#define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST
Definition: rewrite.h:315
icmp6_router_solicitation_or_advertisement_next_t
u32 n_solicitations_rcvd
Definition: ip6_neighbor.c:152
static void unset_random_neighbor_entry(void)
Definition: ip6_neighbor.c:290
static void ip6_neighbor_syslog(vlib_main_t *vm, int priority, char *fmt,...)
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define ICMP6_ROUTER_DISCOVERY_FLAG_OTHER_CONFIG_VIA_DHCP
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:215
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:683
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)
An indication that the rewrite is incomplete, i.e.
Definition: adj_nbr.h:90
static void ip6_nbr_probe(ip_adjacency_t *adj)
Definition: ip6_neighbor.c:355
static clib_error_t * ip6_neighbor_init(vlib_main_t *vm)
f64 last_radv_time
Definition: ip6_neighbor.c:141
ip_interface_address_t * if_address_pool
Pool of addresses that are assigned to interfaces.
Definition: lookup.h:337
An indication that the rewrite is complete, i.e.
Definition: adj_nbr.h:98
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
static char * log_level_strings[]
ip6_multicast_address_scope_t
Definition: ip6_packet.h:130
struct ip_adjacency_t_::@138::@139 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
static void ip6_nd_mk_complete(adj_index_t ai, ip6_neighbor_t *nbr)
Definition: ip6_neighbor.c:423
mhash_t neighbor_index_by_key
Definition: ip6_neighbor.c:188
u32 free_list_index
Buffer free list that this buffer was allocated from and will be freed to.
Definition: buffer.h:99
#define PREDICT_TRUE(x)
Definition: clib.h:98
static void ip6_neighbor_del_mld_prefix(ip6_radv_t *radv_info, ip6_address_t *addr)
Delete a multicast Address from the advertised MLD set.
u8 as_u8[16]
Definition: ip6_packet.h:48
u64 as_u64[2]
Definition: ip6_packet.h:51
static clib_error_t * set_ip6_nd_proxy_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
int send_unicast
Definition: ip6_neighbor.c:112
ip6_address_t prefix
Definition: ip6_neighbor.c:44
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
static ip6_address_t * ip6_interface_address_matching_destination(ip6_main_t *im, ip6_address_t *dst, u32 sw_if_index, ip_interface_address_t **result_ia)
Definition: ip6.h:284
static uword ip6_address_is_local_unicast(ip6_address_t *a)
Definition: ip6_packet.h:303
f64 last_multicast_time
Definition: ip6_neighbor.c:142
void md5_init(md5_context_t *c)
Definition: md5.c:211
vnet_link_t adj_get_link_type(adj_index_t ai)
Return the link type of the adjacency.
Definition: adj.c:340
#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
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:185
ip6_radv_prefix_t * adv_prefixes_pool
Definition: ip6_neighbor.c:97
IP unicast adjacency.
Definition: lookup.h:193
#define ethernet_buffer_header_size(b)
Determine the size of the Ethernet headers of the current frame in the buffer.
Definition: ethernet.h:390
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:459
u8 src_address[6]
Definition: packet.h:54
static uword ip6_address_is_global_unicast(ip6_address_t *a)
Definition: ip6_packet.h:310
ip6_neighbor_t * ip6_neighbors_entries(u32 sw_if_index)
Definition: ip6_neighbor.c:787
pending_resolution_t * pending_resolutions
Definition: ip6_neighbor.c:178
static vlib_cli_command_t set_ip6_neighbor_command
(constructor) VLIB_CLI_COMMAND (set_ip6_neighbor_command)
Definition: ip6_neighbor.c:919
#define ETHER_MAC_ADDR_LEN
Definition: ip6_neighbor.c:38
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
word vnet_sw_interface_compare(vnet_main_t *vnm, uword sw_if_index0, uword sw_if_index1)
Definition: interface.c:1112
static u64 clib_cpu_time_now(void)
Definition: time.h:73
#define IP6_NBR_MK_KEY(k, sw_if_index, addr)
Definition: ip6_neighbor.c:446
static int logmask
struct _vlib_node_registration vlib_node_registration_t
void fib_table_entry_path_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_protocol_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_route_path_flags_t path_flags)
remove one path to an entry (aka route) in the FIB.
Definition: fib_table.c:625
int ip6_neighbor_proxy_add_del(u32 sw_if_index, ip6_address_t *addr, u8 is_del)
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:982
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:62
u32 adv_pref_lifetime_in_secs
Definition: ip6_neighbor.c:49
#define DEF_ADV_PREF_LIFETIME
Definition: ip6_neighbor.c:62
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
u8 * va_format(u8 *s, const char *fmt, va_list *va)
Definition: format.c:386
union ip_adjacency_t_::@138 sub_type
format_function_t format_vlib_cpu_time
Definition: node_funcs.h:1109
unformat_function_t unformat_vnet_sw_interface
static u64 random_u64(u64 *seed)
64-bit random number generator Again, constants courtesy of Donald Knuth.
Definition: random.h:126
int vnet_add_del_ip6_nd_change_event(vnet_main_t *vnm, void *data_callback, u32 pid, void *address_arg, uword node_index, uword type_opaque, uword data, int is_add)
u32 adv_neighbor_reachable_time_in_msec
Definition: ip6_neighbor.c:86
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:418
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
Multicast Adjacency.
Definition: lookup.h:95
ip6_address_t src_address
Definition: ip6_packet.h:341
format_function_t format_vnet_sw_if_index_name
void * data_callback
Definition: arp.c:66
clib_error_t * disable_ip6_interface(vlib_main_t *vm, u32 sw_if_index)
Adjacency to drop this packet.
Definition: lookup.h:63
vnet_link_t ia_link
Definition: lookup.h:214
static uword ip6_neighbor_process_timer_event(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
vlib_packet_template_t discover_neighbor_packet_template
Definition: ip6.h:187
ip6_neighbor_flags_t flags
Definition: ip6_neighbor.h:42
void adj_mcast_update_rewrite(adj_index_t adj_index, u8 *rewrite)
adj_mcast_update_rewrite
Definition: adj_mcast.c:102
ethernet_main_t ethernet_main
Definition: ethernet.h:273
fib_node_index_t ip6_fib_table_lookup_exact_match(u32 fib_index, const ip6_address_t *addr, u32 len)
Definition: ip6_fib.c:239
static void ip6_print_addrs(vlib_main_t *vm, u32 *addrs)
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:128
#define static_always_inline
Definition: clib.h:85
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
Definition: buffer.c:818
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u32 local_interface_sw_if_index
Definition: vnet.h:55
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(ip6_neighbor_sw_interface_up_down)
This packets needs to go to ICMP error.
Definition: lookup.h:92
u8 link_layer_addr_len
Definition: ip6_neighbor.c:94
#define ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE
u8 dst_address[6]
Definition: packet.h:53
enum adj_walk_rc_t_ adj_walk_rc_t
return codes from a adjacency walker callback function
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:220
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:807
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, int is_no_fib_entry)
Definition: ip6_neighbor.c:570
#define DEF_ADV_VALID_LIFETIME
Definition: ip6_neighbor.c:61
mhash_t address_to_mldp_index
Definition: ip6_neighbor.c:106
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static vnet_sw_interface_t * vnet_get_sup_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
Aggregrate type for a prefix.
Definition: fib_types.h:160
Adjacency to punt this packet.
Definition: lookup.h:65
#define clib_error_return(e, args...)
Definition: error.h:111
static u32 ip6_src_lookup_for_packet(ip6_main_t *im, vlib_buffer_t *b, ip6_header_t *i)
return the DPO that the LB stacks on.
Definition: ip6_fib.h:73
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: memory_vlib.c:1327
unsigned long u64
Definition: types.h:89
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:215
clib_error_t * set_ip6_link_local_address(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *address)
f64 max_radv_interval
Definition: ip6_neighbor.c:135
This packet is for one of our own IP addresses.
Definition: lookup.h:68
static clib_error_t * set_ip6_neighbor(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip6_neighbor.c:862
u32 * neighbor_input_next_index_by_hw_if_index
Definition: ip6_neighbor.c:184
int vnet_ip6_nd_term(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *p0, ethernet_header_t *eth, ip6_header_t *ip, u32 sw_if_index, u16 bd_index)
u16 fp_len
The mask length.
Definition: fib_types.h:164
const u8 * ethernet_ip6_mcast_dst_addr(void)
Definition: interface.c:65
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: lookup.h:78
u32 ip6_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip6_fib.c:392
#define MAX_DELAY_BETWEEN_RAS
Definition: ip6_neighbor.c:132
Definition: fib_entry.h:227
unformat_function_t unformat_line_input
Definition: format.h:281
fib_node_index_t fib_table_entry_path_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, fib_protocol_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags)
Add one path to an entry (aka route) in the FIB.
Definition: fib_table.c:477
f64 max_delay_between_radv
Definition: ip6_neighbor.c:138
u32 adv_time_in_msec_between_retransmitted_neighbor_solicitations
Definition: ip6_neighbor.c:87
#define pool_flush(VAR, POOL, BODY)
Remove all elemenets from a pool in a safe way.
Definition: pool.h:433
vnet_api_error_t api_errno
Definition: vnet.h:77
Definition: fib_entry.h:232
format_function_t format_vnet_sw_interface_name
#define ADJ_INDEX_INVALID
Invalid ADJ index - used when no adj is known likewise blazoned capitals INVALID speak volumes where ...
Definition: adj_types.h:36
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:397
vlib_main_t * vlib_main
Definition: vnet.h:79
f64 min_radv_interval
Definition: ip6_neighbor.c:136
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:71
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:930
Adjacency source.
Definition: fib_entry.h:92
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:183
uword type_opaque
Definition: arp.c:63
static void ip6_neighbor_add_mld_grp(ip6_radv_t *a, ip6_multicast_address_scope_t scope, ip6_multicast_link_local_group_id_t group)
Add a multicast Address to the advertised MLD set.
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:715
static void set_unset_ip6_neighbor_rpc(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *a, u8 *link_layer_address, int is_add, int is_static, int is_no_fib_entry)
Definition: ip6_neighbor.c:334
int all_routers_mcast
Definition: ip6_neighbor.c:116
struct _unformat_input_t unformat_input_t
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:123
#define IP6_MLDP_ALERT_TYPE
u8 link_layer_address[8]
Definition: ip6_neighbor.c:93
f64 next_multicast_time
Definition: ip6_neighbor.c:143
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
Definition: buffer.h:390
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
#define foreach_log_level
enum icmp6_neighbor_discovery_option_type icmp6_neighbor_discovery_option_type_t
#define ELOG_DATA(em, f)
Definition: elog.h:392
int ip6_address_compare(ip6_address_t *a1, ip6_address_t *a2)
Definition: ip46_cli.c:58
#define PREDICT_FALSE(x)
Definition: clib.h:97
vnet_main_t vnet_main
Definition: misc.c:43
#define VLIB_FRAME_SIZE
Definition: node.h:328
int adv_other_flag
Definition: ip6_neighbor.c:84
u32 node_index
Node index.
Definition: node.h:436
mhash_t address_to_prefix_index
Definition: ip6_neighbor.c:100
#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:216
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:350
ip6_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Definition: ip6.h:184
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:113
void ip6_link_local_address_from_ethernet_mac_address(ip6_address_t *ip, u8 *mac)
Definition: ip6_forward.c:3035
static void ip6_neighbor_add_mld_prefix(ip6_radv_t *radv_info, ip6_address_t *addr)
Add a multicast Address to the advertised MLD set.
int failed_device_check
Definition: ip6_neighbor.c:115
vlib_node_registration_t ip6_icmp_input_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_input_node)
Definition: icmp6.c:240
unformat_function_t unformat_ip6_address
Definition: format.h:94
#define pool_free(p)
Free a pool.
Definition: pool.h:290
ip6_mldp_group_t * mldp_group_pool
Definition: ip6_neighbor.c:103
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:935
clib_error_t * enable_ip6_interface(vlib_main_t *vm, u32 sw_if_index)
void ip6_mfib_interface_enable_disable(u32 sw_if_index, int is_enable)
Add/remove the interface from the accepting list of the special MFIB entries.
Definition: ip6_mfib.c:258
icmp6_neighbor_solicitation_or_advertisement_next_t
Definition: ip6_neighbor.c:927
int adv_managed_flag
Definition: ip6_neighbor.c:83
static uword icmp6_neighbor_advertisement(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
int fib_entry_is_sourced(fib_node_index_t fib_entry_index, fib_source_t source)
u32 n_solicitations_dropped
Definition: ip6_neighbor.c:153
u32 vlib_buffer_add_data(vlib_main_t *vm, u32 free_list_index, u32 buffer_index, void *data, u32 n_data_bytes)
Definition: buffer.c:856
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
Definition: mhash.c:168
#define VNET_BUFFER_LOCALLY_ORIGINATED
Definition: buffer.h:68
u16 n_vectors
Definition: node.h:344
format_function_t format_ip6_address
Definition: format.h:95
static ip6_address_t ip6a_zero
Definition: ip6_neighbor.c:217
vlib_main_t * vm
Definition: buffer.c:276
vec_header_t h
Definition: buffer.c:275
void fib_table_entry_delete_index(fib_node_index_t fib_entry_index, fib_source_t source)
Delete a FIB entry.
Definition: fib_table.c:821
ip6_address_t mcast_address
Definition: ip6_neighbor.c:72
log_level_t
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
u8 curr_hop_limit
Definition: ip6_neighbor.c:82
#define clib_warning(format, args...)
Definition: error.h:59
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
ip6_address_t * mcast_source_address_pool
Definition: ip6_neighbor.c:74
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:69
#define DEF_CURR_HOP_LIMIT
Definition: ip6_neighbor.c:125
static 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: buffer_funcs.h:269
elog_main_t elog_main
Definition: main.h:141
int adv_link_layer_address
Definition: ip6_neighbor.c:113
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
static vlib_cli_command_t show_ip6_neighbors_command
(constructor) VLIB_CLI_COMMAND (show_ip6_neighbors_command)
Definition: ip6_neighbor.c:854
fib_node_index_t fib_entry_index
Definition: ip6_neighbor.h:44
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
uword * mac_by_ip6
Definition: l2_bd.h:84
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:350
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: lookup.h:73
void md5_add(md5_context_t *c, void *data, int data_bytes)
Definition: md5.c:235
u64 cpu_time_last_updated
Definition: ip6_neighbor.h:43
static void * ip6_next_header(ip6_header_t *i)
Definition: ip6_packet.h:345
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
u32 initial_adverts_count
Definition: ip6_neighbor.c:146
u32 * if_address_pool_index_by_sw_if_index
Head of doubly linked list of interface addresses for each software interface.
Definition: lookup.h:344
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:1139
ip6_add_del_interface_address_function_t * function
Definition: ip6.h:105
#define MAX_INITIAL_RTR_ADVERTISEMENTS
Definition: ip6_neighbor.c:130
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:455
ip6_address_t link_local_address
Definition: ip6_neighbor.c:156
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:536
u32 max_l3_packet_bytes[VLIB_N_RX_TX]
Definition: interface.h:451
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:227
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
int prefix_option
Definition: ip6_neighbor.c:114
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
ip6_address_t ip6_address
Definition: ip6_neighbor.h:26
ip6_main_t ip6_main
Definition: ip6_forward.c:2846
ip_lookup_main_t lookup_main
Definition: ip6.h:151
u32 n_advertisements_sent
Definition: ip6_neighbor.c:151
static void mhash_free(mhash_t *h)
Definition: mhash.h:149
static clib_error_t * show_ip6_interface_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u32 vlib_register_node(vlib_main_t *vm, vlib_node_registration_t *r)
Definition: node.c:469
This packets follow a mid-chain adjacency.
Definition: lookup.h:89
f64 min_delay_between_radv
Definition: ip6_neighbor.c:137
#define DEF_MIN_RADV_INTERVAL
Definition: ip6_neighbor.c:124
static_always_inline uword icmp6_router_solicitation(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static int ip6_neighbor_sort(void *a1, void *a2)
Definition: ip6_neighbor.c:774
u32 * if_radv_pool_index_by_sw_if_index
Definition: ip6_neighbor.c:190
u16 adv_router_lifetime_in_sec
Definition: ip6_neighbor.c:85
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:201
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
ip6_multicast_link_local_group_id_t
Definition: ip6_packet.h:137
Route added as a result of interface configuration.
Definition: fib_entry.h:50
mhash_t pending_resolutions_by_address
Definition: ip6_neighbor.c:177
static uword icmp6_neighbor_solicitation(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static adj_walk_rc_t ip6_nd_mk_incomplete_walk(adj_index_t ai, void *ctx)
Definition: ip6_neighbor.c:483
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static uword vnet_sw_interface_is_admin_up(vnet_main_t *vnm, u32 sw_if_index)
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
#define unformat_parse_error(input)
Definition: format.h:267
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:328
void ethernet_ndp_change_mac(u32 sw_if_index)
fib_entry_flag_t fib_entry_get_flags_for_source(fib_node_index_t fib_entry_index, fib_source_t source)
static vlib_node_registration_t ip6_icmp_router_solicitation_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_router_solicitation_node)
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
l2input_main_t l2input_main
Definition: l2_input.c:88
vlib_node_registration_t ip6_icmp_neighbor_discovery_event_node
u16 payload_length
Definition: ip6_packet.h:332
static void * vlib_process_get_event_data(vlib_main_t *vm, uword *return_event_type_opaque)
Definition: node_funcs.h:473
static void ip6_neighbor_set_unset_rpc_callback(ip6_neighbor_set_unset_rpc_args_t *a)
Definition: ip6_neighbor.c:761
ethernet_interface_t * ethernet_get_interface(ethernet_main_t *em, u32 hw_if_index)
Definition: interface.c:672
static void ip6_set_solicited_node_multicast_address(ip6_address_t *a, u32 id)
Definition: ip6_packet.h:168
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:29
ip6_neighbor_key_t key
Definition: ip6_neighbor.h:40
static uword ip6_address_is_link_local_unicast(ip6_address_t *a)
Definition: ip6_packet.h:296
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:803
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
ip_lookup_next_t lookup_next_index
Definition: lookup.h:204
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:960
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
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)
callback when an interface address is added or deleted
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
u8 * ethernet_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
build a rewrite string to use for sending packets of type &#39;link_type&#39; to &#39;dst_address&#39; ...
Definition: interface.c:79
l2_bridge_domain_t * bd_configs
Definition: l2_input.h:72
#define ICMP6_ROUTER_DISCOVERY_FLAG_ADDRESS_CONFIG_VIA_DHCP
#define hash_get_mem(h, key)
Definition: hash.h:268
static u32 ip6_neighbor_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
create and initialize router advertisement parameters with default values for this intfc ...
static vlib_node_registration_t ip6_icmp_neighbor_advertisement_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_neighbor_advertisement_node)
#define vnet_buffer(b)
Definition: buffer.h:294
static clib_error_t * ip6_neighbor_sw_interface_up_down(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: ip6_neighbor.c:254
f64 initial_adverts_interval
Definition: ip6_neighbor.c:147
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
vnet_sw_interface_type_t type
Definition: interface.h:531
adj_index_t mcast_adj_index
Definition: ip6_neighbor.c:120
uword node_index
Definition: arp.c:62
ip6_icmp_neighbor_discovery_event_type_t
Definition: ip6_neighbor.c:201
adj_index_t adj_mcast_add_or_lock(fib_protocol_t proto, vnet_link_t link_type, u32 sw_if_index)
Mcast Adjacency.
Definition: adj_mcast.c:51
This packet is to be rewritten and forwarded to the next processing node.
Definition: lookup.h:83
#define vec_foreach(var, vec)
Vector iterator.
static uword ip6_address_is_unspecified(ip6_address_t *a)
Definition: ip6_packet.h:277
void ip6_ethernet_update_adjacency(vnet_main_t *vnm, u32 sw_if_index, u32 ai)
Definition: ip6_neighbor.c:491
u16 flags
Copy of main node flags.
Definition: node.h:449
u32 adv_valid_lifetime_in_secs
Definition: ip6_neighbor.c:48
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:447
vhost_vring_addr_t addr
Definition: vhost-user.h:84
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
u32 initial_adverts_sent
Definition: ip6_neighbor.c:148
static void * ip_interface_address_get_address(ip_lookup_main_t *lm, ip_interface_address_t *a)
Definition: lookup.h:410
static ip6_neighbor_t * ip6_nd_find(u32 sw_if_index, const ip6_address_t *addr)
Definition: ip6_neighbor.c:454
mhash_t mac_changes_by_address
Definition: ip6_neighbor.c:181
static void ip6_link_local_address_from_ethernet_address(ip6_address_t *a, u8 *ethernet_address)
Definition: ip6_packet.h:180
static adj_walk_rc_t ip6_nd_mk_complete_walk(adj_index_t ai, void *ctx)
Definition: ip6_neighbor.c:473
#define MAX_INITIAL_RTR_ADVERT_INTERVAL
Definition: ip6_neighbor.c:129
u32 flags
Definition: vhost-user.h:78
#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:485
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
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:139
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:186
void adj_nbr_update_rewrite(adj_index_t adj_index, adj_nbr_rewrite_flag_t flags, u8 *rewrite)
adj_nbr_update_rewrite
Definition: adj_nbr.c:293
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:577
u32 * fib_index_by_sw_if_index
Definition: ip6.h:163
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
u8 link_layer_address[8]
Definition: ip6_neighbor.h:41
static_always_inline uword icmp6_router_advertisement(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:971
#define MAX_DEF_RTR_LIFETIME
Definition: ip6_neighbor.c:127
u32 adv_link_mtu
Definition: ip6_neighbor.c:90
Definition: defs.h:46
static ip6_neighbor_main_t ip6_neighbor_main
Definition: ip6_neighbor.c:216
pending_resolution_t * mac_changes
Definition: ip6_neighbor.c:182
ip6_address_t dst_address
Definition: ip6_packet.h:341
int ip6_interface_enabled(vlib_main_t *vm, u32 sw_if_index)
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
static void ip6_set_reserved_multicast_address(ip6_address_t *a, ip6_multicast_address_scope_t scope, u16 id)
Definition: ip6_packet.h:158
static ip_adjacency_t * ip_get_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.h:377
IPv6 Proxy ND.
Definition: fib_entry.h:86
clib_error_t * ip6_set_neighbor_limit(u32 neighbor_limit)
format_function_t format_icmp6_input_trace
Definition: icmp6.h:64
void adj_nbr_walk_nh6(u32 sw_if_index, const ip6_address_t *addr, adj_walk_cb_t cb, void *ctx)
Walk adjacencies on a link with a given v6 next-hop.
Definition: adj_nbr.c:645
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109