ip: Protocol Independent IP Neighbors

Type: feature

 - ip-neighbour: generic neighbour handling; APIs, DBs, event handling,
aging
 - arp: ARP protocol implementation
 - ip6-nd; IPv6 neighbor discovery implementation; separate ND,
MLD, RA
 - ip6-link; manage link-local addresses
 - l2-arp-term; events separated from IP neighbours, since they are not
the same.

vnet retains just enough education to perform ND/ARP packet
construction.
arp and ip6-nd to be moved to plugins soon.

Change-Id: I88dedd0006b299344f4c7024a0aa5baa6b9a8bbe
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index 128204f..4cb7608 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -40,7 +40,7 @@
 #include <vnet/vnet.h>
 #include <vnet/ip/ip.h>
 #include <vnet/ip/ip_frag.h>
-#include <vnet/ip/ip6_neighbor.h>
+#include <vnet/ip/ip6_link.h>
 #include <vnet/ethernet/ethernet.h>	/* for ethernet_header_t */
 #include <vnet/srp/srp.h>	/* for srp_hw_interface_class */
 #include <vppinfra/cache.h>
@@ -297,7 +297,7 @@
   clib_error_t *error;
   u32 if_address_index;
   ip6_address_fib_t ip6_af, *addr_fib = 0;
-  ip6_address_t ll_addr;
+  const ip6_address_t *ll_addr;
 
   /* local0 interface doesn't support IP addressing */
   if (sw_if_index == 0)
@@ -317,13 +317,20 @@
 	}
       if (!is_del)
 	{
-	  return ip6_neighbor_set_link_local_address (vm, sw_if_index,
-						      address);
+	  int rv;
+
+	  rv = ip6_set_link_local_address (sw_if_index, address);
+
+	  if (rv)
+	    {
+	      vnm->api_errno = rv;
+	      return clib_error_create ("address not assignable");
+	    }
 	}
       else
 	{
-	  ll_addr = ip6_neighbor_get_link_local_address (sw_if_index);
-	  if (ip6_address_is_equal (&ll_addr, address))
+	  ll_addr = ip6_get_link_local_address (sw_if_index);
+	  if (ip6_address_is_equal (ll_addr, address))
 	    {
 	      vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_DELETABLE;
 	      return clib_error_create ("address not deletable");
@@ -408,6 +415,8 @@
   }
 
   ip6_sw_interface_enable_disable (sw_if_index, !is_del);
+  if (!is_del)
+    ip6_link_enable (sw_if_index);
 
   /* intf addr routes are added/deleted on admin up/down */
   if (vnet_sw_interface_is_admin_up (vnm, sw_if_index))
@@ -428,6 +437,8 @@
       cb->function (im, cb->function_opaque, sw_if_index,
 		    address, address_length, if_address_index, is_del);
   }
+  if (is_del)
+    ip6_link_disable (sw_if_index);
 
 done:
   vec_free (addr_fib);
@@ -620,7 +631,6 @@
       ip6_address_t *address;
       vlib_main_t *vm = vlib_get_main ();
 
