diff options
Diffstat (limited to 'src/plugins/nat/nat.c')
-rw-r--r-- | src/plugins/nat/nat.c | 96 |
1 files changed, 78 insertions, 18 deletions
diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index ed01bb4df80..36d03a620d4 100644 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -338,7 +338,7 @@ nat44_set_session_limit (u32 session_limit, u32 vrf_id) vec_validate (sm->max_translations_per_fib, fib_index + 1); for (; len < vec_len (sm->max_translations_per_fib); len++) - sm->max_translations_per_fib[len] = sm->max_translations; + sm->max_translations_per_fib[len] = sm->max_translations_per_thread; } sm->max_translations_per_fib[fib_index] = session_limit; @@ -485,6 +485,13 @@ nat_user_get_or_create (snat_main_t * sm, ip4_address_t * addr, u32 fib_index, /* Ever heard of the "user" = src ip4 address before? */ if (clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value)) { + if (pool_elts (tsm->users) >= sm->max_users_per_thread) + { + vlib_increment_simple_counter (&sm->user_limit_reached, + thread_index, 0, 1); + nat_elog_warn ("maximum user limit reached"); + return NULL; + } /* no, make a new one */ pool_get (tsm->users, u); clib_memset (u, 0, sizeof (*u)); @@ -2578,6 +2585,10 @@ snat_init (vlib_main_t * vm) sm->total_sessions.stat_segment_name = "/nat44/total-sessions"; vlib_validate_simple_counter (&sm->total_sessions, 0); vlib_zero_simple_counter (&sm->total_sessions, 0); + sm->user_limit_reached.name = "user-limit-reached"; + sm->user_limit_reached.stat_segment_name = "/nat44/user-limit-reached"; + vlib_validate_simple_counter (&sm->user_limit_reached, 0); + vlib_zero_simple_counter (&sm->user_limit_reached, 0); /* Init IPFIX logging */ snat_ipfix_logging_init (vm); @@ -3780,13 +3791,25 @@ nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port, s->total_bytes = total_bytes; } +static u32 +nat_calc_bihash_buckets (u32 n_elts) +{ + return 1 << (max_log2 (n_elts >> 1) + 1); +} + +static u32 +nat_calc_bihash_memory (u32 n_buckets, uword kv_size) +{ + return n_buckets * (8 + kv_size * 4); +} + void nat44_db_init (snat_main_per_thread_data_t * tsm) { snat_main_t *sm = &snat_main; - pool_alloc (tsm->sessions, sm->max_translations); - pool_alloc (tsm->lru_pool, sm->max_translations); + pool_alloc (tsm->sessions, sm->max_translations_per_thread); + pool_alloc (tsm->lru_pool, sm->max_translations_per_thread); dlist_elt_t *head; @@ -3831,7 +3854,7 @@ nat44_db_init (snat_main_per_thread_data_t * tsm) } // TODO: resolve static mappings (put only to !ED) - pool_alloc (tsm->list_pool, sm->max_translations); + pool_alloc (tsm->list_pool, sm->max_translations_per_thread); clib_bihash_init_8_8 (&tsm->user_hash, "users", sm->user_buckets, sm->user_memory_size); clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash, format_user_kvp); @@ -3910,10 +3933,10 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) u32 nat64_st_buckets = 2048; uword nat64_st_memory_size = 256 << 20; - u32 user_buckets = 128; - uword user_memory_size = 64 << 20; - u32 translation_buckets = 1024; - uword translation_memory_size = 128 << 20; + u32 max_users_per_thread = 0; + u32 user_memory_size = 0; + u32 max_translations_per_thread = 0; + u32 translation_memory_size = 0; u32 max_translations_per_user = ~0; @@ -3935,7 +3958,8 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat - (input, "translation hash buckets %d", &translation_buckets)) + (input, "max translations per thread %d", + &max_translations_per_thread)) ; else if (unformat (input, "udp timeout %d", &udp_timeout)) ; @@ -3947,7 +3971,9 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) &tcp_established_timeout)); else if (unformat (input, "translation hash memory %d", &translation_memory_size)); - else if (unformat (input, "user hash buckets %d", &user_buckets)) + else + if (unformat + (input, "max users per thread %d", &max_users_per_thread)) ; else if (unformat (input, "user hash memory %d", &user_memory_size)) ; @@ -4000,6 +4026,17 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) if (sm->out2in_dpo && (sm->deterministic || sm->endpoint_dependent)) return clib_error_return (0, "out2in dpo mode available only for simple nat"); + if (sm->endpoint_dependent && max_users_per_thread > 0) + { + return clib_error_return (0, + "setting 'max users' in endpoint-dependent mode is not supported"); + } + + if (sm->endpoint_dependent && max_translations_per_user != ~0) + { + return clib_error_return (0, + "setting 'max translations per user' in endpoint-dependent mode is not supported"); + } /* optionally configurable timeouts for testing purposes */ sm->udp_timeout = udp_timeout; @@ -4007,17 +4044,40 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) sm->tcp_established_timeout = tcp_established_timeout; sm->icmp_timeout = icmp_timeout; - sm->user_buckets = user_buckets; - sm->user_memory_size = user_memory_size; + if (0 == max_users_per_thread) + { + max_users_per_thread = 1024; + } + sm->max_users_per_thread = max_users_per_thread; + sm->user_buckets = nat_calc_bihash_buckets (sm->max_users_per_thread); - sm->translation_buckets = translation_buckets; + if (0 == max_translations_per_thread) + { + // default value based on legacy setting of load factor 10 * default + // translation buckets 1024 + max_translations_per_thread = 10 * 1024; + } + sm->max_translations_per_thread = max_translations_per_thread; + sm->translation_buckets = + nat_calc_bihash_buckets (sm->max_translations_per_thread); + if (0 == translation_memory_size) + { + translation_memory_size = + nat_calc_bihash_memory (sm->translation_buckets, + sizeof (clib_bihash_16_8_t)); + } sm->translation_memory_size = translation_memory_size; - /* do not exceed load factor 10 */ - sm->max_translations = 10 * translation_buckets; - vec_add1 (sm->max_translations_per_fib, sm->max_translations); + if (0 == user_memory_size) + { + user_memory_size = + nat_calc_bihash_memory (sm->max_users_per_thread, + sizeof (clib_bihash_8_8_t)); + } + sm->user_memory_size = user_memory_size; + vec_add1 (sm->max_translations_per_fib, sm->max_translations_per_thread); sm->max_translations_per_user = max_translations_per_user == ~0 ? - sm->max_translations : max_translations_per_user; + sm->max_translations_per_thread : max_translations_per_user; sm->outside_vrf_id = outside_vrf_id; sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, @@ -4062,7 +4122,7 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) nat_ha_init (vm, nat_ha_sadd_ed_cb, nat_ha_sdel_ed_cb, nat_ha_sref_ed_cb); clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed", - translation_buckets, + sm->translation_buckets, translation_memory_size); clib_bihash_set_kvp_format_fn_16_8 (&sm->out2in_ed, format_ed_session_kvp); |