Typos. A bunch of typos I've been collecting.
[vpp.git] / src / vnet / ip / ip6_neighbor.c
index a7ce279..86b1800 100755 (executable)
@@ -26,6 +26,7 @@
 #include <vnet/mfib/ip6_mfib.h>
 #include <vnet/ip/ip6_ll_table.h>
 #include <vnet/l2/l2_input.h>
+#include <vlibmemory/api.h>
 
 /**
  * @file
@@ -173,7 +174,7 @@ typedef struct
   uword type_opaque;
   uword data;
   /* Used for nd event notification only */
-  void *data_callback;
+  ip6_nd_change_event_cb_t data_callback;
   u32 pid;
 } pending_resolution_t;
 
@@ -266,15 +267,15 @@ ip6_neighbor_get_link_local_address (u32 sw_if_index)
  * @param sw_if_index The interface on which the ARP entires are acted
  */
 static int
-vnet_nd_wc_publish (u32 sw_if_index, u8 * mac, ip6_address_t * ip6)
+vnet_nd_wc_publish (u32 sw_if_index,
+                   const mac_address_t * mac, const ip6_address_t * ip6)
 {
   wc_nd_report_t r = {
     .sw_if_index = sw_if_index,
     .ip6 = *ip6,
+    .mac = *mac,
   };
-  memcpy (r.mac, mac, sizeof r.mac);
 
-  void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length);
   vl_api_rpc_call_main_thread (wc_nd_signal_report, (u8 *) & r, sizeof r);
   return 0;
 }
@@ -347,13 +348,13 @@ format_ip6_neighbor_ip6_entry (u8 * s, va_list * va)
     return format (s, "%=12s%=45s%=6s%=20s%=40s", "Time", "Address", "Flags",
                   "Link layer", "Interface");
 
-  if (n->flags & IP6_NEIGHBOR_FLAG_DYNAMIC)
+  if (n->flags & IP_NEIGHBOR_FLAG_DYNAMIC)
     flags = format (flags, "D");
 
-  if (n->flags & IP6_NEIGHBOR_FLAG_STATIC)
+  if (n->flags & IP_NEIGHBOR_FLAG_STATIC)
     flags = format (flags, "S");
 
-  if (n->flags & IP6_NEIGHBOR_FLAG_NO_FIB_ENTRY)
+  if (n->flags & IP_NEIGHBOR_FLAG_NO_FIB_ENTRY)
     flags = format (flags, "N");
 
   si = vnet_get_sw_interface (vnm, n->key.sw_if_index);
@@ -361,7 +362,7 @@ format_ip6_neighbor_ip6_entry (u8 * s, va_list * va)
              format_vlib_time, vm, n->time_last_updated,
              format_ip6_address, &n->key.ip6_address,
              flags ? (char *) flags : "",
-             format_ethernet_address, n->link_layer_address,
+             format_mac_address_t, &n->mac,
              format_vnet_sw_interface_name, vnm, si);
 
   vec_free (flags);
@@ -402,9 +403,8 @@ ip6_neighbor_adj_fib_remove (ip6_neighbor_t * n, u32 fib_index)
 typedef struct
 {
   u8 is_add;
-  u8 is_static;
-  u8 is_no_fib_entry;
-  u8 link_layer_address[6];
+  ip_neighbor_flags_t flags;
+  mac_address_t mac;
   u32 sw_if_index;
   ip6_address_t addr;
 } ip6_neighbor_set_unset_rpc_args_t;
@@ -416,19 +416,16 @@ static void set_unset_ip6_neighbor_rpc
   (vlib_main_t * vm,
    u32 sw_if_index,
    const ip6_address_t * a,
-   const u8 * link_layer_address,
-   int is_add, int is_static, int is_no_fib_entry)
+   const mac_address_t * mac, int is_add, ip_neighbor_flags_t flags)
 {
   ip6_neighbor_set_unset_rpc_args_t args;
   void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length);
 
   args.sw_if_index = sw_if_index;
   args.is_add = is_add;
