ipsec: Add to the SA info directly in the bihash

Type: improvement

this save the cache miss on the protect structure.

Signed-off-by: Neale Ranns <nranns@cisco.com>
Change-Id: I867d5e49df5edfd6b368f17a34747f32840080e4
diff --git a/src/vnet/ipsec/ipsec.h b/src/vnet/ipsec/ipsec.h
index fe44b80..97ef626 100644
--- a/src/vnet/ipsec/ipsec.h
+++ b/src/vnet/ipsec/ipsec.h
@@ -26,9 +26,9 @@
 #include <vnet/ipsec/ipsec_spd_policy.h>
 #include <vnet/ipsec/ipsec_sa.h>
 
-#include <vppinfra/bihash_8_8.h>
+#include <vppinfra/bihash_8_16.h>
 
-#include <vppinfra/bihash_24_8.h>
+#include <vppinfra/bihash_24_16.h>
 
 typedef clib_error_t *(*add_del_sa_sess_cb_t) (u32 sa_index, u8 is_add);
 typedef clib_error_t *(*check_support_cb_t) (ipsec_sa_t * sa);
@@ -130,8 +130,8 @@
   uword *ipsec_if_real_dev_by_show_dev;
   uword *ipsec_if_by_sw_if_index;
 
-  clib_bihash_8_8_t tun4_protect_by_key;
-  clib_bihash_24_8_t tun6_protect_by_key;
+  clib_bihash_8_16_t tun4_protect_by_key;
+  clib_bihash_24_16_t tun6_protect_by_key;
 
   /* node indices */
   u32 error_drop_node_index;
diff --git a/src/vnet/ipsec/ipsec_cli.c b/src/vnet/ipsec/ipsec_cli.c
index 7d265f7..d737853 100644
--- a/src/vnet/ipsec/ipsec_cli.c
+++ b/src/vnet/ipsec/ipsec_cli.c
@@ -1040,7 +1040,7 @@
 /* *INDENT-ON* */
 
 static int
-ipsec_tun_protect4_hash_show_one (clib_bihash_kv_8_8_t * kv, void *arg)
+ipsec_tun_protect4_hash_show_one (clib_bihash_kv_8_16_t * kv, void *arg)
 {
   ipsec4_tunnel_kv_t *ikv = (ipsec4_tunnel_kv_t *) kv;
   vlib_main_t *vm = arg;
@@ -1051,7 +1051,7 @@
 }
 
 static int
-ipsec_tun_protect6_hash_show_one (clib_bihash_kv_24_8_t * kv, void *arg)
+ipsec_tun_protect6_hash_show_one (clib_bihash_kv_24_16_t * kv, void *arg)
 {
   ipsec6_tunnel_kv_t *ikv = (ipsec6_tunnel_kv_t *) kv;
   vlib_main_t *vm = arg;
@@ -1071,12 +1071,12 @@
   {
     vlib_cli_output (vm, "IPv4:");
 
-    clib_bihash_foreach_key_value_pair_8_8
+    clib_bihash_foreach_key_value_pair_8_16
       (&im->tun4_protect_by_key, ipsec_tun_protect4_hash_show_one, vm);
 
     vlib_cli_output (vm, "IPv6:");
 
-    clib_bihash_foreach_key_value_pair_24_8
+    clib_bihash_foreach_key_value_pair_24_16
       (&im->tun6_protect_by_key, ipsec_tun_protect6_hash_show_one, vm);
   }
 
diff --git a/src/vnet/ipsec/ipsec_tun.c b/src/vnet/ipsec/ipsec_tun.c
index 4985c54..c4c8fa7 100644
--- a/src/vnet/ipsec/ipsec_tun.c
+++ b/src/vnet/ipsec/ipsec_tun.c
@@ -23,6 +23,12 @@
 #include <vnet/adj/adj_midchain.h>
 #include <vnet/teib/teib.h>
 
+/* instantiate the bihash functions */
+#include <vppinfra/bihash_8_16.h>
+#include <vppinfra/bihash_template.c>
+#include <vppinfra/bihash_24_16.h>
+#include <vppinfra/bihash_template.c>
+
 #define IPSEC_TUN_DEFAULT_HASH_NUM_BUCKETS (64 * 1024)
 #define IPSEC_TUN_DEFAULT_HASH_MEMORY_SIZE 512 << 20
 
@@ -224,6 +230,8 @@
       ipsec_tun_lkup_result_t res = {
         .tun_index = itp - ipsec_tun_protect_pool,
         .sa_index = sai,
+        .flags = itp->itp_flags,
+        .sw_if_index = itp->itp_sw_if_index,
       };
 
       /*
@@ -235,18 +243,18 @@
           ipsec4_tunnel_kv_t key = {
             .value = res,
           };
-          clib_bihash_kv_8_8_t *bkey = (clib_bihash_kv_8_8_t*)&key;
+          clib_bihash_kv_8_16_t *bkey = (clib_bihash_kv_8_16_t*)&key;
 
           ipsec4_tunnel_mk_key(&key, &itp->itp_crypto.dst.ip4,
                                clib_host_to_net_u32 (sa->spi));
 
           if (!im->tun4_protect_by_key.nbuckets)
-              clib_bihash_init_8_8 (&im->tun4_protect_by_key,
+              clib_bihash_init_8_16 (&im->tun4_protect_by_key,
 			"IPSec IPv4 tunnels",
 			IPSEC_TUN_DEFAULT_HASH_NUM_BUCKETS,
 			IPSEC_TUN_DEFAULT_HASH_MEMORY_SIZE);
 
-          clib_bihash_add_del_8_8 (&im->tun4_protect_by_key, bkey, 1);
+          clib_bihash_add_del_8_16 (&im->tun4_protect_by_key, bkey, 1);
           ipsec_tun_register_nodes(AF_IP4);
         }
       else
@@ -258,14 +266,14 @@
             },
             .value = res,
           };
-          clib_bihash_kv_24_8_t *bkey = (clib_bihash_kv_24_8_t*)&key;
+          clib_bihash_kv_24_16_t *bkey = (clib_bihash_kv_24_16_t*)&key;
 
           if (!im->tun4_protect_by_key.nbuckets)
-            clib_bihash_init_24_8 (&im->tun6_protect_by_key,
+            clib_bihash_init_24_16 (&im->tun6_protect_by_key,
                                    "IPSec IPv6 tunnels",
                                    IPSEC_TUN_DEFAULT_HASH_NUM_BUCKETS,
                                    IPSEC_TUN_DEFAULT_HASH_MEMORY_SIZE);
-          clib_bihash_add_del_24_8 (&im->tun6_protect_by_key, bkey, 1);
+          clib_bihash_add_del_24_16 (&im->tun6_protect_by_key, bkey, 1);
           ipsec_tun_register_nodes(AF_IP6);
         }
   }))
@@ -355,14 +363,14 @@
     if (ip46_address_is_ip4 (&itp->itp_crypto.dst))
       {
           ipsec4_tunnel_kv_t key;
-          clib_bihash_kv_8_8_t res, *bkey = (clib_bihash_kv_8_8_t*)&key;
+          clib_bihash_kv_8_16_t res, *bkey = (clib_bihash_kv_8_16_t*)&key;
 
           ipsec4_tunnel_mk_key(&key, &itp->itp_crypto.dst.ip4,
                                clib_host_to_net_u32 (sa->spi));
 
-          if (!clib_bihash_search_8_8 (&im->tun4_protect_by_key, bkey, &res))
+          if (!clib_bihash_search_8_16 (&im->tun4_protect_by_key, bkey, &res))
             {
-              clib_bihash_add_del_8_8 (&im->tun4_protect_by_key, bkey, 0);
+              clib_bihash_add_del_8_16 (&im->tun4_protect_by_key, bkey, 0);
               ipsec_tun_unregister_nodes(AF_IP4);
             }
       }
@@ -374,11 +382,11 @@
             .spi = clib_host_to_net_u32 (sa->spi),
           },
         };
-        clib_bihash_kv_24_8_t res, *bkey = (clib_bihash_kv_24_8_t*)&key;
+        clib_bihash_kv_24_16_t res, *bkey = (clib_bihash_kv_24_16_t*)&key;
 
-        if (!clib_bihash_search_24_8 (&im->tun6_protect_by_key, bkey, &res))
+        if (!clib_bihash_search_24_16 (&im->tun6_protect_by_key, bkey, &res))
           {
-            clib_bihash_add_del_24_8 (&im->tun6_protect_by_key, bkey, 0);
+            clib_bihash_add_del_24_16 (&im->tun6_protect_by_key, bkey, 0);
             ipsec_tun_unregister_nodes(AF_IP6);
           }
       }
@@ -971,11 +979,11 @@
   im = &ipsec_main;
 
   if (AF_IP4 == af)
-    clib_bihash_init_8_8 (&im->tun4_protect_by_key,
-			  "IPSec IPv4 tunnels", n_buckets, table_size);
+    clib_bihash_init_8_16 (&im->tun4_protect_by_key,
+			   "IPSec IPv4 tunnels", n_buckets, table_size);
   else
-    clib_bihash_init_24_8 (&im->tun6_protect_by_key,
-			   "IPSec IPv6 tunnels", n_buckets, table_size);
+    clib_bihash_init_24_16 (&im->tun6_protect_by_key,
+			    "IPSec IPv6 tunnels", n_buckets, table_size);
 }
 
 clib_error_t *
@@ -984,14 +992,14 @@
   ipsec_main_t *im;
 
   im = &ipsec_main;
-  clib_bihash_init_24_8 (&im->tun6_protect_by_key,
-			 "IPSec IPv6 tunnels",
+  clib_bihash_init_24_16 (&im->tun6_protect_by_key,
+			  "IPSec IPv6 tunnels",
+			  IPSEC_TUN_DEFAULT_HASH_NUM_BUCKETS,
+			  IPSEC_TUN_DEFAULT_HASH_MEMORY_SIZE);
+  clib_bihash_init_8_16 (&im->tun4_protect_by_key,
+			 "IPSec IPv4 tunnels",
 			 IPSEC_TUN_DEFAULT_HASH_NUM_BUCKETS,
 			 IPSEC_TUN_DEFAULT_HASH_MEMORY_SIZE);
-  clib_bihash_init_8_8 (&im->tun4_protect_by_key,
-			"IPSec IPv4 tunnels",
-			IPSEC_TUN_DEFAULT_HASH_NUM_BUCKETS,
-			IPSEC_TUN_DEFAULT_HASH_MEMORY_SIZE);
 
   /* set up feature nodes to drop outbound packets with no crypto alg set */
   im->esp4_no_crypto_tun_node_index =
diff --git a/src/vnet/ipsec/ipsec_tun.h b/src/vnet/ipsec/ipsec_tun.h
index 0d911a2..b8e80d3 100644
--- a/src/vnet/ipsec/ipsec_tun.h
+++ b/src/vnet/ipsec/ipsec_tun.h
@@ -17,20 +17,31 @@
 
 #include <vnet/ipsec/ipsec.h>
 
+#define foreach_ipsec_protect_flags \
+  _(L2, 1, "l2")                    \
+  _(ENCAPED, 2, "encapped")         \
+  _(ITF, 4, "itf")                  \
+
+typedef enum ipsec_protect_flags_t_
+{
+  IPSEC_PROTECT_NONE = 0,
+#define _(a,b,c) IPSEC_PROTECT_##a = b,
+  foreach_ipsec_protect_flags
+#undef _
+} __clib_packed ipsec_protect_flags_t;
+
+extern u8 *format_ipsec_tun_protect_flags (u8 * s, va_list * args);
+
 /**
  * result of a lookup in the protection bihash
  */
 typedef struct ipsec_tun_lkup_result_t_
 {
-  union
-  {
-    struct
-    {
-      u32 tun_index;
-      u32 sa_index;
-    };
-    u64 as_u64;
-  };
+  u32 tun_index;
+  u32 sa_index;
+  u32 sw_if_index;
+  ipsec_protect_flags_t flags;
+  u8 __pad[3];
 } ipsec_tun_lkup_result_t;
 
 typedef struct ipsec4_tunnel_kv_t
@@ -43,9 +54,9 @@
   ipsec_tun_lkup_result_t value;
 } __clib_packed ipsec4_tunnel_kv_t;
 
-STATIC_ASSERT_SIZEOF (ipsec4_tunnel_kv_t, sizeof (clib_bihash_kv_8_8_t));
+STATIC_ASSERT_SIZEOF (ipsec4_tunnel_kv_t, sizeof (clib_bihash_kv_8_16_t));
 STATIC_ASSERT_OFFSET_OF (ipsec4_tunnel_kv_t, value,
-			 STRUCT_OFFSET_OF (clib_bihash_kv_8_8_t, value));
+			 STRUCT_OFFSET_OF (clib_bihash_kv_8_16_t, value));
 
 static inline void
 ipsec4_tunnel_mk_key (ipsec4_tunnel_kv_t * k,
@@ -77,28 +88,13 @@
   ipsec_tun_lkup_result_t value;
 } __clib_packed ipsec6_tunnel_kv_t;
 
-STATIC_ASSERT_SIZEOF (ipsec6_tunnel_kv_t, sizeof (clib_bihash_kv_24_8_t));
+STATIC_ASSERT_SIZEOF (ipsec6_tunnel_kv_t, sizeof (clib_bihash_kv_24_16_t));
 STATIC_ASSERT_OFFSET_OF (ipsec6_tunnel_kv_t, value,
-			 STRUCT_OFFSET_OF (clib_bihash_kv_24_8_t, value));
+			 STRUCT_OFFSET_OF (clib_bihash_kv_24_16_t, value));
 
 extern u8 *format_ipsec4_tunnel_kv (u8 * s, va_list * args);
 extern u8 *format_ipsec6_tunnel_kv (u8 * s, va_list * args);
 
