X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat.c;h=8e20df4e64e41fb83736d76186d2d12b0a8783a8;hp=4803eeb64de217bef8cc2f1e1790538619b130c2;hb=61717cc38;hpb=a73f2d6f53c224668bd6bbea1a980ee4313c794f diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index 4803eeb64de..8e20df4e64e 100755 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -322,6 +323,16 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index, if (snat_is_session_static (s)) return; + ed_bihash_kv_t bihash_key; + clib_memset (&bihash_key, 0, sizeof (bihash_key)); + bihash_key.k.dst_address = s->ext_host_addr.as_u32; + bihash_key.k.dst_port = s->ext_host_port; + bihash_key.k.src_address = s->out2in.addr.as_u32; + bihash_key.k.src_port = s->out2in.port; + bihash_key.k.protocol = s->out2in.protocol; + clib_bihash_add_del_16_8 (&sm->ed_ext_ports, &bihash_key.kv, + 0 /* is_add */ ); + snat_free_outside_address_and_port (sm->addresses, thread_index, &s->out2in); } @@ -447,6 +458,16 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s, if (snat_is_session_static (s)) return; + ed_bihash_kv_t bihash_key; + clib_memset (&bihash_key, 0, sizeof (bihash_key)); + bihash_key.k.dst_address = s->ext_host_addr.as_u32; + bihash_key.k.dst_port = s->ext_host_port; + bihash_key.k.src_address = s->out2in.addr.as_u32; + bihash_key.k.src_port = s->out2in.port; + bihash_key.k.protocol = s->out2in.protocol; + clib_bihash_add_del_16_8 (&sm->ed_ext_ports, &bihash_key.kv, + 0 /* is_add */ ); + // should be called for every dynamic session snat_free_outside_address_and_port (sm->addresses, thread_index, &s->out2in); @@ -490,7 +511,11 @@ nat_user_get_or_create (snat_main_t * sm, ip4_address_t * addr, u32 fib_index, /* add user */ if (clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 1)) - nat_elog_warn ("user_hash keay add failed"); + { + nat_elog_warn ("user_hash key add failed"); + nat44_delete_user_with_no_session (sm, u, thread_index); + return NULL; + } vlib_set_simple_counter (&sm->total_users, thread_index, 0, pool_elts (tsm->users)); @@ -568,6 +593,14 @@ nat_session_alloc_or_recycle (snat_main_t * sm, snat_user_t * u, s->per_user_list_head_index, per_user_translation_list_elt - tsm->list_pool); + dlist_elt_t *global_lru_list_elt; + pool_get (tsm->global_lru_pool, global_lru_list_elt); + global_lru_list_elt->value = s - tsm->sessions; + s->global_lru_index = global_lru_list_elt - tsm->global_lru_pool; + clib_dlist_addtail (tsm->global_lru_pool, tsm->global_lru_head_index, + s->global_lru_index); + s->last_lru_update = now; + s->user_index = u - tsm->users; vlib_set_simple_counter (&sm->total_sessions, thread_index, 0, pool_elts (tsm->sessions)); @@ -582,7 +615,7 @@ snat_session_t * nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index, f64 now) { - snat_session_t *s; + snat_session_t *s = NULL; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; dlist_elt_t *oldest_elt; @@ -608,6 +641,7 @@ nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index, return 0; } + /* first try to reuse an expired session from this ip */ oldest_index = clib_dlist_remove_head (tsm->list_pool, u->sessions_per_user_list_head_index); @@ -615,19 +649,51 @@ nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index, s = pool_elt_at_index (tsm->sessions, oldest_elt->value); sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s); - if (now >= sess_timeout_time) + if (now >= sess_timeout_time || + (s->tcp_close_timestamp && now >= s->tcp_close_timestamp)) { // reuse old session clib_dlist_addtail (tsm->list_pool, u->sessions_per_user_list_head_index, oldest_index); s = nat44_session_reuse_old (sm, u, s, thread_index, now); + s->last_lru_update = now; } else { - // alloc new session clib_dlist_addhead (tsm->list_pool, u->sessions_per_user_list_head_index, oldest_index); - alloc_new: + s = NULL; + } + +alloc_new: + /* try to free an expired session from global LRU list */ + if (!s) + { + oldest_index = clib_dlist_remove_head (tsm->global_lru_pool, + tsm->global_lru_head_index); + if (~0 != oldest_index) + { + oldest_elt = pool_elt_at_index (tsm->global_lru_pool, oldest_index); + s = pool_elt_at_index (tsm->sessions, oldest_elt->value); + + sess_timeout_time = + s->last_heard + (f64) nat44_session_get_timeout (sm, s); + if (now >= sess_timeout_time + || (s->tcp_close_timestamp && now >= s->tcp_close_timestamp)) + { + nat_free_session_data (sm, s, thread_index, 0); + nat44_ed_delete_session (sm, s, thread_index, 0); + } + else + { + clib_dlist_addhead (tsm->global_lru_pool, + tsm->global_lru_head_index, oldest_index); + } + s = NULL; + } + } + if (!s) + { s = nat44_session_alloc_new (tsm, u, now); vlib_set_simple_counter (&sm->total_sessions, thread_index, 0, pool_elts (tsm->sessions)); @@ -696,7 +762,7 @@ snat_add_address (snat_main_t * sm, ip4_address_t * addr, u32 vrf_id, else ap->fib_index = ~0; #define _(N, i, n, s) \ - clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535); \ + clib_memset(ap->busy_##n##_port_refcounts, 0, sizeof(ap->busy_##n##_port_refcounts));\ ap->busy_##n##_ports = 0; \ ap->busy_##n##_ports_per_thread = 0;\ vec_validate_init_empty (ap->busy_##n##_ports_per_thread, tm->n_vlib_mains - 1, 0); @@ -975,9 +1041,9 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, { #define _(N, j, n, s) \ case SNAT_PROTOCOL_##N: \ - if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \ + if (a->busy_##n##_port_refcounts[e_port]) \ return VNET_API_ERROR_INVALID_VALUE; \ - clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \ + ++a->busy_##n##_port_refcounts[e_port]; \ if (e_port > 1024) \ { \ a->busy_##n##_ports++; \ @@ -1159,7 +1225,7 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, { #define _(N, j, n, s) \ case SNAT_PROTOCOL_##N: \ - clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \ + --a->busy_##n##_port_refcounts[e_port]; \ if (e_port > 1024) \ { \ a->busy_##n##_ports--; \ @@ -1338,9 +1404,9 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, { #define _(N, j, n, s) \ case SNAT_PROTOCOL_##N: \ - if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \ + if (a->busy_##n##_port_refcounts[e_port]) \ return VNET_API_ERROR_INVALID_VALUE; \ - clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \ + ++a->busy_##n##_port_refcounts[e_port]; \ if (e_port > 1024) \ { \ a->busy_##n##_ports++; \ @@ -1454,7 +1520,7 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, { #define _(N, j, n, s) \ case SNAT_PROTOCOL_##N: \ - clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \ + --a->busy_##n##_port_refcounts[e_port]; \ if (e_port > 1024) \ { \ a->busy_##n##_ports--; \ @@ -1821,7 +1887,6 @@ snat_del_address (snat_main_t * sm, ip4_address_t addr, u8 delete_sm, } #define _(N, i, n, s) \ - clib_bitmap_free (a->busy_##n##_port_bitmap); \ vec_free (a->busy_##n##_ports_per_thread); foreach_snat_protocol #undef _ @@ -2646,10 +2711,8 @@ snat_free_outside_address_and_port (snat_address_t * addresses, { #define _(N, i, n, s) \ case SNAT_PROTOCOL_##N: \ - ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \ - port_host_byte_order) == 1); \ - clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \ - port_host_byte_order, 0); \ + ASSERT (a->busy_##n##_port_refcounts[port_host_byte_order] >= 1); \ + --a->busy_##n##_port_refcounts[port_host_byte_order]; \ a->busy_##n##_ports--; \ a->busy_##n##_ports_per_thread[thread_index]--; \ break; @@ -2680,9 +2743,9 @@ nat_set_outside_address_and_port (snat_address_t * addresses, { #define _(N, j, n, s) \ case SNAT_PROTOCOL_##N: \ - if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, port_host_byte_order)) \ + if (a->busy_##n##_port_refcounts[port_host_byte_order]) \ return VNET_API_ERROR_INSTANCE_IN_USE; \ - clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, port_host_byte_order, 1); \ + ++a->busy_##n##_port_refcounts[port_host_byte_order]; \ a->busy_##n##_ports_per_thread[thread_index]++; \ a->busy_##n##_ports++; \ return 0; @@ -2897,9 +2960,9 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses, portnum = (port_per_thread * \ snat_thread_index) + \ snat_random_port(1, port_per_thread) + 1024; \ - if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \ + if (a->busy_##n##_port_refcounts[portnum]) \ continue; \ - clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \ + --a->busy_##n##_port_refcounts[portnum]; \ a->busy_##n##_ports_per_thread[thread_index]++; \ a->busy_##n##_ports++; \ k->addr = a->addr; \ @@ -2934,9 +2997,9 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses, portnum = (port_per_thread * \ snat_thread_index) + \ snat_random_port(1, port_per_thread) + 1024; \ - if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \ + if (a->busy_##n##_port_refcounts[portnum]) \ continue; \ - clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \ + ++a->busy_##n##_port_refcounts[portnum]; \ a->busy_##n##_ports_per_thread[thread_index]++; \ a->busy_##n##_ports++; \ k->addr = a->addr; \ @@ -2984,9 +3047,9 @@ nat_alloc_addr_and_port_mape (snat_address_t * addresses, A = snat_random_port(1, pow2_mask(sm->psid_offset)); \ j = snat_random_port(0, pow2_mask(m)); \ portnum = A | (sm->psid << sm->psid_offset) | (j << (16 - m)); \ - if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \ + if (a->busy_##n##_port_refcounts[portnum]) \ continue; \ - clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \ + ++a->busy_##n##_port_refcounts[portnum]; \ a->busy_##n##_ports++; \ k->addr = a->addr; \ k->port = clib_host_to_net_u16 (portnum); \ @@ -3032,9 +3095,9 @@ nat_alloc_addr_and_port_range (snat_address_t * addresses, while (1) \ { \ portnum = snat_random_port(sm->start_port, sm->end_port); \ - if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \ + if (a->busy_##n##_port_refcounts[portnum]) \ continue; \ - clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \ + ++a->busy_##n##_port_refcounts[portnum]; \ a->busy_##n##_ports++; \ k->addr = a->addr; \ k->port = clib_host_to_net_u16 (portnum); \ @@ -3854,18 +3917,18 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) snat_main_per_thread_data_t *tsm; u32 static_mapping_buckets = 1024; - u32 static_mapping_memory_size = 64 << 20; + uword static_mapping_memory_size = 64 << 20; u32 nat64_bib_buckets = 1024; u32 nat64_bib_memory_size = 128 << 20; u32 nat64_st_buckets = 2048; - u32 nat64_st_memory_size = 256 << 20; + uword nat64_st_memory_size = 256 << 20; u32 user_buckets = 128; - u32 user_memory_size = 64 << 20; + uword user_memory_size = 64 << 20; u32 translation_buckets = 1024; - u32 translation_memory_size = 128 << 20; + uword translation_memory_size = 128 << 20; u32 max_translations_per_user = ~0; @@ -4027,8 +4090,8 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) sm->worker_in2out_cb = snat_get_worker_in2out_cb; sm->worker_out2in_cb = snat_get_worker_out2in_cb; - sm->handoff_out2in_index = snat_in2out_node.index; - sm->handoff_in2out_index = snat_out2in_node.index; + sm->handoff_out2in_index = snat_out2in_node.index; + sm->handoff_in2out_index = snat_in2out_node.index; sm->handoff_in2out_output_index = snat_in2out_output_node.index; sm->in2out_node_index = snat_in2out_node.index; @@ -4050,6 +4113,16 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) tsm->cleanup_runs = 0; tsm->cleanup_timeout = 0; + pool_alloc (tsm->sessions, sm->max_translations); + pool_alloc (tsm->list_pool, sm->max_translations); + pool_alloc (tsm->global_lru_pool, sm->max_translations); + + dlist_elt_t *head; + pool_get (tsm->global_lru_pool, head); + tsm->global_lru_head_index = head - tsm->global_lru_pool; + clib_dlist_init (tsm->global_lru_pool, + tsm->global_lru_head_index); + if (sm->endpoint_dependent) { clib_bihash_init_16_8 (&tsm->in2out_ed, "in2out-ed", @@ -4063,6 +4136,9 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) translation_memory_size); clib_bihash_set_kvp_format_fn_16_8 (&tsm->out2in_ed, format_ed_session_kvp); + clib_bihash_init_16_8 + (&sm->ed_ext_ports, "ed-nat-5-tuple-port-overload-hash", + translation_buckets, translation_memory_size); } else {