summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xsrc/plugins/nat/in2out.c3
-rw-r--r--src/plugins/nat/in2out_ed.c55
-rwxr-xr-xsrc/plugins/nat/nat.c214
-rw-r--r--src/plugins/nat/nat.h31
-rw-r--r--src/plugins/nat/nat44/inlines.h218
-rw-r--r--src/plugins/nat/nat44_cli.c195
-rw-r--r--src/plugins/nat/nat_api.c8
-rw-r--r--src/plugins/nat/nat_format.c91
-rwxr-xr-xsrc/plugins/nat/out2in.c3
-rw-r--r--src/plugins/nat/out2in_ed.c17
-rw-r--r--src/plugins/nat/test/test_nat.py73
11 files changed, 615 insertions, 293 deletions
diff --git a/src/plugins/nat/in2out.c b/src/plugins/nat/in2out.c
index 7b712523f29..10acf187208 100755
--- a/src/plugins/nat/in2out.c
+++ b/src/plugins/nat/in2out.c
@@ -264,9 +264,6 @@ slow_path (snat_main_t * sm, vlib_buffer_t * b0,
};
nat44_is_idle_session_ctx_t ctx0;
- nat44_session_try_cleanup (&ip0->src_address, rx_fib_index0, thread_index,
- now);
-
if (PREDICT_FALSE (nat44_maximum_sessions_exceeded (sm, thread_index)))
{
b0->error = node->errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
diff --git a/src/plugins/nat/in2out_ed.c b/src/plugins/nat/in2out_ed.c
index 581d7b4ef60..ca737d56663 100644
--- a/src/plugins/nat/in2out_ed.c
+++ b/src/plugins/nat/in2out_ed.c
@@ -209,14 +209,18 @@ slow_path_ed (snat_main_t * sm,
};
nat44_is_idle_session_ctx_t ctx;
- nat44_session_try_cleanup (&key->l_addr, rx_fib_index, thread_index, now);
+ u32 cleared = 0;
if (PREDICT_FALSE (nat44_maximum_sessions_exceeded (sm, thread_index)))
{
- b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
- nat_ipfix_logging_max_sessions (thread_index, sm->max_translations);
- nat_elog_notice ("maximum sessions exceeded");
- return NAT_NEXT_DROP;
+ if (PREDICT_FALSE
+ (!(cleared = nat44_users_cleanup (thread_index, now))))
+ {
+ b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
+ nat_ipfix_logging_max_sessions (thread_index, sm->max_translations);
+ nat_elog_notice ("maximum sessions exceeded");
+ return NAT_NEXT_DROP;
+ }
}
key0.addr = key->l_addr;
@@ -224,6 +228,7 @@ slow_path_ed (snat_main_t * sm,
key1.protocol = key0.protocol = proto;
key0.fib_index = rx_fib_index;
key1.fib_index = sm->outside_fib_index;
+
/* First try to match static mapping by local address and port */
if (snat_static_mapping_match
(sm, key0, &key1, 0, 0, 0, &lb, 0, &identity_nat))
@@ -234,9 +239,16 @@ slow_path_ed (snat_main_t * sm,
sm->port_per_thread,
tsm->snat_thread_index))
{
- nat_elog_notice ("addresses exhausted");
- b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
- return NAT_NEXT_DROP;
+ if (cleared || !nat44_out_of_ports_cleanup (thread_index, now) ||
+ snat_alloc_outside_address_and_port (sm->addresses,
+ rx_fib_index, thread_index,
+ &key1, sm->port_per_thread,
+ tsm->snat_thread_index))
+ {
+ nat_elog_notice ("addresses exhausted");
+ b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
+ return NAT_NEXT_DROP;
+ }
}
}
else
@@ -246,16 +258,19 @@ slow_path_ed (snat_main_t * sm,
*sessionp = s;
return next;
}
-
is_sm = 1;
}
- if (proto == SNAT_PROTOCOL_TCP)
+ if (PREDICT_TRUE (proto == SNAT_PROTOCOL_TCP))
{
- if (!tcp_flags_is_init
- (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
+ if (PREDICT_FALSE
+ (!tcp_flags_is_init
+ (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
{
b->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN];
+ if (!is_sm)
+ snat_free_outside_address_and_port (sm->addresses,
+ thread_index, &key1);
return NAT_NEXT_DROP;
}
}
@@ -932,9 +947,23 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t * vm,
next0 = def_slow;
goto trace0;
}
-
s0 = pool_elt_at_index (tsm->sessions, value0.value);
+ // drop if session expired
+ u64 sess_timeout_time;
+ sess_timeout_time = s0->last_heard +
+ (f64) nat44_session_get_timeout (sm, s0);
+ if (now >= sess_timeout_time)
+ {
+ // delete session
+ nat_free_session_data (sm, s0, thread_index, 0);
+ nat44_delete_session (sm, s0, thread_index);
+
+ next0 = NAT_NEXT_DROP;
+ goto trace0;
+ }
+ //
+
b0->flags |= VNET_BUFFER_F_IS_NATED;
if (!is_output_feature)
diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c
index 07147083e52..4803eeb64de 100755
--- a/src/plugins/nat/nat.c
+++ b/src/plugins/nat/nat.c
@@ -26,6 +26,7 @@
#include <nat/nat64.h>
#include <nat/nat66.h>
#include <nat/nat_inlines.h>
+#include <nat/nat44/inlines.h>
#include <nat/nat_affinity.h>
#include <nat/nat_syslog.h>
#include <nat/nat_ha.h>
@@ -325,6 +326,133 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
&s->out2in);
}
+void
+nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
+ u32 thread_index, u8 is_ha)
+{
+ snat_session_key_t key;
+ nat_ed_ses_key_t ed_key;
+ clib_bihash_kv_16_8_t ed_kv;
+ snat_main_per_thread_data_t *tsm =
+ vec_elt_at_index (sm->per_thread_data, thread_index);
+
+ if (is_fwd_bypass_session (s))
+ {
+ if (snat_is_unk_proto_session (s))
+ {
+ ed_key.proto = s->in2out.port;
+ ed_key.r_port = 0;
+ ed_key.l_port = 0;
+ }
+ else
+ {
+ ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
+ ed_key.l_port = s->in2out.port;
+ ed_key.r_port = s->ext_host_port;
+ }
+
+ ed_key.l_addr = s->in2out.addr;
+ ed_key.r_addr = s->ext_host_addr;
+ ed_key.fib_index = 0;
+ ed_kv.key[0] = ed_key.as_u64[0];
+ ed_kv.key[1] = ed_key.as_u64[1];
+
+ if (PREDICT_FALSE
+ (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)))
+ nat_elog_warn ("in2out_ed key del failed");
+ return;
+ }
+
+ /* session lookup tables */
+ if (is_affinity_sessions (s))
+ nat_affinity_unlock (s->ext_host_addr, s->out2in.addr,
+ s->in2out.protocol, s->out2in.port);
+ ed_key.l_addr = s->out2in.addr;
+ ed_key.r_addr = s->ext_host_addr;
+ ed_key.fib_index = s->out2in.fib_index;
+ if (snat_is_unk_proto_session (s))
+ {
+ ed_key.proto = s->in2out.port;
+ ed_key.r_port = 0;
+ ed_key.l_port = 0;
+ }
+ else
+ {
+ ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
+ ed_key.l_port = s->out2in.port;
+ ed_key.r_port = s->ext_host_port;
+ }
+ ed_kv.key[0] = ed_key.as_u64[0];
+ ed_kv.key[1] = ed_key.as_u64[1];
+
+ if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0)))
+ nat_elog_warn ("out2in_ed key del failed");
+
+ ed_key.l_addr = s->in2out.addr;
+ ed_key.fib_index = s->in2out.fib_index;
+
+ if (!snat_is_unk_proto_session (s))
+ ed_key.l_port = s->in2out.port;
+
+ if (is_twice_nat_session (s))
+ {
+ ed_key.r_addr = s->ext_host_nat_addr;
+ ed_key.r_port = s->ext_host_nat_port;
+ }
+
+ ed_kv.key[0] = ed_key.as_u64[0];
+ ed_kv.key[1] = ed_key.as_u64[1];
+
+ if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)))
+ nat_elog_warn ("in2out_ed key del failed");
+
+ if (!is_ha)
+ {
+ nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
+ &s->in2out.addr, s->in2out.port,
+ &s->ext_host_nat_addr, s->ext_host_nat_port,
+ &s->out2in.addr, s->out2in.port,
+ &s->ext_host_addr, s->ext_host_port,
+ s->in2out.protocol, is_twice_nat_session (s));
+ }
+
+ if (snat_is_unk_proto_session (s))
+ return;
+
+ // is this correct ?
+ if (!is_ha)
+ {
+ snat_ipfix_logging_nat44_ses_delete (thread_index,
+ s->in2out.addr.as_u32,
+ s->out2in.addr.as_u32,
+ s->in2out.protocol,
+ s->in2out.port,
+ s->out2in.port,
+ s->in2out.fib_index);
+ nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
+ s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
+ thread_index);
+ }
+
+ /* Twice NAT address and port for external host */
+ if (is_twice_nat_session (s))
+ {
+ key.protocol = s->in2out.protocol;
+ key.port = s->ext_host_nat_port;
+ key.addr.as_u32 = s->ext_host_nat_addr.as_u32;
+ snat_free_outside_address_and_port (sm->twice_nat_addresses,
+ thread_index, &key);
+ }
+
+ if (snat_is_session_static (s))
+ return;
+
+ // should be called for every dynamic session
+ snat_free_outside_address_and_port (sm->addresses, thread_index,
+ &s->out2in);
+}
+
+
snat_user_t *
nat_user_get_or_create (snat_main_t * sm, ip4_address_t * addr, u32 fib_index,
u32 thread_index)
@@ -345,6 +473,9 @@ nat_user_get_or_create (snat_main_t * sm, ip4_address_t * addr, u32 fib_index,
/* no, make a new one */
pool_get (tsm->users, u);
clib_memset (u, 0, sizeof (*u));
+
+ u->min_session_timeout = 0;
+
u->addr.as_u32 = addr->as_u32;
u->fib_index = fib_index;
@@ -453,13 +584,30 @@ nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index,
{
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, *oldest_elt;
- u32 oldest_index;
+
+ dlist_elt_t *oldest_elt;
u64 sess_timeout_time;
+ u32 oldest_index;
+ // no sessions
if (PREDICT_FALSE (!(u->nsessions) && !(u->nstaticsessions)))
goto alloc_new;
+ // no free sessions
+ if (PREDICT_FALSE
+ ((u->nsessions + u->nstaticsessions) >= sm->max_translations_per_user))
+ {
+ if (nat44_max_translations_per_user_cleanup (u, thread_index, now))
+ goto alloc_new;
+
+ nat_elog_addr (SNAT_LOG_WARNING, "[warn] max translations per user",
+ clib_net_to_host_u32 (u->addr.as_u32));
+ snat_ipfix_logging_max_entries_per_user (thread_index,
+ 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);
@@ -469,61 +617,21 @@ nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index,
sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
if (now >= sess_timeout_time)
{
+ // reuse old session
clib_dlist_addtail (tsm->list_pool,
u->sessions_per_user_list_head_index, oldest_index);
- nat_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 = nat44_session_reuse_old (sm, u, s, thread_index, now);
}
else
{
+ // alloc new session
clib_dlist_addhead (tsm->list_pool,
u->sessions_per_user_list_head_index, oldest_index);
- if ((u->nsessions + u->nstaticsessions) >=
- sm->max_translations_per_user)
- {
- nat_elog_addr (SNAT_LOG_WARNING, "[warn] max translations per user",
- clib_net_to_host_u32 (u->addr.as_u32));
- snat_ipfix_logging_max_entries_per_user
- (thread_index, sm->max_translations_per_user, u->addr.as_u32);
- return 0;
- }
- else
- {
- alloc_new:
- 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);
- }
-
+ alloc_new:
+ s = nat44_session_alloc_new (tsm, u, now);
vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
pool_elts (tsm->sessions));
}
-
- s->ha_last_refreshed = now;
-
return s;
}
@@ -2370,7 +2478,6 @@ snat_init (vlib_main_t * vm)
sm->fq_in2out_output_index = ~0;
sm->fq_out2in_index = ~0;
-
sm->alloc_addr_and_port = nat_alloc_addr_and_port_default;
sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT;
sm->forwarding_enabled = 0;
@@ -3768,9 +3875,9 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
u8 static_mapping_only = 0;
u8 static_mapping_connection_tracking = 0;
+ // configurable timeouts
u32 udp_timeout = SNAT_UDP_TIMEOUT;
u32 icmp_timeout = SNAT_ICMP_TIMEOUT;
-
u32 tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
u32 tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
@@ -3851,9 +3958,11 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
/* optionally configurable timeouts for testing purposes */
sm->udp_timeout = udp_timeout;
- sm->icmp_timeout = icmp_timeout;
sm->tcp_transitory_timeout = tcp_transitory_timeout;
sm->tcp_established_timeout = tcp_established_timeout;
+ sm->icmp_timeout = icmp_timeout;
+
+ sm->min_timeout = nat44_minimal_timeout (sm);
sm->user_buckets = user_buckets;
sm->user_memory_size = user_memory_size;
@@ -3936,6 +4045,11 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
vec_foreach (tsm, sm->per_thread_data)
{
tsm->min_session_timeout = 0;
+
+ tsm->cleared = 0;
+ tsm->cleanup_runs = 0;
+ tsm->cleanup_timeout = 0;
+
if (sm->endpoint_dependent)
{
clib_bihash_init_16_8 (&tsm->in2out_ed, "in2out-ed",
diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h
index 9bcce9d43cc..647bec0cd07 100644
--- a/src/plugins/nat/nat.h
+++ b/src/plugins/nat/nat.h
@@ -349,6 +349,8 @@ typedef struct
u32 sessions_per_user_list_head_index;
u32 nsessions;
u32 nstaticsessions;
+ /* discovered minimum session timeout time */
+ u64 min_session_timeout;
} snat_user_t;
typedef struct
@@ -519,6 +521,12 @@ typedef struct
/* discovered minimum session timeout time */
u64 min_session_timeout;
+
+ /* session scavenging */
+ u32 cleared;
+ u32 cleanup_runs;
+ f64 cleanup_timeout;
+
} snat_main_per_thread_data_t;
struct snat_main_s;
@@ -676,10 +684,14 @@ typedef struct snat_main_s
u32 inside_fib_index;
/* values of various timeouts */
+
+ // min timeout of all proto timeouts
+ u32 min_timeout;
+ // proto timeouts
u32 udp_timeout;
- u32 icmp_timeout;
u32 tcp_transitory_timeout;
u32 tcp_established_timeout;
+ u32 icmp_timeout;
/* TCP MSS clamping */
u16 mss_clamping;
@@ -703,6 +715,7 @@ typedef struct snat_main_s
ip4_main_t *ip4_main;
ip_lookup_main_t *ip4_lookup_main;
api_main_t *api_main;
+
} snat_main_t;
typedef struct
@@ -750,6 +763,7 @@ extern fib_source_t nat_fib_src_low;
/* format functions */
format_function_t format_snat_user;
+format_function_t format_snat_user_v2;
format_function_t format_snat_static_mapping;
format_function_t format_snat_static_map_to_resolve;
format_function_t format_snat_session;
@@ -1294,6 +1308,16 @@ void nat_free_session_data (snat_main_t * sm, snat_session_t * s,
u32 thread_index, u8 is_ha);
/**
+ * @brief Free NAT44 ED session data (lookup keys, external addrres port)
+ *
+ * @param s NAT session
+ * @param thread_index thread index
+ * @param is_ha is HA event
+ */
+void
+nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
+ u32 thread_index, u8 is_ha);
+/**
* @brief Find or create NAT user
*
* @param addr IPv4 address
@@ -1302,8 +1326,9 @@ void nat_free_session_data (snat_main_t * sm, snat_session_t * s,
*
* @return NAT user data structure on success otherwise zero value
*/
-snat_user_t *nat_user_get_or_create (snat_main_t * sm, ip4_address_t * addr,
- u32 fib_index, u32 thread_index);
+snat_user_t *nat_user_get_or_create (snat_main_t * sm,
+ ip4_address_t * addr, u32 fib_index,
+ u32 thread_index);
/**
* @brief Allocate new NAT session or recycle last used
diff --git a/src/plugins/nat/nat44/inlines.h b/src/plugins/nat/nat44/inlines.h
index 0c8487b473d..7cc24750423 100644
--- a/src/plugins/nat/nat44/inlines.h
+++ b/src/plugins/nat/nat44/inlines.h
@@ -31,13 +31,66 @@ 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->ha_last_refreshed = now;
+ return s;
+}
+
+
+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;
- nat_free_session_data (sm, s, thread_index, 0);
- nat44_delete_session (sm, s, thread_index);
+ 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);
+
+ s->ha_last_refreshed = now;
+ return s;
}
static_always_inline void
@@ -59,7 +112,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 +164,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 +175,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);
@@ -133,102 +194,121 @@ nat44_user_try_cleanup (snat_user_t * u, u32 thread_index, f64 now)
(f64) nat44_session_get_timeout (sm, s);
if (now < sess_timeout_time)
- {
- tsm->min_session_timeout =
- clib_min (sess_timeout_time, tsm->min_session_timeout);
- continue;
- }
+ 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);
+ pool_put (tsm->sessions, s);
+ vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
+ pool_elts (tsm->sessions));
- nat44_session_cleanup (s, thread_index);
+ 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__ */
diff --git a/src/plugins/nat/nat44_cli.c b/src/plugins/nat/nat44_cli.c
index 11e87092ae7..45e00693676 100644
--- a/src/plugins/nat/nat44_cli.c
+++ b/src/plugins/nat/nat44_cli.c
@@ -122,9 +122,7 @@ nat44_session_cleanup_command_fn (vlib_main_t * vm,
vlib_cli_command_t * cmd)
{
clib_error_t *error = 0;
-
- nat44_force_session_cleanup ();
-
+ nat44_force_users_cleanup ();
return error;
}
@@ -645,56 +643,26 @@ nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input,
{
snat_main_per_thread_data_t *tsm;
snat_main_t *sm = &snat_main;
- snat_address_t *a;
snat_session_t *s;
- u32 free_ports, free_ports_addr;
- if (sm->deterministic)
+ if (sm->deterministic || !sm->endpoint_dependent)
return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
- if (sm->endpoint_dependent)
- vlib_cli_output (vm, "mode: endpoint-depenent");
-
- // print timeouts
- vlib_cli_output (vm, "icmp timeout: %u", sm->icmp_timeout);
- vlib_cli_output (vm, "udp timeout: %u", sm->udp_timeout);
-
- vlib_cli_output (vm, "tcp established timeout: %u",
- sm->tcp_established_timeout);
- vlib_cli_output (vm, "tcp transitory timeout: %u",
- sm->tcp_transitory_timeout);
-
// print session configuration values
vlib_cli_output (vm, "max translations: %u", sm->max_translations);
vlib_cli_output (vm, "max translations per user: %u",
sm->max_translations_per_user);
- // do we need also twice-nat addresses ??
- if (vec_len (sm->addresses))
- {
- free_ports = 0;
- /* *INDENT-OFF* */
- vec_foreach (a, sm->addresses)
- {
- free_ports_addr = sm->port_per_thread;
-
- #define _(N, i, n, s) \
- free_ports_addr -= a->busy_##n##_ports;
- foreach_snat_protocol
- #undef _
+ u32 count = 0;
- vlib_cli_output (vm, "addr: %U free ports: %u out of: %u",
- format_ip4_address, &a->addr, free_ports_addr, sm->port_per_thread);
+ u64 now = vlib_time_now (sm->vlib_main);
+ u64 sess_timeout_time;
- free_ports += free_ports_addr;
- }
- /* *INDENT-ON* */
- vlib_cli_output (vm, "free ports overall: %u out of: %u",
- free_ports,
- vec_len (sm->addresses) * sm->port_per_thread);
- }
+ u32 udp_sessions = 0;
+ u32 tcp_sessions = 0;
+ u32 icmp_sessions = 0;
- u32 count = 0;
+ u32 timed_out = 0;
u32 transitory = 0;
u32 established = 0;
@@ -703,14 +671,44 @@ nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input,
/* *INDENT-OFF* */
vec_foreach (tsm, sm->per_thread_data)
{
- count += vec_len (tsm->sessions);
pool_foreach (s, tsm->sessions,
({
- if (s->state)
- transitory++;
- else
- established++;
+ sess_timeout_time = s->last_heard +
+ (f64) nat44_session_get_timeout (sm, s);
+ if (now >= sess_timeout_time)
+ timed_out++;
+
+ switch (s->in2out.protocol)
+ {
+ case SNAT_PROTOCOL_ICMP:
+ icmp_sessions++;
+ break;
+ case SNAT_PROTOCOL_TCP:
+ tcp_sessions++;
+ if (s->state)
+ transitory++;
+ else
+ established++;
+ break;
+ case SNAT_PROTOCOL_UDP:
+ default:
+ udp_sessions++;
+ break;
+ }
}));
+ count += pool_elts (tsm->sessions);
+
+ vlib_cli_output (vm, "tid[%u] session scavenging cleared: %u",
+ tsm->thread_index, tsm->cleared);
+ vlib_cli_output (vm, "tid[%u] session scavenging cleanup runs: %u",
+ tsm->thread_index, tsm->cleanup_runs);
+
+ if (now < tsm->cleanup_timeout)
+ vlib_cli_output (vm, "tid[%u] session scavenging next run in: %f",
+ tsm->thread_index, tsm->cleanup_timeout - now);
+ else
+ vlib_cli_output (vm, "tid[%u] session scavenging next run in: 0",
+ tsm->thread_index);
}
/* *INDENT-ON* */
}
@@ -720,17 +718,51 @@ nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input,
/* *INDENT-OFF* */
pool_foreach (s, tsm->sessions,
({
- if (s->state)
- transitory++;
- else
- established++;
+ sess_timeout_time = s->last_heard +
+ (f64) nat44_session_get_timeout (sm, s);
+ if (now >= sess_timeout_time)
+ timed_out++;
+
+ switch (s->in2out.protocol)
+ {
+ case SNAT_PROTOCOL_ICMP:
+ icmp_sessions++;
+ break;
+ case SNAT_PROTOCOL_TCP:
+ tcp_sessions++;
+ if (s->state)
+ transitory++;
+ else
+ established++;
+ break;
+ case SNAT_PROTOCOL_UDP:
+ default:
+ udp_sessions++;
+ break;
+ }
}));
/* *INDENT-ON* */
- count = vec_len (tsm->sessions);
+ count = pool_elts (tsm->sessions);
+
+ vlib_cli_output (vm, "tid[0] session scavenging cleared: %u",
+ tsm->cleared);
+ vlib_cli_output (vm, "tid[0] session scavenging cleanup runs: %u",
+ tsm->cleanup_runs);
+
+ if (now < tsm->cleanup_timeout)
+ vlib_cli_output (vm, "tid[0] session scavenging next run in: %f",
+ tsm->cleanup_timeout - now);
+ else
+ vlib_cli_output (vm, "tid[0] session scavenging next run in: 0");
}
- vlib_cli_output (vm, "established sessions: %u", established);
- vlib_cli_output (vm, "transitory sessions: %u", transitory);
- vlib_cli_output (vm, "sessions: %u", count);
+
+ vlib_cli_output (vm, "total timed out sessions: %u", timed_out);
+ vlib_cli_output (vm, "total sessions: %u", count);
+ vlib_cli_output (vm, "total tcp sessions: %u", tcp_sessions);
+ vlib_cli_output (vm, "total tcp established sessions: %u", established);
+ vlib_cli_output (vm, "total tcp transitory sessions: %u", transitory);
+ vlib_cli_output (vm, "total udp sessions: %u", udp_sessions);
+ vlib_cli_output (vm, "total icmp sessions: %u", icmp_sessions);
return 0;
}
@@ -1439,20 +1471,38 @@ static clib_error_t *
nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_command_t * cmd)
{
- int verbose = 0;
+ unformat_input_t _line_input, *line_input = &_line_input;
+ clib_error_t *error = 0;
snat_main_t *sm = &snat_main;
snat_main_per_thread_data_t *tsm;
+
+ int detail = 0, metrics = 0;
snat_user_t *u;
int i = 0;
if (sm->deterministic)
return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
- if (unformat (input, "detail"))
- verbose = 1;
+ if (!unformat_user (input, unformat_line_input, line_input))
+ goto print;
- vlib_cli_output (vm, "NAT44 sessions:");
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "detail"))
+ detail = 1;
+ else if (unformat (line_input, "metrics"))
+ metrics = 1;
+ else
+ {
+ error = clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, line_input);
+ break;
+ }
+ }
+ unformat_free (line_input);
+print:
+ vlib_cli_output (vm, "NAT44 sessions:");
/* *INDENT-OFF* */
vec_foreach_index (i, sm->per_thread_data)
{
@@ -1461,14 +1511,24 @@ nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_output (vm, "-------- thread %d %s: %d sessions --------\n",
i, vlib_worker_threads[i].name,
pool_elts (tsm->sessions));
- pool_foreach (u, tsm->users,
- ({
- vlib_cli_output (vm, " %U", format_snat_user, tsm, u, verbose);
- }));
+ if (metrics)
+ {
+ u64 now = vlib_time_now (sm->vlib_main);
+ pool_foreach (u, tsm->users,
+ ({
+ vlib_cli_output (vm, " %U", format_snat_user_v2, tsm, u, now);
+ }));
+ }
+ else
+ {
+ pool_foreach (u, tsm->users,
+ ({
+ vlib_cli_output (vm, " %U", format_snat_user, tsm, u, detail);
+ }));
+ }
}
/* *INDENT-ON* */
-
- return 0;
+ return error;
}
static clib_error_t *
@@ -1896,10 +1956,9 @@ set_timeout_command_fn (vlib_main_t * vm,
goto done;
}
}
-
done:
unformat_free (line_input);
-
+ sm->min_timeout = nat44_minimal_timeout (sm);
return error;
}
@@ -1910,6 +1969,8 @@ nat_show_timeouts_command_fn (vlib_main_t * vm,
{
snat_main_t *sm = &snat_main;
+ // fix text
+ vlib_cli_output (vm, "min session cleanup timeout: %dsec", sm->min_timeout);
vlib_cli_output (vm, "udp timeout: %dsec", sm->udp_timeout);
vlib_cli_output (vm, "tcp-established timeout: %dsec",
sm->tcp_established_timeout);
@@ -2535,7 +2596,7 @@ VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
?*/
VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
.path = "show nat44 sessions",
- .short_help = "show nat44 sessions [detail]",
+ .short_help = "show nat44 sessions [detail|metrics]",
.function = nat44_show_sessions_command_fn,
};
diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c
index d8c2c5fd1c9..a71c888b6c6 100644
--- a/src/plugins/nat/nat_api.c
+++ b/src/plugins/nat/nat_api.c
@@ -247,9 +247,7 @@ vl_api_nat44_session_cleanup_t_handler (vl_api_nat44_session_cleanup_t * mp)
snat_main_t *sm = &snat_main;
vl_api_nat44_session_cleanup_reply_t *rmp;
int rv = 0;
-
- nat44_force_session_cleanup ();
-
+ nat44_force_users_cleanup ();
REPLY_MACRO (VL_API_NAT44_SESSION_CLEANUP_REPLY);
}
@@ -338,6 +336,8 @@ vl_api_nat_set_timeouts_t_handler (vl_api_nat_set_timeouts_t * mp)
sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
sm->icmp_timeout = ntohl (mp->icmp);
+ sm->min_timeout = nat44_minimal_timeout (sm);
+
rv = nat64_set_icmp_timeout (ntohl (mp->icmp));
if (rv)
goto send_reply;
@@ -747,10 +747,8 @@ vl_api_nat44_del_user_t_handler (vl_api_nat44_del_user_t * mp)
vl_api_nat44_del_user_reply_t *rmp;
ip4_address_t addr;
int rv;
-
memcpy (&addr.as_u8, mp->ip_address, 4);
rv = nat44_user_del (&addr, ntohl (mp->fib_index));
-
REPLY_MACRO (VL_API_NAT44_DEL_USER_REPLY);
}
diff --git a/src/plugins/nat/nat_format.c b/src/plugins/nat/nat_format.c
index 17f64b9b222..71bdaa6662c 100644
--- a/src/plugins/nat/nat_format.c
+++ b/src/plugins/nat/nat_format.c
@@ -18,6 +18,7 @@
*/
#include <nat/nat.h>
+#include <nat/nat_inlines.h>
#include <nat/nat_det.h>
uword
@@ -173,7 +174,9 @@ format_snat_session (u8 * s, va_list * args)
u8 *
format_snat_user (u8 * s, va_list * args)
{
- snat_main_per_thread_data_t *sm =
+
+ snat_main_t *sm = &snat_main;
+ snat_main_per_thread_data_t *tsm =
va_arg (*args, snat_main_per_thread_data_t *);
snat_user_t *u = va_arg (*args, snat_user_t *);
int verbose = va_arg (*args, int);
@@ -191,20 +194,20 @@ format_snat_user (u8 * s, va_list * args)
if (u->nsessions || u->nstaticsessions)
{
head_index = u->sessions_per_user_list_head_index;
- head = pool_elt_at_index (sm->list_pool, head_index);
+ head = pool_elt_at_index (tsm->list_pool, head_index);
elt_index = head->next;
- elt = pool_elt_at_index (sm->list_pool, elt_index);
+ elt = pool_elt_at_index (tsm->list_pool, elt_index);
session_index = elt->value;
while (session_index != ~0)
{
- sess = pool_elt_at_index (sm->sessions, session_index);
+ sess = pool_elt_at_index (tsm->sessions, session_index);
s = format (s, " %U\n", format_snat_session, sm, sess);
elt_index = elt->next;
- elt = pool_elt_at_index (sm->list_pool, elt_index);
+ elt = pool_elt_at_index (tsm->list_pool, elt_index);
session_index = elt->value;
}
}
@@ -213,6 +216,84 @@ format_snat_user (u8 * s, va_list * args)
}
u8 *
+format_snat_user_v2 (u8 * s, va_list * args)
+{
+
+ snat_main_t *sm = &snat_main;
+ snat_main_per_thread_data_t *tsm =
+ va_arg (*args, snat_main_per_thread_data_t *);
+ snat_user_t *u = va_arg (*args, snat_user_t *);
+ u64 now = va_arg (*args, u64);
+
+ dlist_elt_t *head, *elt;
+ u32 elt_index, head_index;
+ u32 session_index;
+ snat_session_t *sess;
+
+ u32 udp_sessions = 0;
+ u32 tcp_sessions = 0;
+ u32 icmp_sessions = 0;
+
+ u32 timed_out = 0;
+ u32 transitory = 0;
+ u32 established = 0;
+
+ u64 sess_timeout_time;
+
+ if (u->nsessions || u->nstaticsessions)
+ {
+ head_index = u->sessions_per_user_list_head_index;
+ head = pool_elt_at_index (tsm->list_pool, head_index);
+
+ elt_index = head->next;
+ elt = pool_elt_at_index (tsm->list_pool, elt_index);
+ session_index = elt->value;
+
+ while (session_index != ~0)
+ {
+ sess = pool_elt_at_index (tsm->sessions, session_index);
+
+ sess_timeout_time = sess->last_heard +
+ (f64) nat44_session_get_timeout (sm, sess);
+ if (now >= sess_timeout_time)
+ timed_out++;
+
+ switch (sess->in2out.protocol)
+ {
+ case SNAT_PROTOCOL_ICMP:
+ icmp_sessions++;
+ break;
+ case SNAT_PROTOCOL_TCP:
+ tcp_sessions++;
+ if (sess->state)
+ transitory++;
+ else
+ established++;
+ break;
+ case SNAT_PROTOCOL_UDP:
+ default:
+ udp_sessions++;
+ break;
+
+ }
+
+ elt_index = elt->next;
+ elt = pool_elt_at_index (tsm->list_pool, elt_index);
+ session_index = elt->value;
+ }
+ }
+
+ s = format (s, "%U: %d dynamic translations, %d static translations\n",
+ format_ip4_address, &u->addr, u->nsessions, u->nstaticsessions);
+ s = format (s, "\t%u timed out, %u transitory, %u established\n",
+ timed_out, transitory, established);
+ s = format (s, "\t%u tcp sessions, %u udp sessions, %u icmp sessions\n",
+ tcp_sessions, udp_sessions, icmp_sessions);
+
+ return s;
+}
+
+u8 *
format_snat_static_mapping (u8 * s, va_list * args)
{
snat_static_mapping_t *m = va_arg (*args, snat_static_mapping_t *);
diff --git a/src/plugins/nat/out2in.c b/src/plugins/nat/out2in.c
index 144f324dbf4..f920599b059 100755
--- a/src/plugins/nat/out2in.c
+++ b/src/plugins/nat/out2in.c
@@ -188,9 +188,6 @@ create_session_for_static_mapping (snat_main_t * sm,
udp_header_t *udp0;
nat44_is_idle_session_ctx_t ctx0;
- nat44_session_try_cleanup (&in2out.addr, in2out.fib_index, thread_index,
- now);
-
if (PREDICT_FALSE (nat44_maximum_sessions_exceeded (sm, thread_index)))
{
b0->error = node->errors[SNAT_OUT2IN_ERROR_MAX_SESSIONS_EXCEEDED];
diff --git a/src/plugins/nat/out2in_ed.c b/src/plugins/nat/out2in_ed.c
index 91b8d5a8aae..420b7b7a863 100644
--- a/src/plugins/nat/out2in_ed.c
+++ b/src/plugins/nat/out2in_ed.c
@@ -203,8 +203,6 @@ create_session_for_static_mapping_ed (snat_main_t * sm,
snat_session_key_t eh_key;
nat44_is_idle_session_ctx_t ctx;
- nat44_session_try_cleanup (&l_key.addr, l_key.fib_index, thread_index, now);
-
if (PREDICT_FALSE (nat44_maximum_sessions_exceeded (sm, thread_index)))
{
b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
@@ -764,6 +762,21 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
}
s0 = pool_elt_at_index (tsm->sessions, value0.value);
+ // drop if session expired
+ u64 sess_timeout_time;
+ sess_timeout_time = s0->last_heard +
+ (f64) nat44_session_get_timeout (sm, s0);
+ if (now >= sess_timeout_time)
+ {
+ // delete session
+ nat_free_session_data (sm, s0, thread_index, 0);
+ nat44_delete_session (sm, s0, thread_index);
+
+ next0 = NAT_NEXT_DROP;
+ goto trace0;
+ }
+ //
+
old_addr0 = ip0->dst_address.as_u32;
new_addr0 = ip0->dst_address.as_u32 = s0->in2out.addr.as_u32;
vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
diff --git a/src/plugins/nat/test/test_nat.py b/src/plugins/nat/test/test_nat.py
index d16204e7217..89af40c4d18 100644
--- a/src/plugins/nat/test/test_nat.py
+++ b/src/plugins/nat/test/test_nat.py
@@ -6886,79 +6886,6 @@ class TestNAT44EndpointDependent(MethodHolder):
self.pg0.remote_ip4)
self.assertEqual(users[0].nsessions, 1)
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_session_limit_per_user(self):
- """ Maximum sessions per user limit """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4,
- src_address=self.pg2.local_ip4,
- path_mtu=512,
- template_interval=10)
- self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
- tcp_transitory=240, icmp=60)
-
- # get maximum number of translations per user
- nat44_config = self.vapi.nat_show_config()
-
- pkts = []
- for port in range(0, nat44_config.max_translations_per_user):
- 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=1025 + port, dport=1025 + port))
- pkts.append(p)
-
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
-
- self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
- src_port=self.ipfix_src_port,
- enable=1)
-
- 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()
- capture = self.pg1.assert_nothing_captured()
-
- # verify IPFIX logging
- self.vapi.ipfix_flush()
- sleep(1)
- capture = self.pg2.get_capture(10)
- ipfix = IPFIXDecoder()
- # first load template
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- if p.haslayer(Template):
- ipfix.add_template(p.getlayer(Template))
- # verify events in data set
- for p in capture:
- if p.haslayer(Data):
- data = ipfix.decode_data_set(p.getlayer(Set))
- self.verify_ipfix_max_entries_per_user(
- data,
- nat44_config.max_translations_per_user,
- self.pg0.remote_ip4)
-
- 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 test_syslog_sess(self):
""" Test syslog session creation and deletion """
self.vapi.syslog_set_filter(