-  args.is_static = is_static;
-  args.is_no_fib_entry = is_no_fib_entry;
-  clib_memcpy (&args.addr, a, sizeof (*a));
-  if (NULL != link_layer_address)
-    clib_memcpy (args.link_layer_address, link_layer_address, 6);
+  args.flags = flags;
+  ip6_address_copy (&args.addr, a);
+  mac_address_copy (&args.mac, mac);
 
   vl_api_rpc_call_main_thread (ip6_neighbor_set_unset_rpc_callback,
                               (u8 *) & args, sizeof (args));
@@ -511,7 +508,7 @@ ip6_nd_mk_complete (adj_index_t ai, ip6_neighbor_t * nbr)
                          ethernet_build_rewrite (vnet_get_main (),
                                                  nbr->key.sw_if_index,
                                                  adj_get_link_type (ai),
-                                                 nbr->link_layer_address));
+                                                 nbr->mac.bytes));
 }
 
 static void
@@ -604,7 +601,7 @@ ip6_neighbor_sw_interface_up_down (vnet_main_t * vnm,
          n = pool_elt_at_index (nm->neighbor_pool, to_delete[i]);
          adj_nbr_walk_nh6 (n->key.sw_if_index, &n->key.ip6_address,
                            ip6_nd_mk_incomplete_walk, NULL);
-         if (n->flags & IP6_NEIGHBOR_FLAG_STATIC)
+         if (n->flags & IP_NEIGHBOR_FLAG_STATIC)
            continue;
          ip6_neighbor_adj_fib_remove (n,
                                       ip6_fib_table_get_index_for_sw_if_index
@@ -759,7 +756,7 @@ force_reuse_neighbor_entry (void)
       nm->neighbor_delete_rotor = index;
       index = pool_next_index (nm->neighbor_pool, index);
     }
-  while (n->flags & IP6_NEIGHBOR_FLAG_STATIC);
+  while (n->flags & IP_NEIGHBOR_FLAG_STATIC);
 
   /* Remove ARP entry from its interface and update fib */
   adj_nbr_walk_nh6 (n->key.sw_if_index,
@@ -775,9 +772,8 @@ int
 vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm,
                                u32 sw_if_index,
                                const ip6_address_t * a,
-                               const u8 * link_layer_address,
-                               uword n_bytes_link_layer_address,
-                               int is_static, int is_no_fib_entry)
+                               const mac_address_t * mac,
+                               ip_neighbor_flags_t flags)
 {
   ip6_neighbor_main_t *nm = &ip6_neighbor_main;
   ip6_neighbor_key_t k;
@@ -789,9 +785,7 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm,
 
   if (vlib_get_thread_index ())
     {
-      set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, link_layer_address,
-                                 1 /* set new neighbor */ , is_static,
-                                 is_no_fib_entry);
+      set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, mac, 1, flags);
       return 0;
     }
 
@@ -804,11 +798,11 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm,
     {
       n = pool_elt_at_index (nm->neighbor_pool, p[0]);
       /* Refuse to over-write static neighbor entry. */
-      if (!is_static && (n->flags & IP6_NEIGHBOR_FLAG_STATIC))
+      if (!(flags & IP_NEIGHBOR_FLAG_STATIC) &&
+         (n->flags & IP_NEIGHBOR_FLAG_STATIC))
        {
          /* if MAC address match, still check to send event */
-         if (0 == memcmp (n->link_layer_address,
-                          link_layer_address, n_bytes_link_layer_address))
+         if (0 == mac_address_cmp (&n->mac, mac))
            goto check_customers;
          return -2;
        }
@@ -832,20 +826,19 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm,
       n->key = k;
       n->fib_entry_index = FIB_NODE_INDEX_INVALID;
 
-      clib_memcpy (n->link_layer_address,
-                  link_layer_address, n_bytes_link_layer_address);
+      mac_address_copy (&n->mac, mac);
 
       /*
        * create the adj-fib. the entry in the FIB table for and to the peer.
        */
-      if (!is_no_fib_entry)
+      if (!(flags & IP_NEIGHBOR_FLAG_NO_FIB_ENTRY))
        {
          ip6_neighbor_adj_fib_add
            (n, ip6_fib_table_get_index_for_sw_if_index (n->key.sw_if_index));
        }
       else
        {
-         n->flags |= IP6_NEIGHBOR_FLAG_NO_FIB_ENTRY;
+         n->flags |= IP_NEIGHBOR_FLAG_NO_FIB_ENTRY;
        }
     }
   else
