diff options
-rw-r--r-- | src/plugins/nat/in2out_ed.c | 4 | ||||
-rwxr-xr-x | src/plugins/nat/nat.c | 78 | ||||
-rw-r--r-- | src/plugins/nat/nat.h | 2 | ||||
-rw-r--r-- | src/plugins/nat/out2in_ed.c | 6 | ||||
-rw-r--r-- | test/test_nat.py | 10 |
5 files changed, 73 insertions, 27 deletions
diff --git a/src/plugins/nat/in2out_ed.c b/src/plugins/nat/in2out_ed.c index d4f70f5a12b..77630268047 100644 --- a/src/plugins/nat/in2out_ed.c +++ b/src/plugins/nat/in2out_ed.c @@ -315,7 +315,7 @@ slow_path_ed (snat_main_t * sm, return NAT_IN2OUT_ED_NEXT_DROP; } - s = nat_ed_session_alloc (sm, u, thread_index); + s = nat_ed_session_alloc (sm, u, thread_index, now); if (!s) { nat44_delete_user_with_no_session (sm, u, thread_index); @@ -777,7 +777,7 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm, } create_ses: - s = nat_ed_session_alloc (sm, u, thread_index); + s = nat_ed_session_alloc (sm, u, thread_index, now); if (!s) { nat44_delete_user_with_no_session (sm, u, thread_index); diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index efca4404ddd..0818332eeb3 100755 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -388,37 +388,73 @@ nat_session_alloc_or_recycle (snat_main_t * sm, snat_user_t * u, } snat_session_t * -nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index) +nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index, + f64 now) { snat_session_t *s; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; - dlist_elt_t *per_user_translation_list_elt; + dlist_elt_t *per_user_translation_list_elt, *oldest_elt; + u32 oldest_index; + u64 sess_timeout_time; if ((u->nsessions + u->nstaticsessions) >= sm->max_translations_per_user) { - nat_log_warn ("max translations per user %U", format_ip4_address, - &u->addr); - snat_ipfix_logging_max_entries_per_user (sm->max_translations_per_user, - u->addr.as_u32); - return 0; + oldest_index = + clib_dlist_remove_head (tsm->list_pool, + u->sessions_per_user_list_head_index); + oldest_elt = pool_elt_at_index (tsm->list_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) + { + clib_dlist_addtail (tsm->list_pool, + u->sessions_per_user_list_head_index, + oldest_index); + nat_free_session_data (sm, s, thread_index); + 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; + } + else + { + clib_dlist_addhead (tsm->list_pool, + u->sessions_per_user_list_head_index, + oldest_index); + nat_log_warn ("max translations per user %U", format_ip4_address, + &u->addr); + snat_ipfix_logging_max_entries_per_user + (sm->max_translations_per_user, u->addr.as_u32); + return 0; + } } + else + { + pool_get (tsm->sessions, s); + memset (s, 0, sizeof (*s)); - pool_get (tsm->sessions, s); - 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; + /* 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); - clib_dlist_addtail (tsm->list_pool, - s->per_user_list_head_index, - 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); + } return s; } diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h index 865d27efb5a..1baf10ff43c 100644 --- a/src/plugins/nat/nat.h +++ b/src/plugins/nat/nat.h @@ -933,7 +933,7 @@ snat_session_t *nat_session_alloc_or_recycle (snat_main_t * sm, * @return session data structure on success otherwise zero value */ snat_session_t *nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, - u32 thread_index); + u32 thread_index, f64 now); /** * @brief Set address and port assignment algorithm for MAP-E CE diff --git a/src/plugins/nat/out2in_ed.c b/src/plugins/nat/out2in_ed.c index 4236285df8d..ef772334292 100644 --- a/src/plugins/nat/out2in_ed.c +++ b/src/plugins/nat/out2in_ed.c @@ -233,7 +233,7 @@ create_session_for_static_mapping_ed (snat_main_t * sm, return 0; } - s = nat_ed_session_alloc (sm, u, thread_index); + s = nat_ed_session_alloc (sm, u, thread_index, now); if (!s) { nat44_delete_user_with_no_session (sm, u, thread_index); @@ -421,7 +421,7 @@ create_bypass_for_fwd (snat_main_t * sm, ip4_header_t * ip, u32 rx_fib_index, return; } - s = nat_ed_session_alloc (sm, u, thread_index); + s = nat_ed_session_alloc (sm, u, thread_index, now); if (!s) { nat44_delete_user_with_no_session (sm, u, thread_index); @@ -623,7 +623,7 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm, } /* Create a new session */ - s = nat_ed_session_alloc (sm, u, thread_index); + s = nat_ed_session_alloc (sm, u, thread_index, now); if (!s) { nat44_delete_user_with_no_session (sm, u, thread_index); diff --git a/test/test_nat.py b/test/test_nat.py index f3b5205a2fb..9092b4796bb 100644 --- a/test/test_nat.py +++ b/test/test_nat.py @@ -5657,6 +5657,7 @@ class TestNAT44EndpointDependent(MethodHolder): src_address=self.pg2.local_ip4n, path_mtu=512, template_interval=10) + self.vapi.nat_set_timeouts(udp=5) # get maximum number of translations per user nat44_config = self.vapi.nat_show_config() @@ -5703,6 +5704,15 @@ class TestNAT44EndpointDependent(MethodHolder): nat44_config.max_translations_per_user, self.pg0.remote_ip4n) + sleep(6) + p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / + IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) / + UDP(sport=3001, dport=3002)) + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + self.pg1.get_capture(1) + def tearDown(self): super(TestNAT44EndpointDependent, self).tearDown() if not self.vpp_dead: |