-      ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, 0 /* is_add */ );
       vnet_sw_interface_update_unnumbered (sw_if_index, ~0, 0);
       /* *INDENT-OFF* */
       foreach_ip_interface_address (lm6, ia, sw_if_index, 0,
@@ -1564,9 +1574,7 @@
 
 #ifdef CLIB_MARCH_VARIANT
 extern vlib_node_registration_t ip6_local_node;
-
 #else
-
 void
 ip6_register_protocol (u32 protocol, u32 node_index)
 {
@@ -1588,114 +1596,6 @@
   ASSERT (protocol < ARRAY_LEN (lm->local_next_by_ip_protocol));
   lm->local_next_by_ip_protocol[protocol] = IP_LOCAL_NEXT_PUNT;
 }
-
-clib_error_t *
-ip6_probe_neighbor (vlib_main_t * vm, ip6_address_t * dst, u32 sw_if_index,
-		    u8 refresh)
-{
-  vnet_main_t *vnm = vnet_get_main ();
-  ip6_main_t *im = &ip6_main;
-  icmp6_neighbor_solicitation_header_t *h;
-  ip6_address_t *src;
-  ip_interface_address_t *ia;
-  ip_adjacency_t *adj;
-  vnet_hw_interface_t *hi;
-  vnet_sw_interface_t *si;
-  vlib_buffer_t *b;
-  adj_index_t ai;
-  u32 bi = 0;
-  int bogus_length;
-
-  si = vnet_get_sw_interface (vnm, sw_if_index);
-
-  if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
-    {
-      return clib_error_return (0, "%U: interface %U down",
-				format_ip6_address, dst,
-				format_vnet_sw_if_index_name, vnm,
-				sw_if_index);
-    }
-
-  src =
-    ip6_interface_address_matching_destination (im, dst, sw_if_index, &ia);
-  if (!src)
-    {
-      vnm->api_errno = VNET_API_ERROR_NO_MATCHING_INTERFACE;
-      return clib_error_return
-	(0, "no matching interface address for destination %U (interface %U)",
-	 format_ip6_address, dst,
-	 format_vnet_sw_if_index_name, vnm, sw_if_index);
-    }
-
-  h =
-    vlib_packet_template_get_packet (vm,
-				     &im->discover_neighbor_packet_template,
-				     &bi);
-  if (!h)
-    return clib_error_return (0, "ICMP6 NS packet allocation failed");
-
-  hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
-
-  /* Destination address is a solicited node multicast address.  We need to fill in
-     the low 24 bits with low 24 bits of target's address. */
-  h->ip.dst_address.as_u8[13] = dst->as_u8[13];
-  h->ip.dst_address.as_u8[14] = dst->as_u8[14];
-  h->ip.dst_address.as_u8[15] = dst->as_u8[15];
-
-  h->ip.src_address = src[0];
-  h->neighbor.target_address = dst[0];
-
-  if (PREDICT_FALSE (!hi->hw_address))
-    {
-      return clib_error_return (0, "%U: interface %U do not support ip probe",
-				format_ip6_address, dst,
-				format_vnet_sw_if_index_name, vnm,
-				sw_if_index);
-    }
-
-  clib_memcpy_fast (h->link_layer_option.ethernet_address, hi->hw_address,
-		    vec_len (hi->hw_address));
-
-  h->neighbor.icmp.checksum =
-    ip6_tcp_udp_icmp_compute_checksum (vm, 0, &h->ip, &bogus_length);
-  ASSERT (bogus_length == 0);
-
-  b = vlib_get_buffer (vm, bi);
-  vnet_buffer (b)->sw_if_index[VLIB_RX] =
-    vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
-
-  /* Add encapsulation string for software interface (e.g. ethernet header). */
-  ip46_address_t nh = {
-    .ip6 = *dst,
-  };
-
-  ai = adj_nbr_add_or_lock (FIB_PROTOCOL_IP6,
-			    VNET_LINK_IP6, &nh, sw_if_index);
-  adj = adj_get (ai);
-
-  /* Peer has been previously resolved, retrieve glean adj instead */
-  if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE && refresh == 0)
-    {
-      adj_unlock (ai);
-      ai = adj_glean_add_or_lock (FIB_PROTOCOL_IP6,
-				  VNET_LINK_IP6, sw_if_index, &nh);
-      adj = adj_get (ai);
-    }
-
-  vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t));
-  vlib_buffer_advance (b, -adj->rewrite_header.data_bytes);
-
-  {
-    vlib_frame_t *f = vlib_get_frame_to_node (vm, hi->output_node_index);
-    u32 *to_next = vlib_frame_vector_args (f);
-    to_next[0] = bi;
-    f->n_vectors = 1;
-    vlib_put_frame_to_node (vm, hi->output_node_index, f);
-  }
-
-  adj_unlock (ai);
-  return /* no error */ 0;
-}
 #endif
 
 typedef enum
@@ -2852,79 +2752,11 @@
   /* Unless explicitly configured, don't process HBH options */
   im->hbh_enabled = 0;
 
-  {
-    icmp6_neighbor_solicitation_header_t p;
-
-    clib_memset (&p, 0, sizeof (p));
-
-    p.ip.ip_version_traffic_class_and_flow_label =
-      clib_host_to_net_u32 (0x6 << 28);
-    p.ip.payload_length =
-      clib_host_to_net_u16 (sizeof (p) -
-			    STRUCT_OFFSET_OF
-			    (icmp6_neighbor_solicitation_header_t, neighbor));
-    p.ip.protocol = IP_PROTOCOL_ICMP6;
-    p.ip.hop_limit = 255;
-    ip6_set_solicited_node_multicast_address (&p.ip.dst_address, 0);
-
-    p.neighbor.icmp.type = ICMP6_neighbor_solicitation;
-
-    p.link_layer_option.header.type =
-      ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address;
-    p.link_layer_option.header.n_data_u64s =
-      sizeof (p.link_layer_option) / sizeof (u64);
-
-    vlib_packet_template_init (vm,
-			       &im->discover_neighbor_packet_template,
-			       &p, sizeof (p),
-			       /* alloc chunk size */ 8,
-			       "ip6 neighbor discovery");
-  }
-
   return error;
 }
 
 VLIB_INIT_FUNCTION (ip6_lookup_init);
 
-static clib_error_t *
-test_ip6_link_command_fn (vlib_main_t * vm,
-			  unformat_input_t * input, vlib_cli_command_t * cmd)
-{
-  u8 mac[6];
-  ip6_address_t _a, *a = &_a;
-
-  if (unformat (input, "%U", unformat_ethernet_address, mac))
-    {
-      ip6_link_local_address_from_ethernet_mac_address (a, mac);
-      vlib_cli_output (vm, "Link local address: %U", format_ip6_address, a);
-      ip6_ethernet_mac_address_from_link_local_address (mac, a);
-      vlib_cli_output (vm, "Original MAC address: %U",
-		       format_ethernet_address, mac);
-    }
-
-  return 0;
-}
-
-/*?
- * This command converts the given MAC Address into an IPv6 link-local
- * address.
- *
- * @cliexpar
- * Example of how to create an IPv6 link-local address:
- * @cliexstart{test ip6 link 16:d9:e0:91:79:86}
- * Link local address: fe80::14d9:e0ff:fe91:7986
- * Original MAC address: 16:d9:e0:91:79:86
- * @cliexend
-?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (test_link_command, static) =
-{
-  .path = "test ip6 link",
-  .function = test_ip6_link_command_fn,
-  .short_help = "test ip6 link <mac-address>",
-};
-/* *INDENT-ON* */
-
 #ifndef CLIB_MARCH_VARIANT
 int
 vnet_set_ip6_flow_hash (u32 table_id, u32 flow_hash_config)