@@ -854,28 +847,26 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm,
        * prevent a DoS attack from the data-plane that
        * spams us with no-op updates to the MAC address
        */
-      if (0 == memcmp (n->link_layer_address,
-                      link_layer_address, n_bytes_link_layer_address))
+      if (0 == mac_address_cmp (&n->mac, mac))
        {
          n->time_last_updated = vlib_time_now (vm);
          goto check_customers;
        }
 
-      clib_memcpy (n->link_layer_address,
-                  link_layer_address, n_bytes_link_layer_address);
+      mac_address_copy (&n->mac, mac);
     }
 
   /* Update time stamp and flags. */
   n->time_last_updated = vlib_time_now (vm);
-  if (is_static)
+  if (flags & IP_NEIGHBOR_FLAG_STATIC)
     {
-      n->flags |= IP6_NEIGHBOR_FLAG_STATIC;
-      n->flags &= ~IP6_NEIGHBOR_FLAG_DYNAMIC;
+      n->flags |= IP_NEIGHBOR_FLAG_STATIC;
+      n->flags &= ~IP_NEIGHBOR_FLAG_DYNAMIC;
     }
   else
     {
-      n->flags |= IP6_NEIGHBOR_FLAG_DYNAMIC;
-      n->flags &= ~IP6_NEIGHBOR_FLAG_STATIC;
+      n->flags |= IP_NEIGHBOR_FLAG_DYNAMIC;
+      n->flags &= ~IP_NEIGHBOR_FLAG_STATIC;
     }
 
   adj_nbr_walk_nh6 (sw_if_index,
@@ -908,16 +899,13 @@ check_customers:
 
       while (next_index != (u32) ~ 0)
        {
-         int (*fp) (u32, u8 *, u32, ip6_address_t *);
          int rv = 1;
+
          mc = pool_elt_at_index (nm->mac_changes, next_index);
-         fp = mc->data_callback;
 
          /* Call the user's data callback, return 1 to suppress dup events */
-         if (fp)
-           rv =
-             (*fp) (mc->data, (u8 *) link_layer_address, sw_if_index,
-                    &ip6a_zero);
+         if (mc->data_callback)
+           rv = (mc->data_callback) (mc->data, mac, sw_if_index, &ip6a_zero);
          /*
           * Signal the resolver process, as long as the user
           * says they want to be notified
@@ -944,8 +932,8 @@ vnet_unset_ip6_ethernet_neighbor (vlib_main_t * vm,
 
   if (vlib_get_thread_index ())
     {
-      set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, NULL,
-                                 0 /* unset */ , 0, 0);
+      set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, NULL, 0,
+                                 IP_NEIGHBOR_FLAG_NONE);
       return 0;
     }
 
@@ -980,8 +968,7 @@ static void ip6_neighbor_set_unset_rpc_callback
   vlib_main_t *vm = vlib_get_main ();
   if (a->is_add)
     vnet_set_ip6_ethernet_neighbor (vm, a->sw_if_index, &a->addr,
-                                   a->link_layer_address, 6, a->is_static,
-                                   a->is_no_fib_entry);
+                                   &a->mac, a->flags);
   else
     vnet_unset_ip6_ethernet_neighbor (vm, a->sw_if_index, &a->addr);
 }
