From 897844d1e96797f69e3e7e11d237d847fe4e46bf Mon Sep 17 00:00:00 2001 From: Nathan Skrzypczak Date: Fri, 4 Jun 2021 18:37:27 +0200 Subject: cnat: add ip/client bihash 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 --- src/plugins/cnat/cnat_client.c | 63 +++++++++++++++++++++++++----------------- src/plugins/cnat/cnat_client.h | 39 ++++++++++---------------- src/plugins/cnat/cnat_types.c | 8 ++++++ src/plugins/cnat/cnat_types.h | 10 ++++++- 4 files changed, 68 insertions(+), 52 deletions(-) diff --git a/src/plugins/cnat/cnat_client.c b/src/plugins/cnat/cnat_client.c index b8fcb9add64..73835b093f0 100644 --- a/src/plugins/cnat/cnat_client.c +++ b/src/plugins/cnat/cnat_client.c @@ -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 = diff --git a/src/plugins/cnat/cnat_client.h b/src/plugins/cnat/cnat_client.h index d6e3631d868..db6933c3b95 100644 --- a/src/plugins/cnat/cnat_client.h +++ b/src/plugins/cnat/cnat_client.h @@ -17,6 +17,7 @@ #define __CNAT_CLIENT_H__ #include +#include /** * 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)); } /** diff --git a/src/plugins/cnat/cnat_types.c b/src/plugins/cnat/cnat_types.c index 9b164c6069d..b09459d8a14 100644 --- a/src/plugins/cnat/cnat_types.c +++ b/src/plugins/cnat/cnat_types.c @@ -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)) diff --git a/src/plugins/cnat/cnat_types.h b/src/plugins/cnat/cnat_types.h index 84fb7d0b3c3..abae83af59a 100644 --- a/src/plugins/cnat/cnat_types.h +++ b/src/plugins/cnat/cnat_types.h @@ -36,12 +36,14 @@ #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; -- cgit 1.2.3-korg