-#define foreach_ipsec_protect_flags \
-  _(L2, 1, "l2")                    \
-  _(ENCAPED, 2, "encapped")         \
-  _(ITF, 4, "itf")                  \
-
-typedef enum ipsec_protect_flags_t_
-{
-  IPSEC_PROTECT_NONE = 0,
-#define _(a,b,c) IPSEC_PROTECT_##a = b,
-  foreach_ipsec_protect_flags
-#undef _
-} __clib_packed ipsec_protect_flags_t;
-
-extern u8 *format_ipsec_tun_protect_flags (u8 * s, va_list * args);
-
 typedef struct ipsec_ep_t_
 {
   ip46_address_t src;
diff --git a/src/vnet/ipsec/ipsec_tun_in.c b/src/vnet/ipsec/ipsec_tun_in.c
index 804c729..6b7abce 100644
--- a/src/vnet/ipsec/ipsec_tun_in.c
+++ b/src/vnet/ipsec/ipsec_tun_in.c
@@ -149,10 +149,10 @@
   };
   ipsec4_tunnel_kv_t last_key4;
   ipsec6_tunnel_kv_t last_key6;
+  ipsec_tun_lkup_result_t itr0;
 
   vlib_combined_counter_main_t *rx_counter;
   vlib_combined_counter_main_t *drop_counter;
-  ipsec_tun_protect_t *itp0;
 
   if (is_ip6)
     clib_memset (&last_key6, 0xff, sizeof (last_key6));