@@ -1010,7 +997,7 @@ ip6_neighbor_t *
 ip6_neighbors_entries (u32 sw_if_index)
 {
   ip6_neighbor_main_t *nm = &ip6_neighbor_main;
-  ip6_neighbor_t *n, *ns = 0;
+  ip6_neighbor_t *n, *ns = NULL;
 
   /* *INDENT-OFF* */
   pool_foreach (n, nm->neighbor_pool,
@@ -1034,6 +1021,10 @@ show_ip6_neighbors (vlib_main_t * vm,
   ip6_neighbor_t *n, *ns;
   clib_error_t *error = 0;
   u32 sw_if_index;
+  int verbose = 0;
+
+  if (unformat (input, "verbose"))
+    verbose = 1;
 
   /* Filter entries by interface if given. */
   sw_if_index = ~0;
@@ -1042,13 +1033,29 @@ show_ip6_neighbors (vlib_main_t * vm,
   ns = ip6_neighbors_entries (sw_if_index);
   if (ns)
     {
-      vlib_cli_output (vm, "%U", format_ip6_neighbor_ip6_entry, vm, 0);
-      vec_foreach (n, ns)
-      {
-       vlib_cli_output (vm, "%U", format_ip6_neighbor_ip6_entry, vm, n);
-      }
+      /*
+       * Show the entire table if it's not too big, otherwise just
+       * show the size of the table.
+       */
+      if (vec_len (ns) < 50)
+       verbose = 1;
+      if (verbose)
+       {
+         vlib_cli_output (vm, "%U", format_ip6_neighbor_ip6_entry, vm, 0);
+         vec_foreach (n, ns)
+         {
+           vlib_cli_output (vm, "%U", format_ip6_neighbor_ip6_entry, vm, n);
+         }
+       }
+      else
+       vlib_cli_output
+         (vm, "There are %u ip6 neighbors, "
+          "'show ip6 neighbors verbose' to display the entire table...",
+          vec_len (ns));
       vec_free (ns);
     }
+  else
+    vlib_cli_output (vm, "No ip6 neighbors");
 
   return error;
 }
@@ -1085,13 +1092,12 @@ static clib_error_t *
 set_ip6_neighbor (vlib_main_t * vm,
                  unformat_input_t * input, vlib_cli_command_t * cmd)
 {
+  ip_neighbor_flags_t flags = IP_NEIGHBOR_FLAG_NONE;
   vnet_main_t *vnm = vnet_get_main ();
   ip6_address_t addr;
-  u8 mac_address[6];
+  mac_address_t mac;
   int addr_valid = 0;
   int is_del = 0;
-  int is_static = 0;
-  int is_no_fib_entry = 0;
   u32 sw_if_index;
 
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
@@ -1100,15 +1106,15 @@ set_ip6_neighbor (vlib_main_t * vm,
       if (unformat (input, "%U %U %U",
                    unformat_vnet_sw_interface, vnm, &sw_if_index,
                    unformat_ip6_address, &addr,
-                   unformat_ethernet_address, mac_address))
+                   unformat_mac_address_t, &mac))
        addr_valid = 1;
 
       else if (unformat (input, "delete") || unformat (input, "del"))
        is_del = 1;
       else if (unformat (input, "static"))
-       is_static = 1;
+       flags |= IP_NEIGHBOR_FLAG_STATIC;
       else if (unformat (input, "no-fib-entry"))
-       is_no_fib_entry = 1;
+       flags |= IP_NEIGHBOR_FLAG_NO_FIB_ENTRY;
       else
        break;
     }
@@ -1117,9 +1123,7 @@ set_ip6_neighbor (vlib_main_t * vm,
     return clib_error_return (0, "Missing interface, ip6 or hw address");
 
   if (!is_del)
-    vnet_set_ip6_ethernet_neighbor (vm, sw_if_index, &addr,
-                                   mac_address, sizeof (mac_address),
-                                   is_static, is_no_fib_entry);
+    vnet_set_ip6_ethernet_neighbor (vm, sw_if_index, &addr, &mac, flags);
   else
     vnet_unset_ip6_ethernet_neighbor (vm, sw_if_index, &addr);
   return 0;
@@ -1258,9 +1262,9 @@ icmp6_neighbor_solicitation_or_advertisement (vlib_main_t * vm,
                                              is_solicitation ?
                                              &ip0->src_address :
                                              &h0->target_address,
+                                             (mac_address_t *)
                                              o0->ethernet_address,
-                                             sizeof (o0->ethernet_address),
-                                             0, 0);
+                                             IP_NEIGHBOR_FLAG_NONE);
            }
 
          if (is_solicitation && error0 == ICMP6_ERROR_NONE)
@@ -1591,11 +1595,11 @@ icmp6_router_solicitation (vlib_main_t * vm,
          if (PREDICT_TRUE (error0 == ICMP6_ERROR_NONE && o0 != 0 &&
                            !is_unspecified && !is_link_local))
            {
-             vnet_set_ip6_ethernet_neighbor (vm, sw_if_index0,
-                                             &ip0->src_address,
-                                             o0->ethernet_address,
-                                             sizeof (o0->ethernet_address),
-                                             0, 0);
+             vnet_set_ip6_ethernet_neighbor
+               (vm, sw_if_index0,
+                &ip0->src_address,
+                (mac_address_t *) o0->ethernet_address,
+                IP_NEIGHBOR_FLAG_NONE);
            }
 
          /* default is to drop */
@@ -1690,11 +1694,14 @@ icmp6_router_solicitation (vlib_main_t * vm,
                      u16 payload_length =
                        sizeof (icmp6_router_advertisement_header_t);
 
-                     vlib_buffer_add_data (vm,
-                                           vlib_buffer_get_free_list_index
-                                           (p0), bi0, (void *) &rh,
-                                           sizeof
-                                           (icmp6_router_advertisement_header_t));
+                     if (vlib_buffer_add_data
+                         (vm, &bi0, (void *) &rh,
+                          sizeof (icmp6_router_advertisement_header_t)))
+                       {
+                         /* buffer allocation failed, drop the pkt */
+                         error0 = ICMP6_ERROR_ALLOC_FAILURE;
+                         goto drop0;
+                       }
 
                      if (radv_info->adv_link_layer_address)
                        {
@@ -1709,11 +1716,14 @@ icmp6_router_solicitation (vlib_main_t * vm,
                          clib_memcpy (&h.ethernet_address[0],
                                       eth_if0->address, 6);
 
-                         vlib_buffer_add_data (vm,
-                                               vlib_buffer_get_free_list_index
-                                               (p0), bi0, (void *) &h,
-                                               sizeof
-                                               (icmp6_neighbor_discovery_ethernet_link_layer_address_option_t));
+                         if (vlib_buffer_add_data
+                             (vm, &bi0, (void *) &h,
+                              sizeof
+                              (icmp6_neighbor_discovery_ethernet_link_layer_address_option_t)))
+                           {
+                             error0 = ICMP6_ERROR_ALLOC_FAILURE;
+                             goto drop0;
+                           }
 
                          payload_length +=
                            sizeof
@@ -1734,11 +1744,14 @@ icmp6_router_solicitation (vlib_main_t * vm,
                          payload_length +=
                            sizeof (icmp6_neighbor_discovery_mtu_option_t);
 
-                         vlib_buffer_add_data (vm,
-                                               vlib_buffer_get_free_list_index
-                                               (p0), bi0, (void *) &h,
-                                               sizeof
-                                               (icmp6_neighbor_discovery_mtu_option_t));
+                         if (vlib_buffer_add_data
+                             (vm, &bi0, (void *) &h,
+                              sizeof
+                              (icmp6_neighbor_discovery_mtu_option_t)))
+                           {
+                             error0 = ICMP6_ERROR_ALLOC_FAILURE;
+                             goto drop0;
+                           }
                        }
 
                      /* add advertised prefix options  */
@@ -1787,10 +1800,13 @@ icmp6_router_solicitation (vlib_main_t * vm,
 
                             payload_length += sizeof( icmp6_neighbor_discovery_prefix_information_option_t);
 
-                            vlib_buffer_add_data (vm,
-                                           vlib_buffer_get_free_list_index (p0),
-                                                  bi0,
-                                                  (void *)&h, sizeof(icmp6_neighbor_discovery_prefix_information_option_t));
+                            if (vlib_buffer_add_data
+                               (vm, &bi0, (void *)&h,
+                                sizeof(icmp6_neighbor_discovery_prefix_information_option_t)))
+                              {
+                                error0 = ICMP6_ERROR_ALLOC_FAILURE;
+                                goto drop0;
+                              }
 
                           }
                       }));
@@ -1875,6 +1891,7 @@ icmp6_router_solicitation (vlib_main_t * vm,
                }
            }
 
+       drop0:
          p0->error = error_node->errors[error0];
 
          if (error0 != ICMP6_ERROR_NONE)
@@ -2000,7 +2017,7 @@ icmp6_router_advertisement (vlib_main_t * vm,
                      ra_report_t r;
 
                      r.sw_if_index = sw_if_index0;
-                     memcpy (r.router_address, &ip0->src_address, 16);
+                     memcpy (&r.router_address, &ip0->src_address, 16);
                      r.current_hop_limit = h0->current_hop_limit;
                      r.flags = h0->flags;
                      r.router_lifetime_in_sec =
@@ -2195,9 +2212,9 @@ icmp6_router_advertisement (vlib_main_t * vm,
                                prefix->preferred_time = preferred;
                                prefix->valid_time = valid;
                                prefix->flags = h->flags & 0xc0;
-                               prefix->dst_address_length =
-                                 h->dst_address_length;
-                               prefix->dst_address = h->dst_address;
+                               prefix->prefix.fp_len = h->dst_address_length;
+                               prefix->prefix.fp_addr.ip6 = h->dst_address;
+                               prefix->prefix.fp_proto = FIB_PROTOCOL_IP6;
 
                                /* look for matching prefix - if we our advertising it, it better be consistant */
                                /* *INDENT-OFF* */
@@ -2294,7 +2311,6 @@ create_buffer_for_rs (vlib_main_t * vm, ip6_radv_t * radv_info)
 {
   u32 bi0;
   vlib_buffer_t *p0;
-  vlib_buffer_free_list_t *fl;
   icmp6_router_solicitation_header_t *rh;
   u16 payload_length;
   int bogus_length;
@@ -2309,8 +2325,6 @@ create_buffer_for_rs (vlib_main_t * vm, ip6_radv_t * radv_info)
     }
 
   p0 = vlib_get_buffer (vm, bi0);
-  fl = vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
-  vlib_buffer_init_for_free_list (p0, fl);
   VLIB_BUFFER_TRACE_TRAJECTORY_INIT (p0);
   p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
 
@@ -2348,7 +2362,7 @@ create_buffer_for_rs (vlib_main_t * vm, ip6_radv_t * radv_info)
   rh->ip.hop_limit = 255;
   rh->ip.src_address = radv_info->link_local_address;
   /* set address ff02::2 */
-  rh->ip.dst_address.as_u64[0] = clib_host_to_net_u64 (0xff02L << 48);
+  rh->ip.dst_address.as_u64[0] = clib_host_to_net_u64 (0xff02ULL << 48);
   rh->ip.dst_address.as_u64[1] = clib_host_to_net_u64 (2);
 
   rh->neighbor.icmp.checksum = ip6_tcp_udp_icmp_compute_checksum (vm, p0,
@@ -2761,6 +2775,7 @@ ip6_neighbor_send_mldpv2_report (u32 sw_if_index)
   n_allocated = vlib_buffer_alloc (vm, &bo0, n_to_alloc);
   if (PREDICT_FALSE (n_allocated == 0))
     {
+    alloc_fail:
       clib_warning ("buffer allocation failure");
       return;
     }
@@ -2827,9 +2842,12 @@ ip6_neighbor_send_mldpv2_report (u32 sw_if_index)
 
     num_addr_records++;
 
-    vlib_buffer_add_data
-      (vm, vlib_buffer_get_free_list_index (b0), bo0,
-       (void *)&rr, sizeof(icmp6_multicast_address_record_t));
+    if(vlib_buffer_add_data (vm, &bo0, (void *)&rr,
+                            sizeof(icmp6_multicast_address_record_t)))
+      {
+        vlib_buffer_free (vm, &bo0, 1);
+        goto alloc_fail;
+      }
 
     payload_length += sizeof( icmp6_multicast_address_record_t);
   }));
@@ -3261,6 +3279,10 @@ ip6_discover_neighbor_inline (vlib_main_t * vm,
            if (!h0)
              continue;
 
+           /* copy the persistent fields from the original */
+           b0 = vlib_get_buffer (vm, bi0);
+           clib_memcpy_fast (b0->opaque2, p0->opaque2, sizeof (p0->opaque2));
+
            /*
             * Build ethernet header.
             * Choose source address based on destination lookup
@@ -3301,7 +3323,6 @@ ip6_discover_neighbor_inline (vlib_main_t * vm,
            ASSERT (bogus_length == 0);
 
            vlib_buffer_copy_trace_flag (vm, p0, bi0);
-           b0 = vlib_get_buffer (vm, bi0);
            vnet_buffer (b0)->sw_if_index[VLIB_TX]
              = vnet_buffer (p0)->sw_if_index[VLIB_TX];
 
@@ -4482,7 +4503,7 @@ ip6_neighbor_add_del_interface_address (ip6_main_t * im,
   ip6_radv_t *radv_info;
   ip6_address_t a;
 
-  /* create solicited node multicast address for this interface adddress */
+  /* create solicited node multicast address for this interface address */
   ip6_set_solicited_node_multicast_address (&a, 0);
 
   a.as_u8[0xd] = address->as_u8[0xd];
@@ -4669,7 +4690,7 @@ vnet_register_ip6_neighbor_resolution_event (vnet_main_t * vnm,
 
 int
 vnet_add_del_ip6_nd_change_event (vnet_main_t * vnm,
-                                 void *data_callback,
+                                 ip6_nd_change_event_cb_t data_callback,
                                  u32 pid,
                                  void *address_arg,
                                  uword node_index,
@@ -4723,9 +4744,8 @@ vnet_add_del_ip6_nd_change_event (vnet_main_t * vnm,
        return VNET_API_ERROR_NO_SUCH_ENTRY;
 
       /* Clients may need to clean up pool entries, too */
-      void (*fp) (u32, u8 *) = data_callback;
-      if (fp)
-       (*fp) (mc->data, 0 /* no new mac addrs */ );
+      if (data_callback)
+       (data_callback) (mc->data, NULL /* no new mac addrs */ , 0, NULL);
 
       /* Remove the entry from the list and delete the entry */
       *p = mc->next_index;
@@ -4747,7 +4767,9 @@ vnet_ip6_nd_term (vlib_main_t * vm,
 {
   ip6_neighbor_main_t *nm = &ip6_neighbor_main;
   icmp6_neighbor_solicitation_or_advertisement_header_t *ndh;
+  mac_address_t mac;
 
+  mac_address_from_bytes (&mac, eth->src_address);
   ndh = ip6_next_header (ip);
   if (ndh->icmp.type != ICMP6_neighbor_solicitation &&
       ndh->icmp.type != ICMP6_neighbor_advertisement)
@@ -4766,7 +4788,7 @@ vnet_ip6_nd_term (vlib_main_t * vm,
       (nm->wc_ip6_nd_publisher_node != (uword) ~ 0
        && !ip6_address_is_link_local_unicast (&ip->src_address)))
     {
-      vnet_nd_wc_publish (sw_if_index, eth->src_address, &ip->src_address);
+      vnet_nd_wc_publish (sw_if_index, &mac, &ip->src_address);
     }
 
   /* Check if MAC entry exsist for solicited target IP */