NAT44: endpoint-dependent mode session timeout improvement (VPP-1423)
Change-Id: I630f3da1ea4e6e50a50f1352c097becef1efe3c0
Signed-off-by: Matus Fabian <matfabia@cisco.com>
diff --git a/src/plugins/nat/in2out_ed.c b/src/plugins/nat/in2out_ed.c
index d4f70f5..7763026 100644
--- a/src/plugins/nat/in2out_ed.c
+++ b/src/plugins/nat/in2out_ed.c
@@ -315,7 +315,7 @@
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 @@
}
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 efca440..0818332 100755
--- a/src/plugins/nat/nat.c
+++ b/src/plugins/nat/nat.c
@@ -388,37 +388,73 @@
}
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);
- /* 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;
- 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);
-
+ 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 865d27e..1baf10f 100644
--- a/src/plugins/nat/nat.h
+++ b/src/plugins/nat/nat.h
@@ -933,7 +933,7 @@
* @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 4236285..ef77233 100644
--- a/src/plugins/nat/out2in_ed.c
+++ b/src/plugins/nat/out2in_ed.c
@@ -233,7 +233,7 @@
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 @@
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 @@
}
/* 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 f3b5205..9092b47 100644
--- a/test/test_nat.py
+++ b/test/test_nat.py
@@ -5657,6 +5657,7 @@
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 @@
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: