cnat: add ip/client bihash 21/32821/12
authorNathan Skrzypczak <nathan.skrzypczak@gmail.com>
Fri, 4 Jun 2021 16:37:27 +0000 (18:37 +0200)
committerBeno�t Ganne <bganne@cisco.com>
Wed, 9 Aug 2023 07:59:09 +0000 (07:59 +0000)
This replace the cnat ip4/ip6 to client
lookups previously done with a regular
hash, by a bihash lookup.

Type: improvement

Do the client lookup in a bihash instead of
a hash.

Change-Id: I730c1893525c002b44ada8e290a36802835e88e9
Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
src/plugins/cnat/cnat_client.c
src/plugins/cnat/cnat_client.h
src/plugins/cnat/cnat_types.c
src/plugins/cnat/cnat_types.h

index b8fcb9a..73835b0 100644 (file)
@@ -34,10 +34,42 @@ cnat_client_is_clone (cnat_client_t * cc)
 static void
 cnat_client_db_remove (cnat_client_t * cc)
 {
+  clib_bihash_kv_16_8_t bkey;
   if (ip_addr_version (&cc->cc_ip) == AF_IP4)
-    hash_unset (cnat_client_db.crd_cip4, ip_addr_v4 (&cc->cc_ip).as_u32);
+    {
+      bkey.key[0] = ip_addr_v4 (&cc->cc_ip).as_u32;
+      bkey.key[1] = 0;
+    }
   else
-    hash_unset_mem_free (&cnat_client_db.crd_cip6, &ip_addr_v6 (&cc->cc_ip));
+    {
+      bkey.key[0] = ip_addr_v6 (&cc->cc_ip).as_u64[0];
+      bkey.key[1] = ip_addr_v6 (&cc->cc_ip).as_u64[1];
+    }
+
+  clib_bihash_add_del_16_8 (&cnat_client_db.cc_ip_id_hash, &bkey, 0 /* del */);
+}
+
+static void
+cnat_client_db_add (cnat_client_t *cc)
+{
+  index_t cci;
+
+  cci = cc - cnat_client_pool;
+
+  clib_bihash_kv_16_8_t bkey;
+  bkey.value = cci;
+  if (ip_addr_version (&cc->cc_ip) == AF_IP4)
+    {
+      bkey.key[0] = ip_addr_v4 (&cc->cc_ip).as_u32;
+      bkey.key[1] = 0;
+    }
+  else
+    {
+      bkey.key[0] = ip_addr_v6 (&cc->cc_ip).as_u64[0];
+      bkey.key[1] = ip_addr_v6 (&cc->cc_ip).as_u64[1];
+    }
+
+  clib_bihash_add_del_16_8 (&cnat_client_db.cc_ip_id_hash, &bkey, 1 /* add */);
 }
 
 static void
@@ -118,21 +150,6 @@ cnat_client_translation_deleted (index_t cci)
     cnat_client_destroy (cc);
 }
 
