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