X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat44%2Finlines.h;h=631c4cd4104f04f59f145e20e7c33a1150c563d7;hb=ba5f9bc7534bcf58225b0658993728b1f4d47a67;hp=0c8487b473d08452cbff081390f289b57892ada8;hpb=98301bd5603ce691d809759ec444641953cb5caa;p=vpp.git diff --git a/src/plugins/nat/nat44/inlines.h b/src/plugins/nat/nat44/inlines.h index 0c8487b473d..631c4cd4104 100644 --- a/src/plugins/nat/nat44/inlines.h +++ b/src/plugins/nat/nat44/inlines.h @@ -31,13 +31,74 @@ nat44_maximum_sessions_exceeded (snat_main_t * sm, u32 thread_index) return 0; } -static_always_inline void -nat44_session_cleanup (snat_session_t * s, u32 thread_index) +static_always_inline f64 +nat44_minimal_timeout (snat_main_t * sm) { - snat_main_t *sm = &snat_main; + f64 min_timeout; + + min_timeout = clib_min (sm->udp_timeout, sm->icmp_timeout); + min_timeout = clib_min (min_timeout, sm->icmp_timeout); + min_timeout = clib_min (min_timeout, sm->tcp_transitory_timeout); + min_timeout = clib_min (min_timeout, sm->tcp_established_timeout); + + return min_timeout; +} + +static_always_inline snat_session_t * +nat44_session_reuse_old (snat_main_t * sm, snat_user_t * u, + snat_session_t * s, u32 thread_index, f64 now) +{ + nat44_free_session_data (sm, s, thread_index, 0); + if (snat_is_session_static (s)) + u->nstaticsessions--; + else + u->nsessions--; + s->flags = 0; + s->total_bytes = 0; + s->total_pkts = 0; + s->state = 0; + s->ext_host_addr.as_u32 = 0; + s->ext_host_port = 0; + s->ext_host_nat_addr.as_u32 = 0; + s->ext_host_nat_port = 0; + s->tcp_close_timestamp = 0; + s->ha_last_refreshed = now; + return s; +} - nat_free_session_data (sm, s, thread_index, 0); - nat44_delete_session (sm, s, thread_index); + +static_always_inline snat_session_t * +nat44_session_alloc_new (snat_main_per_thread_data_t * tsm, snat_user_t * u, + f64 now) +{ + snat_session_t *s; + dlist_elt_t *per_user_translation_list_elt; + + pool_get (tsm->sessions, s); + clib_memset (s, 0, sizeof (*s)); + /* Create list elts */ + pool_get (tsm->list_pool, per_user_translation_list_elt); + clib_dlist_init (tsm->list_pool, + per_user_translation_list_elt - tsm->list_pool); + + per_user_translation_list_elt->value = s - tsm->sessions; + s->per_user_index = per_user_translation_list_elt - tsm->list_pool; + s->per_user_list_head_index = u->sessions_per_user_list_head_index; + + clib_dlist_addtail (tsm->list_pool, + s->per_user_list_head_index, + per_user_translation_list_elt - tsm->list_pool); + + dlist_elt_t *lru_list_elt; + pool_get (tsm->global_lru_pool, lru_list_elt); + s->global_lru_index = lru_list_elt - tsm->global_lru_pool; + clib_dlist_addtail (tsm->global_lru_pool, tsm->global_lru_head_index, + s->global_lru_index); + lru_list_elt->value = s - tsm->sessions; + s->last_lru_update = now; + + s->ha_last_refreshed = now; + return s; } static_always_inline void @@ -59,7 +120,10 @@ nat44_user_del_sessions (snat_user_t * u, u32 thread_index) { s = pool_elt_at_index (tsm->sessions, elt->value); elt = pool_elt_at_index (tsm->list_pool, elt->next); - nat44_session_cleanup (s, thread_index); + + nat44_free_session_data (sm, s, thread_index, 0); + // TODO: needs refactoring as in nat44_user_session_cleanup + nat44_delete_session (sm, s, thread_index); } } @@ -108,9 +172,10 @@ nat44_user_del (ip4_address_t * addr, u32 fib_index) return rv; } -static_always_inline void -nat44_user_try_cleanup (snat_user_t * u, u32 thread_index, f64 now) +static_always_inline u32 +nat44_user_session_cleanup (snat_user_t * u, u32 thread_index, f64 now) { + u32 cleared = 0; dlist_elt_t *elt; snat_session_t *s; u64 sess_timeout_time; @@ -118,6 +183,10 @@ nat44_user_try_cleanup (snat_user_t * u, u32 thread_index, f64 now) snat_main_t *sm = &snat_main; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; + if (now < u->min_session_timeout) + goto done; + u->min_session_timeout = now + sm->min_timeout; + // get head elt = pool_elt_at_index (tsm->list_pool, u->sessions_per_user_list_head_index); @@ -132,103 +201,130 @@ nat44_user_try_cleanup (snat_user_t * u, u32 thread_index, f64 now) sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s); - if (now < sess_timeout_time) + if (s->tcp_close_timestamp) { - tsm->min_session_timeout = - clib_min (sess_timeout_time, tsm->min_session_timeout); - continue; + sess_timeout_time = + clib_min (sess_timeout_time, s->tcp_close_timestamp); } - nat44_session_cleanup (s, thread_index); + if (now < sess_timeout_time) + continue; + + // do cleanup of this call (refactor for ED NAT44 only) + nat44_free_session_data (sm, s, thread_index, 0); + + clib_dlist_remove (tsm->list_pool, s->per_user_index); + pool_put_index (tsm->list_pool, s->per_user_index); + clib_dlist_remove (tsm->global_lru_pool, s->global_lru_index); + pool_put_index (tsm->global_lru_pool, s->global_lru_index); + pool_put (tsm->sessions, s); + vlib_set_simple_counter (&sm->total_sessions, thread_index, 0, + pool_elts (tsm->sessions)); + + if (snat_is_session_static (s)) + u->nstaticsessions--; + else + u->nsessions--; + + cleared++; } +done: + return cleared; } -static_always_inline void -nat44_session_try_cleanup (ip4_address_t * addr, - u32 fib_index, u32 thread_index, f64 now) +static_always_inline u32 +nat44_users_cleanup (u32 thread_index, f64 now) { + snat_main_t *sm = &snat_main; + snat_main_per_thread_data_t *tsm; + + u32 cleared = 0; + + snat_user_key_t u_key; + clib_bihash_kv_8_8_t kv; + snat_user_t *u = 0; - snat_user_key_t user_key; - clib_bihash_kv_8_8_t kv, value; + u32 pool_index; - snat_main_t *sm = &snat_main; - snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; + tsm = vec_elt_at_index (sm->per_thread_data, thread_index); - user_key.addr.as_u32 = addr->as_u32; - user_key.fib_index = fib_index; - kv.key = user_key.as_u64; + if (now < tsm->min_session_timeout) + goto done; + tsm->min_session_timeout = now + sm->min_timeout; + // consider + tsm->cleanup_timeout = tsm->min_session_timeout; - // lookup user for this traffic - if (PREDICT_FALSE (clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))) + pool_index = ~0; + do { - // there is still place and a new user can be created - if (PREDICT_TRUE (pool_elts (tsm->sessions) < sm->max_translations)) - return; + pool_index = pool_next_index (tsm->users, pool_index); + if (pool_index == ~0) + break; + u = pool_elt_at_index (tsm->users, pool_index); - if (now >= tsm->min_session_timeout) - { - tsm->min_session_timeout = ~0; - // there is no place so we try to cleanup all users in this thread - /* *INDENT-OFF* */ - pool_foreach (u, tsm->users, - ({ nat44_user_try_cleanup (u, thread_index, now); })); - /* *INDENT-ON* */ - if (~0 == tsm->min_session_timeout) - { - tsm->min_session_timeout = 0; - } - } - return; - } + cleared += nat44_user_session_cleanup (u, thread_index, now); - if (now >= tsm->min_session_timeout) - { - tsm->min_session_timeout = ~0; - // each time user creates a new session we try to cleanup expired sessions - nat44_user_try_cleanup (pool_elt_at_index (tsm->users, value.value), - thread_index, now); - if (~0 == tsm->min_session_timeout) + if (u->nstaticsessions == 0 && u->nsessions == 0) { - tsm->min_session_timeout = 0; + u_key.addr.as_u32 = u->addr.as_u32; + u_key.fib_index = u->fib_index; + kv.key = u_key.as_u64; + + // delete user + pool_put_index (tsm->list_pool, + u->sessions_per_user_list_head_index); + pool_put (tsm->users, u); + clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 0); + + // update total users counter + vlib_set_simple_counter (&sm->total_users, thread_index, 0, + pool_elts (tsm->users)); } } + while (1); + tsm->cleared += cleared; + tsm->cleanup_runs++; +done: + return cleared; } -static_always_inline void -nat44_force_session_cleanup (void) +static_always_inline u32 +nat44_out_of_ports_cleanup (u32 thread_index, f64 now) { - snat_user_t *u = 0; + return nat44_users_cleanup (thread_index, now); +} + +static_always_inline u32 +nat44_max_translations_per_user_cleanup (snat_user_t * u, u32 thread_index, + f64 now) +{ + return nat44_user_session_cleanup (u, thread_index, now); +} +static_always_inline u32 +nat44_force_users_cleanup (void) +{ snat_main_t *sm = &snat_main; snat_main_per_thread_data_t *tsm; - vlib_main_t *vm = vlib_get_main (); - f64 now = vlib_time_now (vm); - - // TODO: consider own timeouts + f64 now = vlib_time_now (vlib_get_main ()); + u32 cleared = 0; if (sm->num_workers > 1) { /* *INDENT-OFF* */ vec_foreach (tsm, sm->per_thread_data) { - pool_foreach (u, tsm->users, - ({ - nat44_user_try_cleanup (u, tsm->thread_index, now); - })); + cleared += nat44_users_cleanup (tsm->thread_index, now); } /* *INDENT-ON* */ } else { tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); - /* *INDENT-OFF* */ - pool_foreach (u, tsm->users, - ({ - nat44_user_try_cleanup (u, tsm->thread_index, now); - })); - /* *INDENT-ON* */ + cleared += nat44_users_cleanup (tsm->thread_index, now); } + return cleared; } #endif /* included_nat44_inlines_h__ */