-static void
-cnat_client_db_add (cnat_client_t * cc)
-{
-  index_t cci;
-
-  cci = cc - cnat_client_pool;
-
-  if (ip_addr_version (&cc->cc_ip) == AF_IP4)
-    hash_set (cnat_client_db.crd_cip4, ip_addr_v4 (&cc->cc_ip).as_u32, cci);
-  else
-    hash_set_mem_alloc (&cnat_client_db.crd_cip6,
-                       &ip_addr_v6 (&cc->cc_ip), cci);
-}
-
-
 index_t
 cnat_client_add (const ip_address_t * ip, u8 flags)
 {
@@ -228,12 +245,6 @@ int
 cnat_client_purge (void)
 {
   int rv = 0, rrv = 0;
-  if ((rv = hash_elts (cnat_client_db.crd_cip6)))
-    clib_warning ("len(crd_cip6) isnt 0 but %d", rv);
-  rrv |= rv;
-  if ((rv = hash_elts (cnat_client_db.crd_cip4)))
-    clib_warning ("len(crd_cip4) isnt 0 but %d", rv);
-  rrv |= rv;
   if ((rv = pool_elts (cnat_client_pool)))
     clib_warning ("len(cnat_client_pool) isnt 0 but %d", rv);
   rrv |= rv;
@@ -371,12 +382,12 @@ const static dpo_vft_t cnat_client_dpo_vft = {
 static clib_error_t *
 cnat_client_init (vlib_main_t * vm)
 {
+  cnat_main_t *cm = &cnat_main;
   cnat_client_dpo = dpo_register_new_type (&cnat_client_dpo_vft,
                                           cnat_client_dpo_nodes);
 
-  cnat_client_db.crd_cip6 = hash_create_mem (0,
-                                            sizeof (ip6_address_t),
-                                            sizeof (uword));
+  clib_bihash_init_16_8 (&cnat_client_db.cc_ip_id_hash, "CNat client DB",
+                        cm->client_hash_buckets, cm->client_hash_memory);
 
   clib_spinlock_init (&cnat_client_db.throttle_lock);
   cnat_client_db.throttle_mem =
index d6e3631..db6933c 100644 (file)
@@ -17,6 +17,7 @@
 #define __CNAT_CLIENT_H__
 
 #include <cnat/cnat_types.h>
+#include <vppinfra/bihash_16_8.h>
 
 /**
  * A client is a representation of an IP address behind the NAT.
@@ -132,8 +133,7 @@ extern void cnat_client_throttle_pool_process ();
  */
 typedef struct cnat_client_db_t_
 {
-  uword *crd_cip4;
-  uword *crd_cip6;
+  clib_bihash_16_8_t cc_ip_id_hash;
   /* Pool of addresses that have been throttled
      and need to be refcounted before calling
      cnat_client_free_by_ip */
@@ -149,27 +149,15 @@ extern cnat_client_db_t cnat_client_db;
 static_always_inline cnat_client_t *
 cnat_client_ip4_find (const ip4_address_t * ip)
 {
-  uword *p;
+  clib_bihash_kv_16_8_t bkey, bval;
 
-  p = hash_get (cnat_client_db.crd_cip4, ip->as_u32);
+  bkey.key[0] = ip->as_u32;
+  bkey.key[1] = 0;
 
-  if (p)
-    return (pool_elt_at_index (cnat_client_pool, p[0]));
+  if (clib_bihash_search_16_8 (&cnat_client_db.cc_ip_id_hash, &bkey, &bval))
+    return (NULL);
 
-  return (NULL);
-}
-
-static_always_inline u32
-cnat_client_ip4_find_index (const ip4_address_t * ip)
-{
-  uword *p;
-
-  p = hash_get (cnat_client_db.crd_cip4, ip->as_u32);
-
-  if (p)
-    return p[0];
-
-  return -1;
+  return (pool_elt_at_index (cnat_client_pool, bval.value));
 }
 
 /**
@@ -178,14 +166,15 @@ cnat_client_ip4_find_index (const ip4_address_t * ip)
 static_always_inline cnat_client_t *
 cnat_client_ip6_find (const ip6_address_t * ip)
 {
-  uword *p;
+  clib_bihash_kv_16_8_t bkey, bval;
 
-  p = hash_get_mem (cnat_client_db.crd_cip6, ip);
+  bkey.key[0] = ip->as_u64[0];
+  bkey.key[1] = ip->as_u64[1];
 
-  if (p)
-    return (pool_elt_at_index (cnat_client_pool, p[0]));
+  if (clib_bihash_search_16_8 (&cnat_client_db.cc_ip_id_hash, &bkey, &bval))
+    return (NULL);
 
-  return (NULL);
+  return (pool_elt_at_index (cnat_client_pool, bval.value));
 }
 
 /**
index 9b164c6..b09459d 100644 (file)
@@ -191,6 +191,8 @@ cnat_config (vlib_main_t * vm, unformat_input_t * input)
   cm->session_hash_buckets = CNAT_DEFAULT_SESSION_BUCKETS;
   cm->translation_hash_memory = CNAT_DEFAULT_TRANSLATION_MEMORY;
   cm->translation_hash_buckets = CNAT_DEFAULT_TRANSLATION_BUCKETS;
+  cm->client_hash_memory = CNAT_DEFAULT_CLIENT_MEMORY;
+  cm->client_hash_buckets = CNAT_DEFAULT_CLIENT_BUCKETS;
   cm->snat_hash_memory = CNAT_DEFAULT_SNAT_MEMORY;
   cm->snat_hash_buckets = CNAT_DEFAULT_SNAT_BUCKETS;
   cm->snat_if_map_length = CNAT_DEFAULT_SNAT_IF_MAP_LEN;
@@ -215,6 +217,12 @@ cnat_config (vlib_main_t * vm, unformat_input_t * input)
       else if (unformat (input, "translation-db-memory %U",
                         unformat_memory_size, &cm->translation_hash_memory))
        ;
+      else if (unformat (input, "client-db-buckets %u",
+                        &cm->client_hash_buckets))
+       ;
+      else if (unformat (input, "client-db-memory %U", unformat_memory_size,
+                        &cm->client_hash_memory))
+       ;
       else if (unformat (input, "snat-db-buckets %u", &cm->snat_hash_buckets))
        ;
       else if (unformat (input, "snat-if-map-len %u", &cm->snat_if_map_length))
index 84fb7d0..abae83a 100644 (file)
 
 #define CNAT_DEFAULT_SESSION_BUCKETS     1024
 #define CNAT_DEFAULT_TRANSLATION_BUCKETS 1024
+#define CNAT_DEFAULT_CLIENT_BUCKETS     1024
 #define CNAT_DEFAULT_SNAT_BUCKETS        1024
 #define CNAT_DEFAULT_SNAT_IF_MAP_LEN    4096
 
 #define CNAT_DEFAULT_SESSION_MEMORY      (1 << 20)
 #define CNAT_DEFAULT_TRANSLATION_MEMORY  (256 << 10)
-#define CNAT_DEFAULT_SNAT_MEMORY         (64 << 20)
+#define CNAT_DEFAULT_CLIENT_MEMORY      (256 << 10)
+#define CNAT_DEFAULT_SNAT_MEMORY        (64 << 10)
 
 /* Should be prime >~ 100 * numBackends */
 #define CNAT_DEFAULT_MAGLEV_LEN 1009
@@ -120,6 +122,12 @@ typedef struct cnat_main_
   /* Number of buckets of the  translation bihash */
   u32 translation_hash_buckets;
 
+  /* Memory size of the client bihash */
+  uword client_hash_memory;
+
+  /* Number of buckets of the  client bihash */
+  u32 client_hash_buckets;
+
   /* Memory size of the source NAT prefix bihash */
   uword snat_hash_memory;