aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilip Varga <fivarga@cisco.com>2020-04-19 19:44:49 +0200
committerOle Trøan <otroan@employees.org>2020-05-06 08:46:45 +0000
commitc611f36bbc75a7157bbec26a78178872ddc5441f (patch)
treed1ad9d56d69f7e8b6284ab5d8d25c0671cdd5f59
parente4deacc4220511c5ee93eca6b059d2a64ab1d36c (diff)
nat: enable force session cleanup
Force session cleanup drops NAT db. Also fixing user specific cli/api calls. Type: improvement Change-Id: Ia3e25fcf07fe5fb9a83d55c03fe90aca727b41ac Signed-off-by: Filip Varga <fivarga@cisco.com>
-rwxr-xr-xsrc/plugins/nat/nat.c115
-rw-r--r--src/plugins/nat/nat.h16
-rw-r--r--src/plugins/nat/nat44/inlines.h25
-rw-r--r--src/plugins/nat/nat44_cli.c67
-rw-r--r--src/plugins/nat/nat_format.c86
-rw-r--r--src/plugins/nat/test/test_nat.py69
6 files changed, 236 insertions, 142 deletions
diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c
index 7cb0b53368c..c30324b7d9e 100755
--- a/src/plugins/nat/nat.c
+++ b/src/plugins/nat/nat.c
@@ -3923,6 +3923,76 @@ nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port,
s->total_bytes = total_bytes;
}
+void
+nat44_db_init (snat_main_per_thread_data_t * tsm)
+{
+ snat_main_t *sm = &snat_main;
+
+ pool_alloc (tsm->sessions, 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",
+ sm->translation_buckets,
+ sm->translation_memory_size);
+ clib_bihash_set_kvp_format_fn_16_8 (&tsm->in2out_ed,
+ format_ed_session_kvp);
+ clib_bihash_init_16_8 (&tsm->out2in_ed, "out2in-ed",
+ sm->translation_buckets,
+ sm->translation_memory_size);
+ clib_bihash_set_kvp_format_fn_16_8 (&tsm->out2in_ed,
+ format_ed_session_kvp);
+ }
+ else
+ {
+ clib_bihash_init_8_8 (&tsm->in2out, "in2out",
+ sm->translation_buckets,
+ sm->translation_memory_size);
+ clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out, format_session_kvp);
+ clib_bihash_init_8_8 (&tsm->out2in, "out2in",
+ sm->translation_buckets,
+ sm->translation_memory_size);
+ clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in, format_session_kvp);
+ }
+
+ // TODO: resolve static mappings (put only to !ED)
+ pool_alloc (tsm->list_pool, sm->max_translations);
+ clib_bihash_init_8_8 (&tsm->user_hash, "users", sm->user_buckets,
+ sm->user_memory_size);
+ clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash, format_user_kvp);
+}
+
+void
+nat44_db_free (snat_main_per_thread_data_t * tsm)
+{
+ snat_main_t *sm = &snat_main;
+
+ pool_free (tsm->sessions);
+ pool_free (tsm->global_lru_pool);
+
+ if (sm->endpoint_dependent)
+ {
+ clib_bihash_free_16_8 (&tsm->in2out_ed);
+ clib_bihash_free_16_8 (&tsm->out2in_ed);
+ }
+ else
+ {
+ clib_bihash_free_8_8 (&tsm->in2out);
+ clib_bihash_free_8_8 (&tsm->out2in);
+ }
+
+ // TODO: resolve static mappings (put only to !ED)
+ pool_free (tsm->users);
+ pool_free (tsm->list_pool);
+ clib_bihash_free_8_8 (&tsm->user_hash);
+}
+
static clib_error_t *
snat_config (vlib_main_t * vm, unformat_input_t * input)
{
@@ -4121,52 +4191,9 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
/* *INDENT-OFF* */
vec_foreach (tsm, sm->per_thread_data)
{
- 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",
- translation_buckets,
- translation_memory_size);
- clib_bihash_set_kvp_format_fn_16_8 (&tsm->in2out_ed,
- format_ed_session_kvp);
-
- clib_bihash_init_16_8 (&tsm->out2in_ed, "out2in-ed",
- translation_buckets,
- translation_memory_size);
- clib_bihash_set_kvp_format_fn_16_8 (&tsm->out2in_ed,
- format_ed_session_kvp);
- }
- else
- {
- clib_bihash_init_8_8 (&tsm->in2out, "in2out",
- translation_buckets,
- translation_memory_size);
- clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out,
- format_session_kvp);
-
- clib_bihash_init_8_8 (&tsm->out2in, "out2in",
- translation_buckets,
- translation_memory_size);
- clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in,
- format_session_kvp);
- }
-
- clib_bihash_init_8_8 (&tsm->user_hash, "users", user_buckets,
- user_memory_size);
- clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash,
- format_user_kvp);
+ nat44_db_init (tsm);
}
/* *INDENT-ON* */
-
}
else
{
diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h
index 9331901a3bc..bc998da9982 100644
--- a/src/plugins/nat/nat.h
+++ b/src/plugins/nat/nat.h
@@ -716,7 +716,6 @@ 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;
@@ -1276,6 +1275,21 @@ int nat44_set_session_limit (u32 session_limit, u32 vrf_id);
void
nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
u32 thread_index, u8 is_ha);
+
+/**
+ * @brief Initialize NAT44 data
+ *
+ * @param tsm per thread data
+ */
+void nat44_db_init (snat_main_per_thread_data_t * tsm);
+
+/**
+ * @brief Free NAT44 data
+ *
+ * @param tsm per thread data
+ */
+void nat44_db_free (snat_main_per_thread_data_t * tsm);
+
/**
* @brief Find or create NAT user
*
diff --git a/src/plugins/nat/nat44/inlines.h b/src/plugins/nat/nat44/inlines.h
index 229daa2425e..a5118ea2fa6 100644
--- a/src/plugins/nat/nat44/inlines.h
+++ b/src/plugins/nat/nat44/inlines.h
@@ -78,6 +78,28 @@ nat44_global_lru_insert (snat_main_per_thread_data_t * tsm,
}
static_always_inline void
+nat44_sessions_clear ()
+{
+ snat_main_t *sm = &snat_main;
+ snat_main_per_thread_data_t *tsm;
+
+ /* *INDENT-OFF* */
+ vec_foreach (tsm, sm->per_thread_data)
+ {
+ u32 ti;
+
+ nat44_db_free (tsm);
+ nat44_db_init (tsm);
+
+ ti = tsm->snat_thread_index;
+ // clear per thread session counters
+ vlib_set_simple_counter (&sm->total_users, ti, 0, 0);
+ vlib_set_simple_counter (&sm->total_sessions, ti, 0, 0);
+ }
+ /* *INDENT-ON* */
+}
+
+static_always_inline void
nat44_user_del_sessions (snat_user_t * u, u32 thread_index)
{
dlist_elt_t *elt;
@@ -113,6 +135,9 @@ nat44_user_del (ip4_address_t * addr, u32 fib_index)
snat_user_key_t user_key;
clib_bihash_kv_8_8_t kv, value;
+ if (sm->deterministic || sm->endpoint_dependent)
+ return rv;
+
user_key.addr.as_u32 = addr->as_u32;
user_key.fib_index = fib_index;
kv.key = user_key.as_u64;
diff --git a/src/plugins/nat/nat44_cli.c b/src/plugins/nat/nat44_cli.c
index fe08832c641..ad4c1c8fdbd 100644
--- a/src/plugins/nat/nat44_cli.c
+++ b/src/plugins/nat/nat44_cli.c
@@ -27,8 +27,15 @@
#include <vnet/fib/fib_table.h>
#include <nat/nat_ha.h>
+
+#define UNSUPPORTED_IN_DET_OR_ED_MODE_STR \
+ "This command is unsupported in deterministic or endpoint dependent mode"
+#define UNSUPPORTED_IN_DET_OR_NON_ED_MODE_STR \
+ "This command is unsupported in deterministic or non endpoint dependent mode"
#define UNSUPPORTED_IN_DET_MODE_STR \
"This command is unsupported in deterministic mode"
+#define SUPPORTED_ONLY_IN_ED_MODE_STR \
+ "This command is supported only in endpoint dependent mode"
#define SUPPORTED_ONLY_IN_DET_MODE_STR \
"This command is supported only in deterministic mode"
@@ -638,7 +645,7 @@ nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input,
snat_session_t *s;
if (sm->deterministic || !sm->endpoint_dependent)
- return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
+ return clib_error_return (0, UNSUPPORTED_IN_DET_OR_NON_ED_MODE_STR);
// print session configuration values
vlib_cli_output (vm, "max translations: %u", sm->max_translations);
@@ -1474,11 +1481,11 @@ nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
{
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;
+ snat_main_t *sm = &snat_main;
- int detail = 0, metrics = 0;
- snat_user_t *u;
+ int detail = 0;
int i = 0;
if (sm->deterministic)
@@ -1491,8 +1498,6 @@ nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * 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'",
@@ -1503,7 +1508,11 @@ nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
unformat_free (line_input);
print:
- vlib_cli_output (vm, "NAT44 sessions:");
+ if (!sm->endpoint_dependent)
+ vlib_cli_output (vm, "NAT44 sessions:");
+ else
+ vlib_cli_output (vm, "NAT44 ED sessions:");
+
/* *INDENT-OFF* */
vec_foreach_index (i, sm->per_thread_data)
{
@@ -1512,19 +1521,21 @@ print:
vlib_cli_output (vm, "-------- thread %d %s: %d sessions --------\n",
i, vlib_worker_threads[i].name,
pool_elts (tsm->sessions));
- if (metrics)
+
+ if (!sm->endpoint_dependent)
{
- u64 now = vlib_time_now (sm->vlib_main);
+ snat_user_t *u;
pool_foreach (u, tsm->users,
({
- vlib_cli_output (vm, " %U", format_snat_user_v2, tsm, u, now);
+ vlib_cli_output (vm, " %U", format_snat_user, tsm, u, detail);
}));
}
else
{
- pool_foreach (u, tsm->users,
+ snat_session_t *s;
+ pool_foreach (s, tsm->sessions,
({
- vlib_cli_output (vm, " %U", format_snat_user, tsm, u, detail);
+ vlib_cli_output (vm, " %U\n", format_snat_session, tsm, s);
}));
}
}
@@ -1586,8 +1597,8 @@ nat44_del_user_command_fn (vlib_main_t * vm,
u32 fib_index = 0;
int rv;
- if (sm->deterministic)
- return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
+ if (sm->deterministic || sm->endpoint_dependent)
+ return clib_error_return (0, UNSUPPORTED_IN_DET_OR_ED_MODE_STR);
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
@@ -1621,6 +1632,21 @@ done:
}
static clib_error_t *
+nat44_clear_sessions_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ snat_main_t *sm = &snat_main;
+ clib_error_t *error = 0;
+
+ if (sm->deterministic)
+ return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
+
+ nat44_sessions_clear ();
+ return error;
+}
+
+static clib_error_t *
nat44_del_session_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
@@ -2655,6 +2681,19 @@ VLIB_CLI_COMMAND (nat44_del_user_command, static) = {
/*?
* @cliexpar
+ * @cliexstart{clear nat44 sessions}
+ * To clear all NAT44 sessions
+ * vpp# clear nat44 sessions
+ * @cliexend
+?*/
+VLIB_CLI_COMMAND (nat44_clear_sessions_command, static) = {
+ .path = "clear nat44 sessions",
+ .short_help = "clear nat44 sessions",
+ .function = nat44_clear_sessions_command_fn,
+};
+
+/*?
+ * @cliexpar
* @cliexstart{nat44 del session}
* To administratively delete NAT44 session by inside address and port use:
* vpp# nat44 del session in 10.0.0.3:6303 tcp
diff --git a/src/plugins/nat/nat_format.c b/src/plugins/nat/nat_format.c
index 71bdaa6662c..b9241545096 100644
--- a/src/plugins/nat/nat_format.c
+++ b/src/plugins/nat/nat_format.c
@@ -117,7 +117,7 @@ format_snat_session_state (u8 * s, va_list * args)
u8 *
format_snat_session (u8 * s, va_list * args)
{
- snat_main_per_thread_data_t *sm =
+ snat_main_per_thread_data_t *tsm =
va_arg (*args, snat_main_per_thread_data_t *);
snat_session_t *sess = va_arg (*args, snat_session_t *);
@@ -153,7 +153,7 @@ format_snat_session (u8 * s, va_list * args)
clib_net_to_host_u16 (sess->ext_host_port));
}
}
- s = format (s, " index %llu\n", sess - sm->sessions);
+ s = format (s, " index %llu\n", sess - tsm->sessions);
s = format (s, " last heard %.2f\n", sess->last_heard);
s = format (s, " total pkts %d, total bytes %lld\n",
sess->total_pkts, sess->total_bytes);
@@ -174,8 +174,6 @@ format_snat_session (u8 * s, va_list * args)
u8 *
format_snat_user (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 *);
@@ -204,7 +202,7 @@ format_snat_user (u8 * s, va_list * args)
{
sess = pool_elt_at_index (tsm->sessions, session_index);
- s = format (s, " %U\n", format_snat_session, sm, sess);
+ s = format (s, " %U\n", format_snat_session, tsm, sess);
elt_index = elt->next;
elt = pool_elt_at_index (tsm->list_pool, elt_index);
@@ -216,84 +214,6 @@ 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/test/test_nat.py b/src/plugins/nat/test/test_nat.py
index 2c0fa1017d6..1cddc405f07 100644
--- a/src/plugins/nat/test/test_nat.py
+++ b/src/plugins/nat/test/test_nat.py
@@ -1442,6 +1442,38 @@ class TestNAT44(MethodHolder):
def tearDownClass(cls):
super(TestNAT44, cls).tearDownClass()
+ def test_clear_sessions(self):
+ """ NAT44 session clearing test """
+
+ 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)
+
+ nat_config = self.vapi.nat_show_config()
+ self.assertEqual(0, nat_config.endpoint_dependent)
+
+ pkts = self.create_stream_in(self.pg0, self.pg1)
+ self.pg0.add_stream(pkts)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ capture = self.pg1.get_capture(len(pkts))
+ self.verify_capture_out(capture)
+
+ sessions = self.statistics.get_counter('/nat44/total-sessions')
+ self.assertTrue(sessions[0][0] > 0)
+ self.logger.info("sessions before clearing: %s" % sessions[0][0])
+
+ self.vapi.cli("clear nat44 sessions")
+
+ sessions = self.statistics.get_counter('/nat44/total-sessions')
+ self.assertEqual(sessions[0][0], 0)
+ self.logger.info("sessions after clearing: %s" % sessions[0][0])
+
def test_dynamic(self):
""" NAT44 dynamic translation test """
self.nat44_add_address(self.nat_addr)
@@ -4565,6 +4597,43 @@ class TestNAT44EndpointDependent(MethodHolder):
self.reass_hairpinning(proto=IP_PROTOS.udp)
self.reass_hairpinning(proto=IP_PROTOS.icmp)
+ def test_clear_sessions(self):
+ """ NAT44 ED session clearing test """
+
+ 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)
+
+ nat_config = self.vapi.nat_show_config()
+ self.assertEqual(1, nat_config.endpoint_dependent)
+
+ pkts = self.create_stream_in(self.pg0, self.pg1)
+ self.pg0.add_stream(pkts)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ capture = self.pg1.get_capture(len(pkts))
+ self.verify_capture_out(capture)
+
+ sessions = self.statistics.get_counter('/nat44/total-sessions')
+ self.assertTrue(sessions[0][0] > 0)
+ self.logger.info("sessions before clearing: %s" % sessions[0][0])
+
+ # just for testing purposes
+ self.logger.info(self.vapi.cli("show nat44 summary"))
+
+ self.vapi.cli("clear nat44 sessions")
+
+ self.logger.info(self.vapi.cli("show nat44 summary"))
+
+ sessions = self.statistics.get_counter('/nat44/total-sessions')
+ self.assertEqual(sessions[0][0], 0)
+ self.logger.info("sessions after clearing: %s" % sessions[0][0])
+
def test_dynamic(self):
""" NAT44 dynamic translation test """