@@ -165,9 +165,8 @@
   while (n_left_from > 0)
     {
       u32 sw_if_index0, len0, hdr_sz0;
-      ipsec_tun_lkup_result_t itr0;
-      clib_bihash_kv_24_8_t bkey60;
-      clib_bihash_kv_8_8_t bkey40;
+      clib_bihash_kv_24_16_t bkey60;
+      clib_bihash_kv_8_16_t bkey40;
       ipsec4_tunnel_kv_t *key40;
       ipsec6_tunnel_kv_t *key60;
       ip4_header_t *ip40;
@@ -231,17 +230,18 @@
 
 	  if (memcmp (key60, &last_key6, sizeof (last_key6)) == 0)
 	    {
-	      itr0 = last_result;
+	      clib_memcpy_fast (&itr0, &last_result, sizeof (itr0));
 	    }
 	  else
 	    {
 	      int rv =
-		clib_bihash_search_inline_24_8 (&im->tun6_protect_by_key,
-						&bkey60);
+		clib_bihash_search_inline_24_16 (&im->tun6_protect_by_key,
+						 &bkey60);
 	      if (!rv)
 		{
-		  itr0.as_u64 = bkey60.value;
-		  last_result = itr0;
+		  clib_memcpy_fast (&itr0, &bkey60.value, sizeof (itr0));
+		  clib_memcpy_fast (&last_result, &bkey60.value,
+				    sizeof (last_result));
 		  clib_memcpy_fast (&last_key6, key60, sizeof (last_key6));
 		}
 	      else
@@ -258,17 +258,18 @@
 
 	  if (key40->key == last_key4.key)
 	    {
-	      itr0 = last_result;
+	      clib_memcpy_fast (&itr0, &last_result, sizeof (itr0));
 	    }
 	  else
 	    {
 	      int rv =
-		clib_bihash_search_inline_8_8 (&im->tun4_protect_by_key,
-					       &bkey40);
+		clib_bihash_search_inline_8_16 (&im->tun4_protect_by_key,
+						&bkey40);
 	      if (!rv)
 		{
-		  itr0.as_u64 = bkey40.value;
-		  last_result = itr0;
+		  clib_memcpy_fast (&itr0, &bkey40.value, sizeof (itr0));
+		  clib_memcpy_fast (&last_result, &bkey40.value,
+				    sizeof (last_result));
 		  last_key4.key = key40->key;
 		}
 	      else
@@ -281,11 +282,10 @@
 	    }
 	}
 
-      itp0 = pool_elt_at_index (ipsec_tun_protect_pool, itr0.tun_index);
       vnet_buffer (b[0])->ipsec.sad_index = itr0.sa_index;
       vnet_buffer (b[0])->ipsec.protect_index = itr0.tun_index;
 
-      sw_if_index0 = itp0->itp_sw_if_index;
+      sw_if_index0 = itr0.sw_if_index;
       vnet_buffer (b[0])->sw_if_index[VLIB_RX] = sw_if_index0;
 
       if (PREDICT_FALSE (!vnet_sw_interface_is_admin_up (vnm, sw_if_index0)))
@@ -306,7 +306,7 @@
 	    }
 	  else
 	    {
-	      if (n_packets && !(itp0->itp_flags & IPSEC_PROTECT_ENCAPED))
+	      if (n_packets && !(itr0.flags & IPSEC_PROTECT_ENCAPED))
 		{
 		  vlib_increment_combined_counter
 		    (rx_counter, thread_index, last_sw_if_index,
@@ -344,12 +344,10 @@
       n_left_from -= 1;
     }
 
-  if (n_packets && !(itp0->itp_flags & IPSEC_PROTECT_ENCAPED))
-    {
-      vlib_increment_combined_counter (rx_counter,
-				       thread_index,
-				       last_sw_if_index, n_packets, n_bytes);
-    }
+  if (n_packets && !(itr0.flags & IPSEC_PROTECT_ENCAPED))
+    vlib_increment_combined_counter (rx_counter,
+				     thread_index,
+				     last_sw_if_index, n_packets, n_bytes);
 
   vlib_node_increment_counter (vm, node->node_index,
 			       IPSEC_TUN_PROTECT_INPUT_ERROR_RX,
diff --git a/src/vppinfra/bihash_24_16.h b/src/vppinfra/bihash_24_16.h
new file mode 100644
index 0000000..4e979b4
--- /dev/null
+++ b/src/vppinfra/bihash_24_16.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#undef BIHASH_TYPE
+#undef BIHASH_KVP_PER_PAGE
+#undef BIHASH_32_64_SVM
+#undef BIHASH_ENABLE_STATS
+#undef BIHASH_KVP_AT_BUCKET_LEVEL
+#undef BIHASH_LAZY_INSTANTIATE
+#undef BIHASH_BUCKET_PREFETCH_CACHE_LINES
+#undef BIHASH_USE_HEAP
+
+#define BIHASH_TYPE _24_16
+#define BIHASH_KVP_PER_PAGE 4
+#define BIHASH_KVP_AT_BUCKET_LEVEL 0
+#define BIHASH_LAZY_INSTANTIATE 1
+#define BIHASH_BUCKET_PREFETCH_CACHE_LINES 1
+#define BIHASH_USE_HEAP 1
+
+#ifndef __included_bihash_24_16_h__
+#define __included_bihash_24_16_h__
+
+#include <vppinfra/crc32.h>
+#include <vppinfra/heap.h>
+#include <vppinfra/format.h>
+#include <vppinfra/pool.h>
+#include <vppinfra/xxhash.h>
+
+typedef struct
+{
+  u64 key[3];
+  u64 value[2];
+} clib_bihash_kv_24_16_t;
+
+static inline int
+clib_bihash_is_free_24_16 (const clib_bihash_kv_24_16_t * v)
+{
+  /* Free values are clib_memset to 0xff, check a bit... */
+  if (v->key[0] == ~0ULL && v->value[0] == ~0ULL && v->value[1] == ~0ULL)
+    return 1;
+  return 0;
+}
+
+static inline u64
+clib_bihash_hash_24_16 (const clib_bihash_kv_24_16_t * v)
+{
+#ifdef clib_crc32c_uses_intrinsics
+  return clib_crc32c ((u8 *) v->key, 24);
+#else
+  u64 tmp = v->key[0] ^ v->key[1] ^ v->key[2];
+  return clib_xxhash (tmp);
+#endif
+}
+
+static inline u8 *
+format_bihash_kvp_24_16 (u8 * s, va_list * args)
+{
+  clib_bihash_kv_24_16_t *v = va_arg (*args, clib_bihash_kv_24_16_t *);
+
+  s = format (s, "key %llu %llu %llu value %llu %llu",
+	      v->key[0], v->key[1], v->key[2], v->value[0], v->value[1]);
+  return s;
+}
+
+static inline int
+clib_bihash_key_compare_24_16 (u64 * a, u64 * b)
+{
+#if defined (CLIB_HAVE_VEC512)
+  u64x8 v = u64x8_load_unaligned (a) ^ u64x8_load_unaligned (b);
+  return (u64x8_is_zero_mask (v) & 0x7) == 0;
+#elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
+  u64x2 v = { a[2] ^ b[2], 0 };
+  v |= u64x2_load_unaligned (a) ^ u64x2_load_unaligned (b);
+  return u64x2_is_all_zero (v);
+#else
+  return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0;
+#endif
+}
+
+#undef __included_bihash_template_h__
+#include <vppinfra/bihash_template.h>
+
+#endif /* __included_bihash_24_16_h__ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/vppinfra/bihash_8_16.h b/src/vppinfra/bihash_8_16.h
new file mode 100644
index 0000000..b42b32c
--- /dev/null
+++ b/src/vppinfra/bihash_8_16.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2015 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#undef BIHASH_TYPE
+#undef BIHASH_KVP_PER_PAGE
+#undef BIHASH_32_64_SVM
+#undef BIHASH_ENABLE_STATS
+#undef BIHASH_KVP_AT_BUCKET_LEVEL
+#undef BIHASH_LAZY_INSTANTIATE
+#undef BIHASH_BUCKET_PREFETCH_CACHE_LINES
+#undef BIHASH_USE_HEAP
+
+#define BIHASH_TYPE _8_16
+#define BIHASH_KVP_PER_PAGE 7
+#define BIHASH_KVP_AT_BUCKET_LEVEL 1
+#define BIHASH_LAZY_INSTANTIATE 0
+#define BIHASH_BUCKET_PREFETCH_CACHE_LINES 2
+#define BIHASH_USE_HEAP 1
+
+#ifndef __included_bihash_8_16_h__
+#define __included_bihash_8_16_h__
+
+#include <vppinfra/heap.h>
+#include <vppinfra/format.h>
+#include <vppinfra/pool.h>
+#include <vppinfra/xxhash.h>
+#include <vppinfra/crc32.h>
+
+/** 8 octet key, 8 octet key value pair */
+typedef struct
+{
+  u64 key;			/**< the key */
+  u64 value[2];			/**< the value */
+} clib_bihash_kv_8_16_t;
+
+/** Decide if a clib_bihash_kv_8_16_t instance is free
+    @param v- pointer to the (key,value) pair
+*/
+static inline int
+clib_bihash_is_free_8_16 (clib_bihash_kv_8_16_t * v)
+{
+  if (v->key == ~0ULL && v->value[0] == ~0ULL && v->value[1] == ~0ULL)
+    return 1;
+  return 0;
+}
+
+/** Hash a clib_bihash_kv_8_16_t instance
+    @param v - pointer to the (key,value) pair, hash the key (only)
+*/
+static inline u64
+clib_bihash_hash_8_16 (clib_bihash_kv_8_16_t * v)
+{
+  /* Note: to torture-test linear scan, make this fn return a constant */
+#ifdef clib_crc32c_uses_intrinsics
+  return clib_crc32c ((u8 *) & v->key, 8);
+#else
+  return clib_xxhash (v->key);
+#endif
+}
+
+/** Format a clib_bihash_kv_8_16_t instance
+    @param s - u8 * vector under construction
+    @param args (vararg) - the (key,value) pair to format
+    @return s - the u8 * vector under construction
+*/
+static inline u8 *
+format_bihash_kvp_8_16 (u8 * s, va_list * args)
+{
+  clib_bihash_kv_8_16_t *v = va_arg (*args, clib_bihash_kv_8_16_t *);
+
+  s =
+    format (s, "key %llu value [%ll,%llx]u", v->key, v->value[0],
+	    v->value[1]);
+  return s;
+}
+
+/** Compare two clib_bihash_kv_8_16_t instances
+    @param a - first key
+    @param b - second key
+*/
+static inline int
+clib_bihash_key_compare_8_16 (u64 a, u64 b)
+{
+  return a == b;
+}
+
+#undef __included_bihash_template_h__
+#include <vppinfra/bihash_template.h>
+
+#endif /* __included_bihash_8_16_h__ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */