IPSEC: no second lookup after tunnel encap

in the same maaner as with other tunnel tyeps we use
the FIB to cache and track the destination used to reach
the tunnel endpoint. Post encap we can then ship the packet
straight to this adjacency and thus elide the costly second
lookup.

- SA add and del function so they can be used both directly
  from the API and for tunnels.
- API change for the SA dump to use the SA type
- ipsec_key_t type for convenience (copying, [un]formating)
- no matching tunnel counters in ipsec-if-input

Change-Id: I9d144a59667f7bf96442f4ca66bef5c1d3c7f1ea
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/ipsec/ipsec_if_in.c b/src/vnet/ipsec/ipsec_if_in.c
index 1dbd127..833f848 100644
--- a/src/vnet/ipsec/ipsec_if_in.c
+++ b/src/vnet/ipsec/ipsec_if_in.c
@@ -25,7 +25,8 @@
 /* Statistics (not really errors) */
 #define foreach_ipsec_if_input_error				  \
 _(RX, "good packets received")					  \
-_(DISABLED, "ipsec packets received on disabled interface")
+_(DISABLED, "ipsec packets received on disabled interface")       \
+_(NO_TUNNEL, "no matching tunnel")
 
 static char *ipsec_if_input_error_strings[] = {
 #define _(sym,string) string,
@@ -76,7 +77,7 @@
   ipsec_sa_t *sa0;
   vlib_combined_counter_main_t *rx_counter;
   vlib_combined_counter_main_t *drop_counter;
-  u32 n_disabled = 0;
+  u32 n_disabled = 0, n_no_tunnel = 0;
 
   rx_counter = vim->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX;
   drop_counter = vim->combined_sw_if_counters + VNET_INTERFACE_COUNTER_DROP;
@@ -181,6 +182,11 @@
 	      vlib_buffer_advance (b0, ip4_header_bytes (ip0));
 	      next0 = im->esp4_decrypt_next_index;
 	    }
+	  else
+	    {
+	      b0->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL];
+	      n_no_tunnel++;
+	    }
 
 	trace:
 	  if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
@@ -216,6 +222,8 @@
 
   vlib_node_increment_counter (vm, ipsec_if_input_node.index,
 			       IPSEC_IF_INPUT_ERROR_DISABLED, n_disabled);
+  vlib_node_increment_counter (vm, ipsec_if_input_node.index,
+			       IPSEC_IF_INPUT_ERROR_DISABLED, n_no_tunnel);
 
   return from_frame->n_vectors;
 }