aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/nat/nat.c526
-rw-r--r--src/plugins/nat/nat.h44
-rw-r--r--src/plugins/nat/nat44-ei/nat44_ei.c787
-rw-r--r--src/plugins/nat/nat44-ei/nat44_ei.h98
-rw-r--r--src/plugins/nat/nat44-ei/nat44_ei_in2out.c27
-rw-r--r--src/plugins/nat/nat44-ei/nat44_ei_out2in.c48
-rw-r--r--src/plugins/nat/nat44_api.c13
-rw-r--r--src/plugins/nat/nat44_cli.c24
8 files changed, 1216 insertions, 351 deletions
diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c
index 156b6ddf369..81af143ab2c 100644
--- a/src/plugins/nat/nat.c
+++ b/src/plugins/nat/nat.c
@@ -40,6 +40,39 @@
snat_main_t snat_main;
+#define skip_if_disabled() \
+ do \
+ { \
+ snat_main_t *sm = &snat_main; \
+ if (PREDICT_FALSE (!sm->enabled)) \
+ return; \
+ } \
+ while (0)
+
+#define fail_if_enabled() \
+ do \
+ { \
+ snat_main_t *sm = &snat_main; \
+ if (PREDICT_FALSE (sm->enabled)) \
+ { \
+ nat_log_err ("plugin enabled"); \
+ return 1; \
+ } \
+ } \
+ while (0)
+
+#define fail_if_disabled() \
+ do \
+ { \
+ snat_main_t *sm = &snat_main; \
+ if (PREDICT_FALSE (!sm->enabled)) \
+ { \
+ nat_log_err ("plugin disabled"); \
+ return 1; \
+ } \
+ } \
+ while (0)
+
/* *INDENT-OFF* */
/* Hook up input features */
VNET_FEATURE_INIT (nat_pre_in2out, static) = {
@@ -181,6 +214,11 @@ VLIB_PLUGIN_REGISTER () = {
};
/* *INDENT-ON* */
+static void nat44_ed_db_init (u32 translations, u32 translation_buckets,
+ u32 user_buckets);
+
+static void nat44_ed_db_free ();
+
static u32
nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip,
u32 rx_fib_index, u8 is_output);
@@ -189,7 +227,7 @@ static u32
nat44_ed_get_worker_in2out_cb (ip4_header_t * ip, u32 rx_fib_index,
u8 is_output);
-static u32 nat_calc_bihash_buckets (u32 n_elts);
+u32 nat_calc_bihash_buckets (u32 n_elts);
u8 *
format_session_kvp (u8 * s, va_list * args)
@@ -647,16 +685,11 @@ is_snat_address_used_in_static_mapping (snat_main_t * sm, ip4_address_t addr)
}
static void
-snat_add_static_mapping_when_resolved (snat_main_t * sm,
- ip4_address_t l_addr,
- u16 l_port,
- u32 sw_if_index,
- u16 e_port,
- u32 vrf_id,
- nat_protocol_t proto,
- int addr_only, int is_add, u8 * tag,
- int twice_nat, int out2in_only,
- int identity_nat,
+snat_add_static_mapping_when_resolved (snat_main_t *sm, ip4_address_t l_addr,
+ u16 l_port, u32 sw_if_index, u16 e_port,
+ u32 vrf_id, nat_protocol_t proto,
+ int addr_only, u8 *tag, int twice_nat,
+ int out2in_only, int identity_nat,
ip4_address_t pool_addr, int exact)
{
snat_static_map_resolve_t *rp;
@@ -669,7 +702,6 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm,
rp->vrf_id = vrf_id;
rp->proto = proto;
rp->addr_only = addr_only;
- rp->is_add = is_add;
rp->twice_nat = twice_nat;
rp->out2in_only = out2in_only;
rp->identity_nat = identity_nat;
@@ -678,7 +710,7 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm,
rp->exact = exact;
}
-static u32
+u32
get_thread_idx_by_port (u16 e_port)
{
snat_main_t *sm = &snat_main;
@@ -738,12 +770,14 @@ nat_ed_static_mapping_del_sessions (snat_main_t * sm,
vec_free (indexes_to_free);
}
-int
-snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
- u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
- u32 sw_if_index, nat_protocol_t proto, int is_add,
- twice_nat_type_t twice_nat, u8 out2in_only, u8 * tag,
- u8 identity_nat, ip4_address_t pool_addr, int exact)
+static_always_inline int
+nat44_ed_add_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
+ u16 l_port, u16 e_port, u32 vrf_id,
+ int addr_only, u32 sw_if_index,
+ nat_protocol_t proto, int is_add,
+ twice_nat_type_t twice_nat, u8 out2in_only,
+ u8 *tag, u8 identity_nat,
+ ip4_address_t pool_addr, int exact)
{
snat_main_t *sm = &snat_main;
snat_static_mapping_t *m;
@@ -803,10 +837,9 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
if (rp_match)
return VNET_API_ERROR_VALUE_EXIST;
- snat_add_static_mapping_when_resolved
- (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
- addr_only, is_add, tag, twice_nat, out2in_only,
- identity_nat, pool_addr, exact);
+ snat_add_static_mapping_when_resolved (
+ sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto, addr_only,
+ tag, twice_nat, out2in_only, identity_nat, pool_addr, exact);
/* DHCP resolution required? */
if (first_int_addr == 0)
@@ -1002,10 +1035,12 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
else
tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
- init_nat_kv (&kv, m->local_addr, m->local_port, fib_index, m->proto,
- m - sm->static_mappings);
if (!out2in_only)
- clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
+ {
+ init_nat_kv (&kv, m->local_addr, m->local_port, fib_index, m->proto,
+ m - sm->static_mappings);
+ clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
+ }
init_nat_kv (&kv, m->external_addr, m->external_port, 0, m->proto,
m - sm->static_mappings);
@@ -1184,6 +1219,31 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
}
int
+snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
+ u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
+ u32 sw_if_index, nat_protocol_t proto, int is_add,
+ twice_nat_type_t twice_nat, u8 out2in_only, u8 *tag,
+ u8 identity_nat, ip4_address_t pool_addr, int exact)
+{
+ snat_main_t *sm = &snat_main;
+ int rv;
+
+ if (sm->endpoint_dependent)
+ {
+ rv = nat44_ed_add_del_static_mapping (
+ l_addr, e_addr, l_port, e_port, vrf_id, addr_only, sw_if_index, proto,
+ is_add, twice_nat, out2in_only, tag, identity_nat, pool_addr, exact);
+ }
+ else
+ {
+ rv = nat44_ei_add_del_static_mapping (
+ l_addr, e_addr, l_port, e_port, proto, sw_if_index, vrf_id, addr_only,
+ identity_nat, tag, is_add);
+ }
+ return rv;
+}
+
+int
nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
nat_protocol_t proto,
nat44_lb_addr_port_t * locals, u8 is_add,
@@ -2655,51 +2715,34 @@ nat_init (vlib_main_t * vm)
VLIB_INIT_FUNCTION (nat_init);
-int
-nat44_plugin_enable (nat44_config_t c)
+static int
+nat44_ed_plugin_enable (nat44_config_t c)
{
snat_main_t *sm = &snat_main;
- u32 static_mapping_buckets = 1024;
- u32 static_mapping_memory_size = 64 << 20;
- if (sm->enabled)
+ if (c.static_mapping_only && !c.connection_tracking)
{
- nat_log_err ("nat44 is enabled");
+ nat_log_err ("unsupported combination of configuration");
return 1;
}
- // c.static_mapping_only + c.connection_tracking
- // - supported in NAT EI & NAT ED
- // c.out2in_dpo, c.static_mapping_only
- // - supported in NAT EI
-
- if (c.endpoint_dependent)
- {
- if ((c.static_mapping_only && !c.connection_tracking) || c.out2in_dpo)
- {
- nat_log_err ("unsupported combination of configuration");
- return 1;
- }
- if (c.users || c.user_sessions)
- {
- nat_log_err ("unsupported combination of configuration");
- return 1;
- }
- }
-
- nat_reset_timeouts (&sm->timeouts);
-
// nat44 feature configuration
sm->endpoint_dependent = c.endpoint_dependent;
sm->static_mapping_only = c.static_mapping_only;
sm->static_mapping_connection_tracking = c.connection_tracking;
+
+ // EI only feature (could break ED)
sm->out2in_dpo = c.out2in_dpo;
+
sm->forwarding_enabled = 0;
sm->mss_clamping = 0;
+ sm->pat = (!c.static_mapping_only ||
+ (c.static_mapping_only && c.connection_tracking));
if (!c.users)
c.users = 1024;
+ // EI only feature (could break ED)
sm->max_users_per_thread = c.users;
sm->user_buckets = nat_calc_bihash_buckets (c.users);
@@ -2709,65 +2752,34 @@ nat44_plugin_enable (nat44_config_t c)
sm->max_translations_per_thread = c.sessions;
sm->translation_buckets = nat_calc_bihash_buckets (c.sessions);
+ // ED only feature
vec_add1 (sm->max_translations_per_fib, sm->max_translations_per_thread);
+
+ // EI only feature (could break ED)
sm->max_translations_per_user
= c.user_sessions ? c.user_sessions : sm->max_translations_per_thread;
- sm->outside_vrf_id = c.outside_vrf;
- sm->outside_fib_index =
- fib_table_find_or_create_and_lock
- (FIB_PROTOCOL_IP4, c.outside_vrf, sm->fib_src_hi);
-
sm->inside_vrf_id = c.inside_vrf;
sm->inside_fib_index =
fib_table_find_or_create_and_lock
(FIB_PROTOCOL_IP4, c.inside_vrf, sm->fib_src_hi);
- if (c.endpoint_dependent)
- {
- sm->worker_out2in_cb = nat44_ed_get_worker_out2in_cb;
- sm->worker_in2out_cb = nat44_ed_get_worker_in2out_cb;
- sm->out2in_node_index = sm->ed_out2in_node_index;
- sm->in2out_node_index = sm->ed_in2out_node_index;
- sm->in2out_output_node_index = sm->ed_in2out_output_node_index;
- sm->icmp_match_out2in_cb = icmp_match_out2in_ed;
- sm->icmp_match_in2out_cb = icmp_match_in2out_ed;
-
- // try to move it into nat44_db_init,
- // consider static mapping requirements
- clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed",
- sm->translation_buckets, 0);
- clib_bihash_set_kvp_format_fn_16_8 (&sm->out2in_ed,
- format_ed_session_kvp);
+ sm->outside_vrf_id = c.outside_vrf;
+ sm->outside_fib_index = fib_table_find_or_create_and_lock (
+ FIB_PROTOCOL_IP4, c.outside_vrf, sm->fib_src_hi);
- nat_affinity_enable ();
- }
- else
- {
- sm->worker_out2in_cb = nat44_ei_get_out2in_worker_index;
- sm->worker_in2out_cb = nat44_ei_get_in2out_worker_index;
+ sm->worker_in2out_cb = nat44_ed_get_worker_in2out_cb;
+ sm->worker_out2in_cb = nat44_ed_get_worker_out2in_cb;
- sm->out2in_node_index = sm->ei_out2in_node_index;
- sm->in2out_node_index = sm->ei_in2out_node_index;
- sm->in2out_output_node_index = sm->ei_in2out_output_node_index;
- sm->icmp_match_out2in_cb = icmp_match_out2in_slow;
- sm->icmp_match_in2out_cb = icmp_match_in2out_slow;
+ sm->in2out_node_index = sm->ed_in2out_node_index;
+ sm->out2in_node_index = sm->ed_out2in_node_index;
- nat44_ei_plugin_enable ();
- }
+ sm->in2out_output_node_index = sm->ed_in2out_output_node_index;
- // c.static_mapping & c.connection_tracking require
- // session database
- if (!c.static_mapping_only
- || (c.static_mapping_only && c.connection_tracking))
+ if (sm->pat)
{
- snat_main_per_thread_data_t *tsm;
- /* *INDENT-OFF* */
- vec_foreach (tsm, sm->per_thread_data)
- {
- nat44_db_init (tsm);
- }
- /* *INDENT-ON* */
+ sm->icmp_match_in2out_cb = icmp_match_in2out_ed;
+ sm->icmp_match_out2in_cb = icmp_match_out2in_ed;
}
else
{
@@ -2775,19 +2787,14 @@ nat44_plugin_enable (nat44_config_t c)
sm->icmp_match_out2in_cb = icmp_match_out2in_fast;
}
- clib_bihash_init_8_8 (&sm->static_mapping_by_local,
- "static_mapping_by_local", static_mapping_buckets,
- static_mapping_memory_size);
- clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
- format_static_mapping_kvp);
+ nat44_ed_db_init (sm->max_translations_per_thread, sm->translation_buckets,
+ sm->user_buckets);
- clib_bihash_init_8_8 (&sm->static_mapping_by_external,
- "static_mapping_by_external",
- static_mapping_buckets, static_mapping_memory_size);
- clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
- format_static_mapping_kvp);
+ nat_affinity_enable ();
+
+ nat_reset_timeouts (&sm->timeouts);
- // last: reset counters
+ // TODO: function for reset counters
vlib_zero_simple_counter (&sm->total_users, 0);
vlib_zero_simple_counter (&sm->total_sessions, 0);
vlib_zero_simple_counter (&sm->user_limit_reached, 0);
@@ -2798,6 +2805,43 @@ nat44_plugin_enable (nat44_config_t c)
return 0;
}
+int
+nat44_plugin_enable (nat44_config_t c)
+{
+ fail_if_enabled ();
+
+ // c.static_mapping_only + c.connection_tracking
+ // - supported in NAT EI & NAT ED
+ // c.out2in_dpo, c.static_mapping_only
+ // - supported in NAT EI
+
+ if (c.endpoint_dependent)
+ {
+ if (c.out2in_dpo || c.users || c.user_sessions)
+ {
+ nat_log_err ("unsupported combination of configuration");
+ return 1;
+ }
+ return nat44_ed_plugin_enable (c);
+ }
+
+ // separation:
+ // for now just copy variables
+
+ nat44_ei_config_t ei_c = {
+ .inside_vrf = c.inside_vrf,
+ .outside_vrf = c.outside_vrf,
+ .users = c.users,
+ .sessions = c.sessions,
+ .user_sessions = c.user_sessions,
+ .out2in_dpo = c.out2in_dpo,
+ .static_mapping_only = c.static_mapping_only,
+ .connection_tracking = c.connection_tracking,
+ };
+
+ return nat44_ei_plugin_enable (ei_c);
+}
+
void
nat44_addresses_free (snat_address_t ** addresses)
{
@@ -2815,24 +2859,13 @@ nat44_addresses_free (snat_address_t ** addresses)
*addresses = 0;
}
-int
-nat44_plugin_disable ()
+static int
+nat44_ed_plugin_disable ()
{
snat_main_t *sm = &snat_main;
snat_interface_t *i, *vec;
int error = 0;
- if (!sm->enabled)
- {
- nat_log_err ("nat44 is disabled");
- return 1;
- }
-
- if (!sm->endpoint_dependent)
- {
- nat44_ei_plugin_disable ();
- }
-
// first unregister all nodes from interfaces
vec = vec_dup (sm->interfaces);
/* *INDENT-OFF* */
@@ -2874,28 +2907,9 @@ nat44_plugin_disable ()
vec_free (sm->max_translations_per_fib);
- if (sm->endpoint_dependent)
- {
- nat_affinity_disable ();
- clib_bihash_free_16_8 (&sm->out2in_ed);
- }
-
- clib_bihash_free_8_8 (&sm->static_mapping_by_local);
- clib_bihash_free_8_8 (&sm->static_mapping_by_external);
-
- if (!sm->static_mapping_only ||
- (sm->static_mapping_only && sm->static_mapping_connection_tracking))
- {
- snat_main_per_thread_data_t *tsm;
- /* *INDENT-OFF* */
- vec_foreach (tsm, sm->per_thread_data)
- {
- nat44_db_free (tsm);
- }
- /* *INDENT-ON* */
- }
+ nat_affinity_disable ();
- pool_free (sm->static_mappings);
+ nat44_ed_db_free ();
nat44_addresses_free (&sm->addresses);
nat44_addresses_free (&sm->twice_nat_addresses);
@@ -2917,10 +2931,21 @@ nat44_plugin_disable ()
return 0;
}
+int
+nat44_plugin_disable ()
+{
+ snat_main_t *sm = &snat_main;
+
+ fail_if_disabled ();
+
+ if (sm->endpoint_dependent)
+ return nat44_ed_plugin_disable ();
+ return nat44_ei_plugin_disable ();
+}
+
void
-snat_free_outside_address_and_port (snat_address_t * addresses,
- u32 thread_index,
- ip4_address_t * addr,
+snat_free_outside_address_and_port (snat_address_t *addresses,
+ u32 thread_index, ip4_address_t *addr,
u16 port, nat_protocol_t protocol)
{
snat_address_t *a;
@@ -3177,7 +3202,7 @@ nat44_add_del_address_dpo (ip4_address_t addr, u8 is_add)
}
static u32
-nat44_ed_get_worker_in2out_cb (ip4_header_t * ip, u32 rx_fib_index,
+nat44_ed_get_worker_in2out_cb (ip4_header_t *ip, u32 rx_fib_index,
u8 is_output)
{
snat_main_t *sm = &snat_main;
@@ -3435,7 +3460,7 @@ done:
return next_worker_index;
}
-static u32
+u32
nat_calc_bihash_buckets (u32 n_elts)
{
n_elts = n_elts / 2.5;
@@ -3504,16 +3529,15 @@ nat44_update_session_limit (u32 session_limit, u32 vrf_id)
return 0;
}
-void
-nat44_db_init (snat_main_per_thread_data_t * tsm)
+static void
+nat44_ed_worker_db_init (snat_main_per_thread_data_t *tsm, u32 translations,
+ u32 translation_buckets, u32 user_buckets)
{
- snat_main_t *sm = &snat_main;
-
- pool_alloc (tsm->sessions, sm->max_translations_per_thread);
- pool_alloc (tsm->lru_pool, sm->max_translations_per_thread);
-
dlist_elt_t *head;
+ pool_alloc (tsm->sessions, translations);
+ pool_alloc (tsm->lru_pool, translations);
+
pool_get (tsm->lru_pool, head);
tsm->tcp_trans_lru_head_index = head - tsm->lru_pool;
clib_dlist_init (tsm->lru_pool, tsm->tcp_trans_lru_head_index);
@@ -3534,87 +3558,122 @@ nat44_db_init (snat_main_per_thread_data_t * tsm)
tsm->unk_proto_lru_head_index = head - tsm->lru_pool;
clib_dlist_init (tsm->lru_pool, tsm->unk_proto_lru_head_index);
- if (sm->endpoint_dependent)
- {
- clib_bihash_init_16_8 (&tsm->in2out_ed, "in2out-ed",
- sm->translation_buckets, 0);
- clib_bihash_set_kvp_format_fn_16_8 (&tsm->in2out_ed,
- format_ed_session_kvp);
- /*
- clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed",
- sm->translation_buckets, 0);
- clib_bihash_set_kvp_format_fn_16_8 (&sm->out2in_ed,
- format_ed_session_kvp); */
- }
- else
- {
- clib_bihash_init_8_8 (&tsm->in2out, "in2out", sm->translation_buckets,
- 0);
- clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out, format_session_kvp);
- clib_bihash_init_8_8 (&tsm->out2in, "out2in", sm->translation_buckets,
- 0);
- clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in, format_session_kvp);
- }
+ clib_bihash_init_16_8 (&tsm->in2out_ed, "in2out-ed", translation_buckets, 0);
+ clib_bihash_set_kvp_format_fn_16_8 (&tsm->in2out_ed, format_ed_session_kvp);
// TODO: ED nat is not using these
// before removal large refactor required
- pool_alloc (tsm->list_pool, sm->max_translations_per_thread);
- clib_bihash_init_8_8 (&tsm->user_hash, "users", sm->user_buckets, 0);
+ pool_alloc (tsm->list_pool, translations);
+ clib_bihash_init_8_8 (&tsm->user_hash, "users", user_buckets, 0);
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)
+static void
+nat44_ed_db_init (u32 translations, u32 translation_buckets, u32 user_buckets)
{
snat_main_t *sm = &snat_main;
+ snat_main_per_thread_data_t *tsm;
+ u32 static_mapping_buckets = 1024;
+ u32 static_mapping_memory_size = 64 << 20;
- pool_free (tsm->sessions);
- pool_free (tsm->lru_pool);
+ clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed", translation_buckets, 0);
+ clib_bihash_set_kvp_format_fn_16_8 (&sm->out2in_ed, format_ed_session_kvp);
- if (sm->endpoint_dependent)
- {
- clib_bihash_free_16_8 (&tsm->in2out_ed);
- vec_free (tsm->per_vrf_sessions_vec);
- }
- else
+ clib_bihash_init_8_8 (&sm->static_mapping_by_local,
+ "static_mapping_by_local", static_mapping_buckets,
+ static_mapping_memory_size);
+ clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
+ format_static_mapping_kvp);
+
+ clib_bihash_init_8_8 (&sm->static_mapping_by_external,
+ "static_mapping_by_external", static_mapping_buckets,
+ static_mapping_memory_size);
+ clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
+ format_static_mapping_kvp);
+
+ if (sm->pat)
{
- clib_bihash_free_8_8 (&tsm->in2out);
- clib_bihash_free_8_8 (&tsm->out2in);
+ vec_foreach (tsm, sm->per_thread_data)
+ {
+ nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread,
+ sm->translation_buckets, sm->user_buckets);
+ }
}
+}
+
+static void
+nat44_ed_worker_db_free (snat_main_per_thread_data_t *tsm)
+{
+ pool_free (tsm->sessions);
+ pool_free (tsm->lru_pool);
+
+ clib_bihash_free_16_8 (&tsm->in2out_ed);
+ vec_free (tsm->per_vrf_sessions_vec);
// TODO: resolve static mappings (put only to !ED)
- pool_free (tsm->users);
pool_free (tsm->list_pool);
+ pool_free (tsm->users);
clib_bihash_free_8_8 (&tsm->user_hash);
}
-void
-nat44_sessions_clear ()
+static void
+nat44_ed_db_free ()
{
snat_main_t *sm = &snat_main;
snat_main_per_thread_data_t *tsm;
- if (sm->endpoint_dependent)
+ pool_free (sm->static_mappings);
+ clib_bihash_free_16_8 (&sm->out2in_ed);
+ clib_bihash_free_8_8 (&sm->static_mapping_by_local);
+ clib_bihash_free_8_8 (&sm->static_mapping_by_external);
+
+ if (sm->pat)
{
- clib_bihash_free_16_8 (&sm->out2in_ed);
- clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed",
- clib_max (1,
- sm->num_workers) *
- sm->translation_buckets, 0);
- clib_bihash_set_kvp_format_fn_16_8 (&sm->out2in_ed,
- format_ed_session_kvp);
+ vec_foreach (tsm, sm->per_thread_data)
+ {
+ nat44_ed_worker_db_free (tsm);
+ }
}
+}
- /* *INDENT-OFF* */
- vec_foreach (tsm, sm->per_thread_data)
+void
+nat44_ed_sessions_clear ()
+{
+ snat_main_t *sm = &snat_main;
+ snat_main_per_thread_data_t *tsm;
+
+ clib_bihash_free_16_8 (&sm->out2in_ed);
+ clib_bihash_init_16_8 (
+ &sm->out2in_ed, "out2in-ed",
+ clib_max (1, sm->num_workers) * sm->translation_buckets, 0);
+ clib_bihash_set_kvp_format_fn_16_8 (&sm->out2in_ed, format_ed_session_kvp);
+
+ if (sm->pat)
{
- nat44_db_free (tsm);
- nat44_db_init (tsm);
+ vec_foreach (tsm, sm->per_thread_data)
+ {
+
+ nat44_ed_worker_db_free (tsm);
+ nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread,
+ sm->translation_buckets, sm->user_buckets);
+ }
}
- /* *INDENT-ON* */
+ // TODO: function for reset counters
vlib_zero_simple_counter (&sm->total_users, 0);
vlib_zero_simple_counter (&sm->total_sessions, 0);
+ vlib_zero_simple_counter (&sm->user_limit_reached, 0);
+}
+
+void
+nat44_sessions_clear ()
+{
+ snat_main_t *sm = &snat_main;
+
+ if (sm->endpoint_dependent)
+ nat44_ed_sessions_clear ();
+ else
+ nat44_ei_sessions_clear ();
}
static void
@@ -3744,18 +3803,11 @@ match:
else
l_addr.as_u32 = rp->l_addr.as_u32;
/* Add the static mapping */
- rv = snat_add_static_mapping (l_addr,
- address[0],
- rp->l_port,
- rp->e_port,
- rp->vrf_id,
- rp->addr_only,
- ~0 /* sw_if_index */ ,
- rp->proto,
- rp->is_add, rp->twice_nat,
- rp->out2in_only, rp->tag,
- rp->identity_nat,
- rp->pool_addr, rp->exact);
+ rv = snat_add_static_mapping (
+ l_addr, address[0], rp->l_port, rp->e_port, rp->vrf_id,
+ rp->addr_only, ~0 /* sw_if_index */, rp->proto, 1,
+ rp->twice_nat, rp->out2in_only, rp->tag, rp->identity_nat,
+ rp->pool_addr, rp->exact);
if (rv)
nat_elog_notice_X1 ("snat_add_static_mapping returned %d",
"i4", rv);
@@ -3839,44 +3891,6 @@ snat_add_interface_address (snat_main_t * sm, u32 sw_if_index, int is_del,
}
int
-nat44_del_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
- nat_protocol_t proto, u32 vrf_id, int is_in)
-{
- snat_main_per_thread_data_t *tsm;
- clib_bihash_kv_8_8_t kv, value;
- ip4_header_t ip;
- u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
- snat_session_t *s;
- clib_bihash_8_8_t *t;
-
- if (sm->endpoint_dependent)
- return VNET_API_ERROR_UNSUPPORTED;
-
- ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
- if (sm->num_workers > 1)
- tsm =
- vec_elt_at_index (sm->per_thread_data,
- sm->worker_in2out_cb (&ip, fib_index, 0));
- else
- tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
-
- init_nat_k (&kv, *addr, port, fib_index, proto);
- t = is_in ? &tsm->in2out : &tsm->out2in;
- if (!clib_bihash_search_8_8 (t, &kv, &value))
- {
- if (pool_is_free_index (tsm->sessions, value.value))
- return VNET_API_ERROR_UNSPECIFIED;
-
- s = pool_elt_at_index (tsm->sessions, value.value);
- nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
- nat44_delete_session (sm, s, tsm - sm->per_thread_data);
- return 0;
- }
-
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-}
-
-int
nat44_del_ed_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
ip4_address_t * eh_addr, u16 eh_port, u8 proto,
u32 vrf_id, int is_in)
diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h
index af40409d267..58883d491aa 100644
--- a/src/plugins/nat/nat.h
+++ b/src/plugins/nat/nat.h
@@ -427,7 +427,6 @@ typedef struct
u32 flags;
int addr_only;
int twice_nat;
- int is_add;
int out2in_only;
int identity_nat;
int exact;
@@ -729,6 +728,9 @@ typedef struct snat_main_s
fib_source_t fib_src_hi;
fib_source_t fib_src_low;
+ /* pat - dynamic mapping enabled or conneciton tracking */
+ u8 pat;
+
/* nat44 plugin enabled */
u8 enabled;
@@ -1298,20 +1300,6 @@ int snat_add_interface_address (snat_main_t * sm, u32 sw_if_index, int is_del,
u8 twice_nat);
/**
- * @brief Delete NAT44 session
- *
- * @param addr IPv4 address
- * @param port L4 port number
- * @param proto L4 protocol
- * @param vrf_id VRF ID
- * @param is_in 1 = inside network address and port pair, 0 = outside
- *
- * @return 0 on success, non-zero value otherwise
- */
-int nat44_del_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
- nat_protocol_t proto, u32 vrf_id, int is_in);
-
-/**
* @brief Delete NAT44 endpoint-dependent session
*
* @param sm snat global configuration data
@@ -1357,20 +1345,6 @@ int nat44_set_session_limit (u32 session_limit, u32 vrf_id);
int nat44_update_session_limit (u32 session_limit, u32 vrf_id);
/**
- * @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 Free all NAT44 sessions
*/
void nat44_sessions_clear ();
@@ -1510,6 +1484,18 @@ typedef struct
u8 *format_user_kvp (u8 * s, va_list * args);
+u32 get_thread_idx_by_port (u16 e_port);
+
+u8 *format_static_mapping_kvp (u8 *s, va_list *args);
+
+u8 *format_session_kvp (u8 *s, va_list *args);
+
+u8 *format_user_kvp (u8 *s, va_list *args);
+
+u32 nat_calc_bihash_buckets (u32 n_elts);
+
+void nat44_addresses_free (snat_address_t **addresses);
+
#endif /* __included_nat_h__ */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/src/plugins/nat/nat44-ei/nat44_ei.c b/src/plugins/nat/nat44-ei/nat44_ei.c
index f50ccb9ba1b..00aa8e1b65b 100644
--- a/src/plugins/nat/nat44-ei/nat44_ei.c
+++ b/src/plugins/nat/nat44-ei/nat44_ei.c
@@ -36,18 +36,156 @@
#include <nat/nat44-ei/nat44_ei_inlines.h>
#include <nat/nat44-ei/nat44_ei.h>
+nat44_ei_main_t nat44_ei_main;
+
+static void nat44_ei_db_free ();
+
+static void nat44_ei_db_init (u32 translations, u32 translation_buckets,
+ u32 user_buckets);
+
int
-nat44_ei_plugin_enable ()
+nat44_ei_plugin_enable (nat44_ei_config_t c)
{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ snat_main_t *sm = &snat_main;
+
+ clib_memset (nm, 0, sizeof (*nm));
+
+ if (!c.users)
+ c.users = 1024;
+
+ if (!c.sessions)
+ c.sessions = 10 * 1024;
+
+ nm->rconfig = c;
+
+ nm->translations = c.sessions;
+ nm->translation_buckets = nat_calc_bihash_buckets (c.sessions);
+ nm->user_buckets = nat_calc_bihash_buckets (c.users);
+
+ // OBSOLETE
+
+ sm->static_mapping_only = c.static_mapping_only;
+ sm->static_mapping_connection_tracking = c.connection_tracking;
+ sm->out2in_dpo = c.out2in_dpo;
+ sm->forwarding_enabled = 0;
+ sm->mss_clamping = 0;
+ sm->pat = (!c.static_mapping_only ||
+ (c.static_mapping_only && c.connection_tracking));
+
+ sm->max_users_per_thread = c.users;
+ sm->max_translations_per_thread = c.sessions;
+ sm->translation_buckets = nat_calc_bihash_buckets (c.sessions);
+ sm->max_translations_per_user =
+ c.user_sessions ? c.user_sessions : sm->max_translations_per_thread;
+
+ sm->inside_vrf_id = c.inside_vrf;
+ sm->inside_fib_index = fib_table_find_or_create_and_lock (
+ FIB_PROTOCOL_IP4, c.inside_vrf, sm->fib_src_hi);
+
+ sm->outside_vrf_id = c.outside_vrf;
+ sm->outside_fib_index = fib_table_find_or_create_and_lock (
+ FIB_PROTOCOL_IP4, c.outside_vrf, sm->fib_src_hi);
+
+ sm->worker_in2out_cb = nat44_ei_get_in2out_worker_index;
+ sm->worker_out2in_cb = nat44_ei_get_out2in_worker_index;
+
+ sm->in2out_node_index = sm->ei_in2out_node_index;
+ sm->out2in_node_index = sm->ei_out2in_node_index;
+
+ sm->in2out_output_node_index = sm->ei_in2out_output_node_index;
+
+ if (sm->pat)
+ {
+ sm->icmp_match_in2out_cb = icmp_match_in2out_slow;
+ sm->icmp_match_out2in_cb = icmp_match_out2in_slow;
+ }
+ else
+ {
+ sm->icmp_match_in2out_cb = icmp_match_in2out_fast;
+ sm->icmp_match_out2in_cb = icmp_match_out2in_fast;
+ }
+
+ nat_reset_timeouts (&sm->timeouts);
+ nat44_ei_db_init (nm->translations, nm->translation_buckets,
+ nm->user_buckets);
nat44_ei_set_alloc_default ();
nat_ha_enable ();
+
+ // TODO: function for reset counters
+ vlib_zero_simple_counter (&sm->total_users, 0);
+ vlib_zero_simple_counter (&sm->total_sessions, 0);
+ vlib_zero_simple_counter (&sm->user_limit_reached, 0);
+
+ sm->enabled = 1;
+
return 0;
}
-void
+int
nat44_ei_plugin_disable ()
{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ snat_main_t *sm = &snat_main;
+ snat_interface_t *i, *vec;
+ int error = 0;
+
+ // first unregister all nodes from interfaces
+ vec = vec_dup (sm->interfaces);
+ vec_foreach (i, vec)
+ {
+ if (nat_interface_is_inside (i))
+ error = snat_interface_add_del (i->sw_if_index, 1, 1);
+ if (nat_interface_is_outside (i))
+ error = snat_interface_add_del (i->sw_if_index, 0, 1);
+
+ if (error)
+ {
+ nat_log_err ("error occurred while removing interface %u",
+ i->sw_if_index);
+ }
+ }
+ vec_free (vec);
+ sm->interfaces = 0;
+
+ vec = vec_dup (sm->output_feature_interfaces);
+ vec_foreach (i, vec)
+ {
+ if (nat_interface_is_inside (i))
+ error = snat_interface_add_del_output_feature (i->sw_if_index, 1, 1);
+ if (nat_interface_is_outside (i))
+ error = snat_interface_add_del_output_feature (i->sw_if_index, 0, 1);
+
+ if (error)
+ {
+ nat_log_err ("error occurred while removing interface %u",
+ i->sw_if_index);
+ }
+ }
+ vec_free (vec);
+ sm->output_feature_interfaces = 0;
+
nat_ha_disable ();
+ nat44_ei_db_free ();
+
+ nat44_addresses_free (&sm->addresses);
+ nat44_addresses_free (&sm->twice_nat_addresses);
+
+ vec_free (sm->to_resolve);
+ vec_free (sm->auto_add_sw_if_indices);
+ vec_free (sm->auto_add_sw_if_indices_twice_nat);
+
+ sm->to_resolve = 0;
+ sm->auto_add_sw_if_indices = 0;
+ sm->auto_add_sw_if_indices_twice_nat = 0;
+
+ sm->forwarding_enabled = 0;
+
+ sm->enabled = 0;
+ clib_memset (&nm->rconfig, 0, sizeof (nm->rconfig));
+ clib_memset (&sm->rconfig, 0, sizeof (sm->rconfig));
+
+ return error;
}
void
@@ -525,6 +663,651 @@ nat44_ei_set_alloc_mape (u16 psid, u16 psid_offset, u16 psid_length)
sm->psid_length = psid_length;
}
+static void
+nat44_ei_add_static_mapping_when_resolved (ip4_address_t l_addr, u16 l_port,
+ u16 e_port, nat_protocol_t proto,
+ u32 sw_if_index, u32 vrf_id,
+ int addr_only, int identity_nat,
+ u8 *tag)
+{
+ snat_main_t *sm = &snat_main;
+ snat_static_map_resolve_t *rp;
+
+ vec_add2 (sm->to_resolve, rp, 1);
+ clib_memset (rp, 0, sizeof (*rp));
+
+ rp->l_addr.as_u32 = l_addr.as_u32;
+ rp->l_port = l_port;
+ rp->e_port = e_port;
+ rp->sw_if_index = sw_if_index;
+ rp->vrf_id = vrf_id;
+ rp->proto = proto;
+ rp->addr_only = addr_only;
+ rp->identity_nat = identity_nat;
+ rp->tag = vec_dup (tag);
+}
+
+int
+nat44_ei_del_session (snat_main_t *sm, ip4_address_t *addr, u16 port,
+ nat_protocol_t proto, u32 vrf_id, int is_in)
+{
+ snat_main_per_thread_data_t *tsm;
+ clib_bihash_kv_8_8_t kv, value;
+ ip4_header_t ip;
+ u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
+ snat_session_t *s;
+ clib_bihash_8_8_t *t;
+
+ if (sm->endpoint_dependent)
+ return VNET_API_ERROR_UNSUPPORTED;
+
+ ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
+ if (sm->num_workers > 1)
+ tsm = vec_elt_at_index (sm->per_thread_data,
+ sm->worker_in2out_cb (&ip, fib_index, 0));
+ else
+ tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
+
+ init_nat_k (&kv, *addr, port, fib_index, proto);
+ t = is_in ? &tsm->in2out : &tsm->out2in;
+ if (!clib_bihash_search_8_8 (t, &kv, &value))
+ {
+ if (pool_is_free_index (tsm->sessions, value.value))
+ return VNET_API_ERROR_UNSPECIFIED;
+
+ s = pool_elt_at_index (tsm->sessions, value.value);
+ nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
+ nat44_delete_session (sm, s, tsm - sm->per_thread_data);
+ return 0;
+ }
+
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+}
+
+int
+nat44_ei_add_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
+ u16 l_port, u16 e_port, nat_protocol_t proto,
+ u32 sw_if_index, u32 vrf_id, u8 addr_only,
+ u8 identity_nat, u8 *tag, u8 is_add)
+{
+ snat_main_t *sm = &snat_main;
+ snat_static_mapping_t *m = 0;
+ clib_bihash_kv_8_8_t kv, value;
+ snat_address_t *a = 0;
+ u32 fib_index = ~0;
+ snat_interface_t *interface;
+ snat_main_per_thread_data_t *tsm;
+ snat_user_key_t u_key;
+ snat_user_t *u;
+ dlist_elt_t *head, *elt;
+ u32 elt_index, head_index;
+ u32 ses_index;
+ u64 user_index;
+ snat_session_t *s;
+ snat_static_map_resolve_t *rp, *rp_match = 0;
+ nat44_lb_addr_port_t *local;
+ u32 find = ~0;
+ int i;
+
+ if (sw_if_index != ~0)
+ {
+ ip4_address_t *first_int_addr;
+
+ for (i = 0; i < vec_len (sm->to_resolve); i++)
+ {
+ rp = sm->to_resolve + i;
+ if (rp->sw_if_index != sw_if_index ||
+ rp->l_addr.as_u32 != l_addr.as_u32 || rp->vrf_id != vrf_id ||
+ rp->addr_only != addr_only)
+ continue;
+
+ if (!addr_only)
+ {
+ if ((rp->l_port != l_port && rp->e_port != e_port) ||
+ rp->proto != proto)
+ continue;
+ }
+
+ rp_match = rp;
+ break;
+ }
+
+ /* Might be already set... */
+ first_int_addr = ip4_interface_first_address (
+ sm->ip4_main, sw_if_index, 0 /* just want the address */);
+
+ if (is_add)
+ {
+ if (rp_match)
+ return VNET_API_ERROR_VALUE_EXIST;
+
+ nat44_ei_add_static_mapping_when_resolved (
+ l_addr, l_port, e_port, proto, sw_if_index, vrf_id, addr_only,
+ identity_nat, tag);
+
+ /* DHCP resolution required? */
+ if (!first_int_addr)
+ return 0;
+
+ e_addr.as_u32 = first_int_addr->as_u32;
+ /* Identity mapping? */
+ if (l_addr.as_u32 == 0)
+ l_addr.as_u32 = e_addr.as_u32;
+ }
+ else
+ {
+ if (!rp_match)
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+
+ vec_del1 (sm->to_resolve, i);
+
+ if (!first_int_addr)
+ return 0;
+
+ e_addr.as_u32 = first_int_addr->as_u32;
+ /* Identity mapping? */
+ if (l_addr.as_u32 == 0)
+ l_addr.as_u32 = e_addr.as_u32;
+ }
+ }
+
+ init_nat_k (&kv, e_addr, addr_only ? 0 : e_port, 0, addr_only ? 0 : proto);
+ if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
+ m = pool_elt_at_index (sm->static_mappings, value.value);
+
+ if (is_add)
+ {
+ if (m)
+ {
+ // identity mapping for second vrf
+ if (is_identity_static_mapping (m))
+ {
+ pool_foreach (local, m->locals)
+ {
+ if (local->vrf_id == vrf_id)
+ return VNET_API_ERROR_VALUE_EXIST;
+ }
+ pool_get (m->locals, local);
+ local->vrf_id = vrf_id;
+ local->fib_index = fib_table_find_or_create_and_lock (
+ FIB_PROTOCOL_IP4, vrf_id, sm->fib_src_low);
+ init_nat_kv (&kv, m->local_addr, m->local_port, local->fib_index,
+ m->proto, m - sm->static_mappings);
+ clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
+ return 0;
+ }
+ return VNET_API_ERROR_VALUE_EXIST;
+ }
+
+ /* Convert VRF id to FIB index */
+ if (vrf_id != ~0)
+ {
+ fib_index = fib_table_find_or_create_and_lock (
+ FIB_PROTOCOL_IP4, vrf_id, sm->fib_src_low);
+ }
+ /* If not specified use inside VRF id from NAT44 plugin config */
+ else
+ {
+ fib_index = sm->inside_fib_index;
+ vrf_id = sm->inside_vrf_id;
+ fib_table_lock (fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low);
+ }
+
+ if (!identity_nat)
+ {
+ init_nat_k (&kv, l_addr, addr_only ? 0 : l_port, fib_index,
+ addr_only ? 0 : proto);
+ if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv,
+ &value))
+ return VNET_API_ERROR_VALUE_EXIST;
+ }
+
+ /* Find external address in allocated addresses and reserve port for
+ address and port pair mapping when dynamic translations enabled */
+ if (!(addr_only || sm->static_mapping_only))
+ {
+ for (i = 0; i < vec_len (sm->addresses); i++)
+ {
+ if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
+ {
+ a = sm->addresses + i;
+ /* External port must be unused */
+ switch (proto)
+ {
+#define _(N, j, n, s) \
+ case NAT_PROTOCOL_##N: \
+ if (a->busy_##n##_port_refcounts[e_port]) \
+ return VNET_API_ERROR_INVALID_VALUE; \
+ ++a->busy_##n##_port_refcounts[e_port]; \
+ if (e_port > 1024) \
+ { \
+ a->busy_##n##_ports++; \
+ a->busy_##n##_ports_per_thread[get_thread_idx_by_port (e_port)]++; \
+ } \
+ break;
+ foreach_nat_protocol
+#undef _
+ default : nat_elog_info ("unknown protocol");
+ return VNET_API_ERROR_INVALID_VALUE_2;
+ }
+ break;
+ }
+ }
+ /* External address must be allocated */
+ if (!a && (l_addr.as_u32 != e_addr.as_u32))
+ {
+ if (sw_if_index != ~0)
+ {
+ for (i = 0; i < vec_len (sm->to_resolve); i++)
+ {
+ rp = sm->to_resolve + i;
+ if (rp->addr_only)
+ continue;
+ if (rp->sw_if_index != sw_if_index &&
+ rp->l_addr.as_u32 != l_addr.as_u32 &&
+ rp->vrf_id != vrf_id && rp->l_port != l_port &&
+ rp->e_port != e_port && rp->proto != proto)
+ continue;
+
+ vec_del1 (sm->to_resolve, i);
+ break;
+ }
+ }
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
+ }
+
+ pool_get (sm->static_mappings, m);
+ clib_memset (m, 0, sizeof (*m));
+ m->tag = vec_dup (tag);
+ m->local_addr = l_addr;
+ m->external_addr = e_addr;
+
+ if (addr_only)
+ m->flags |= NAT_STATIC_MAPPING_FLAG_ADDR_ONLY;
+ else
+ {
+ m->local_port = l_port;
+ m->external_port = e_port;
+ m->proto = proto;
+ }
+
+ if (identity_nat)
+ {
+ m->flags |= NAT_STATIC_MAPPING_FLAG_IDENTITY_NAT;
+ pool_get (m->locals, local);
+ local->vrf_id = vrf_id;
+ local->fib_index = fib_index;
+ }
+ else
+ {
+ m->vrf_id = vrf_id;
+ m->fib_index = fib_index;
+ }
+
+ if (sm->num_workers > 1)
+ {
+ ip4_header_t ip = {
+ .src_address = m->local_addr,
+ };
+ vec_add1 (m->workers, sm->worker_in2out_cb (&ip, m->fib_index, 0));
+ tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
+ }
+ else
+ tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
+
+ init_nat_kv (&kv, m->local_addr, m->local_port, fib_index, m->proto,
+ m - sm->static_mappings);
+ clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
+
+ init_nat_kv (&kv, m->external_addr, m->external_port, 0, m->proto,
+ m - sm->static_mappings);
+ clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1);
+
+ /* Delete dynamic sessions matching local address (+ local port) */
+ // TODO: based on type of NAT EI/ED
+ if (!(sm->static_mapping_only))
+ {
+ u_key.addr = m->local_addr;
+ u_key.fib_index = m->fib_index;
+ kv.key = u_key.as_u64;
+ if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
+ {
+ user_index = value.value;
+ u = pool_elt_at_index (tsm->users, user_index);
+ if (u->nsessions)
+ {
+ 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);
+ ses_index = elt->value;
+ while (ses_index != ~0)
+ {
+ s = pool_elt_at_index (tsm->sessions, ses_index);
+ elt = pool_elt_at_index (tsm->list_pool, elt->next);
+ ses_index = elt->value;
+
+ if (snat_is_session_static (s))
+ continue;
+
+ if (!addr_only && s->in2out.port != m->local_port)
+ continue;
+
+ nat_free_session_data (sm, s, tsm - sm->per_thread_data,
+ 0);
+ nat44_delete_session (sm, s, tsm - sm->per_thread_data);
+
+ if (!addr_only)
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!m)
+ {
+ if (sw_if_index != ~0)
+ return 0;
+ else
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
+
+ if (identity_nat)
+ {
+ if (vrf_id == ~0)
+ vrf_id = sm->inside_vrf_id;
+
+ pool_foreach (local, m->locals)
+ {
+ if (local->vrf_id == vrf_id)
+ find = local - m->locals;
+ }
+ if (find == ~0)
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+
+ local = pool_elt_at_index (m->locals, find);
+ fib_index = local->fib_index;
+ pool_put (m->locals, local);
+ }
+ else
+ fib_index = m->fib_index;
+
+ /* Free external address port */
+ if (!(addr_only || sm->static_mapping_only))
+ {
+ for (i = 0; i < vec_len (sm->addresses); i++)
+ {
+ if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
+ {
+ a = sm->addresses + i;
+ switch (proto)
+ {
+#define _(N, j, n, s) \
+ case NAT_PROTOCOL_##N: \
+ --a->busy_##n##_port_refcounts[e_port]; \
+ if (e_port > 1024) \
+ { \
+ a->busy_##n##_ports--; \
+ a->busy_##n##_ports_per_thread[get_thread_idx_by_port (e_port)]--; \
+ } \
+ break;
+ foreach_nat_protocol
+#undef _
+ default : return VNET_API_ERROR_INVALID_VALUE_2;
+ }
+ break;
+ }
+ }
+ }
+
+ if (sm->num_workers > 1)
+ tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
+ else
+ tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
+
+ init_nat_k (&kv, m->local_addr, m->local_port, fib_index, m->proto);
+ clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0);
+
+ /* Delete session(s) for static mapping if exist */
+ if (!(sm->static_mapping_only) ||
+ (sm->static_mapping_only && sm->static_mapping_connection_tracking))
+ {
+ u_key.addr = m->local_addr;
+ u_key.fib_index = fib_index;
+ kv.key = u_key.as_u64;
+ nat44_ei_static_mapping_del_sessions (sm, tsm, u_key, addr_only,
+ e_addr, e_port);
+ }
+
+ fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low);
+ if (pool_elts (m->locals))
+ return 0;
+
+ init_nat_k (&kv, m->external_addr, m->external_port, 0, m->proto);
+ clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0);
+
+ vec_free (m->tag);
+ vec_free (m->workers);
+ /* Delete static mapping from pool */
+ pool_put (sm->static_mappings, m);
+ }
+
+ if (!addr_only || (l_addr.as_u32 == e_addr.as_u32))
+ return 0;
+
+ /* Add/delete external address to FIB */
+ pool_foreach (interface, sm->interfaces)
+ {
+ if (nat_interface_is_inside (interface) || sm->out2in_dpo)
+ continue;
+
+ snat_add_del_addr_to_fib (&e_addr, 32, interface->sw_if_index, is_add);
+ break;
+ }
+ pool_foreach (interface, sm->output_feature_interfaces)
+ {
+ if (nat_interface_is_inside (interface) || sm->out2in_dpo)
+ continue;
+
+ snat_add_del_addr_to_fib (&e_addr, 32, interface->sw_if_index, is_add);
+ break;
+ }
+ return 0;
+}
+
+int
+nat44_ei_static_mapping_match (ip4_address_t match_addr, u16 match_port,
+ u32 match_fib_index,
+ nat_protocol_t match_protocol,
+ ip4_address_t *mapping_addr, u16 *mapping_port,
+ u32 *mapping_fib_index, u8 by_external,
+ u8 *is_addr_only, u8 *is_identity_nat)
+{
+ snat_main_t *sm = &snat_main;
+ clib_bihash_kv_8_8_t kv, value;
+ snat_static_mapping_t *m;
+ u16 port;
+
+ if (by_external)
+ {
+ init_nat_k (&kv, match_addr, match_port, 0, match_protocol);
+ if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv,
+ &value))
+ {
+ /* Try address only mapping */
+ init_nat_k (&kv, match_addr, 0, 0, 0);
+ if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv,
+ &value))
+ return 1;
+ }
+ m = pool_elt_at_index (sm->static_mappings, value.value);
+
+ *mapping_fib_index = m->fib_index;
+ *mapping_addr = m->local_addr;
+ port = m->local_port;
+ }
+ else
+ {
+ init_nat_k (&kv, match_addr, match_port, match_fib_index,
+ match_protocol);
+ if (clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value))
+ {
+ /* Try address only mapping */
+ init_nat_k (&kv, match_addr, 0, match_fib_index, 0);
+ if (clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv,
+ &value))
+ return 1;
+ }
+ m = pool_elt_at_index (sm->static_mappings, value.value);
+
+ *mapping_fib_index = sm->outside_fib_index;
+ *mapping_addr = m->external_addr;
+ port = m->external_port;
+ }
+
+ /* Address only mapping doesn't change port */
+ if (is_addr_only_static_mapping (m))
+ *mapping_port = match_port;
+ else
+ *mapping_port = port;
+
+ if (PREDICT_FALSE (is_addr_only != 0))
+ *is_addr_only = is_addr_only_static_mapping (m);
+
+ if (PREDICT_FALSE (is_identity_nat != 0))
+ *is_identity_nat = is_identity_static_mapping (m);
+
+ return 0;
+}
+
+static void
+nat44_ei_worker_db_free (snat_main_per_thread_data_t *tsm)
+{
+ pool_free (tsm->list_pool);
+ pool_free (tsm->lru_pool);
+ pool_free (tsm->sessions);
+ pool_free (tsm->users);
+
+ clib_bihash_free_8_8 (&tsm->in2out);
+ clib_bihash_free_8_8 (&tsm->out2in);
+ clib_bihash_free_8_8 (&tsm->user_hash);
+}
+
+static void
+nat44_ei_worker_db_init (snat_main_per_thread_data_t *tsm, u32 translations,
+ u32 translation_buckets, u32 user_buckets)
+{
+ dlist_elt_t *head;
+
+ pool_alloc (tsm->list_pool, translations);
+ pool_alloc (tsm->lru_pool, translations);
+ pool_alloc (tsm->sessions, translations);
+
+ clib_bihash_init_8_8 (&tsm->in2out, "in2out", translation_buckets, 0);
+ clib_bihash_init_8_8 (&tsm->out2in, "out2in", translation_buckets, 0);
+ clib_bihash_init_8_8 (&tsm->user_hash, "users", user_buckets, 0);
+
+ clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out, format_session_kvp);
+ clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in, format_session_kvp);
+ clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash, format_user_kvp);
+
+ pool_get (tsm->lru_pool, head);
+ tsm->tcp_trans_lru_head_index = head - tsm->lru_pool;
+ clib_dlist_init (tsm->lru_pool, tsm->tcp_trans_lru_head_index);
+
+ pool_get (tsm->lru_pool, head);
+ tsm->tcp_estab_lru_head_index = head - tsm->lru_pool;
+ clib_dlist_init (tsm->lru_pool, tsm->tcp_estab_lru_head_index);
+
+ pool_get (tsm->lru_pool, head);
+ tsm->udp_lru_head_index = head - tsm->lru_pool;
+ clib_dlist_init (tsm->lru_pool, tsm->udp_lru_head_index);
+
+ pool_get (tsm->lru_pool, head);
+ tsm->icmp_lru_head_index = head - tsm->lru_pool;
+ clib_dlist_init (tsm->lru_pool, tsm->icmp_lru_head_index);
+
+ pool_get (tsm->lru_pool, head);
+ tsm->unk_proto_lru_head_index = head - tsm->lru_pool;
+ clib_dlist_init (tsm->lru_pool, tsm->unk_proto_lru_head_index);
+}
+
+static void
+nat44_ei_db_free ()
+{
+ snat_main_t *sm = &snat_main;
+ snat_main_per_thread_data_t *tsm;
+
+ pool_free (sm->static_mappings);
+ clib_bihash_free_8_8 (&sm->static_mapping_by_local);
+ clib_bihash_free_8_8 (&sm->static_mapping_by_external);
+
+ if (sm->pat)
+ {
+ vec_foreach (tsm, sm->per_thread_data)
+ {
+ nat44_ei_worker_db_free (tsm);
+ }
+ }
+}
+
+static void
+nat44_ei_db_init (u32 translations, u32 translation_buckets, u32 user_buckets)
+{
+ snat_main_t *sm = &snat_main;
+ snat_main_per_thread_data_t *tsm;
+
+ u32 static_mapping_buckets = 1024;
+ u32 static_mapping_memory_size = 64 << 20;
+
+ clib_bihash_init_8_8 (&sm->static_mapping_by_local,
+ "static_mapping_by_local", static_mapping_buckets,
+ static_mapping_memory_size);
+ clib_bihash_init_8_8 (&sm->static_mapping_by_external,
+ "static_mapping_by_external", static_mapping_buckets,
+ static_mapping_memory_size);
+ clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
+ format_static_mapping_kvp);
+ clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
+ format_static_mapping_kvp);
+
+ if (sm->pat)
+ {
+ vec_foreach (tsm, sm->per_thread_data)
+ {
+ nat44_ei_worker_db_init (tsm, translations, translation_buckets,
+ user_buckets);
+ }
+ }
+}
+
+void
+nat44_ei_sessions_clear ()
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+
+ snat_main_per_thread_data_t *tsm;
+ snat_main_t *sm = &snat_main;
+
+ if (sm->pat)
+ {
+ vec_foreach (tsm, sm->per_thread_data)
+ {
+ nat44_ei_worker_db_free (tsm);
+ nat44_ei_worker_db_init (tsm, nm->translations,
+ nm->translation_buckets, nm->user_buckets);
+ }
+ }
+
+ // TODO: function for reset counters
+ vlib_zero_simple_counter (&sm->total_users, 0);
+ vlib_zero_simple_counter (&sm->total_sessions, 0);
+ vlib_zero_simple_counter (&sm->user_limit_reached, 0);
+}
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/src/plugins/nat/nat44-ei/nat44_ei.h b/src/plugins/nat/nat44-ei/nat44_ei.h
index ac430bee5c3..510e73de59a 100644
--- a/src/plugins/nat/nat44-ei/nat44_ei.h
+++ b/src/plugins/nat/nat44-ei/nat44_ei.h
@@ -19,9 +19,38 @@
#ifndef __included_nat44_ei_h__
#define __included_nat44_ei_h__
-int nat44_ei_plugin_enable ();
+typedef struct
+{
+ /* maximum number of users */
+ u32 users;
+ /* maximum number of sessions */
+ u32 sessions;
+ /* maximum number of ssessions per user */
+ u32 user_sessions;
-void nat44_ei_plugin_disable ();
+ /* plugin features */
+ u8 static_mapping_only;
+ u8 connection_tracking;
+ u8 out2in_dpo;
+
+ u32 inside_vrf;
+ u32 outside_vrf;
+
+} nat44_ei_config_t;
+
+typedef struct
+{
+ u32 translations;
+ u32 translation_buckets;
+ u32 user_buckets;
+
+ nat44_ei_config_t rconfig;
+
+} nat44_ei_main_t;
+
+int nat44_ei_plugin_enable (nat44_ei_config_t c);
+
+int nat44_ei_plugin_disable ();
/**
* @brief Delete specific NAT44 EI user and his sessions
@@ -71,6 +100,71 @@ void nat44_ei_set_alloc_mape (u16 psid, u16 psid_offset, u16 psid_length);
*/
void nat44_ei_set_alloc_range (u16 start_port, u16 end_port);
+/**
+ * @brief Add/delete NAT44-EI static mapping
+ *
+ * @param l_addr local IPv4 address
+ * @param e_addr external IPv4 address
+ * @param l_port local port number
+ * @param e_port external port number
+ * @param proto L4 protocol
+ * @param sw_if_index use interface address as external IPv4 address
+ * @param vrf_id local VRF ID
+ * @param addr_only 1 = 1:1NAT, 0 = 1:1NAPT
+ * @param identity_nat identity NAT
+ * @param tag opaque string tag
+ * @param is_add 1 = add, 0 = delete
+ *
+ * @return 0 on success, non-zero value otherwise
+
+ */
+int nat44_ei_add_del_static_mapping (ip4_address_t l_addr,
+ ip4_address_t e_addr, u16 l_port,
+ u16 e_port, nat_protocol_t proto,
+ u32 sw_if_index, u32 vrf_id, u8 addr_only,
+ u8 identity_nat, u8 *tag, u8 is_add);
+
+/**
+ * @brief Delete NAT44-EI session
+ *
+ * @param addr IPv4 address
+ * @param port L4 port number
+ * @param proto L4 protocol
+ * @param vrf_id VRF ID
+ * @param is_in 1 = inside network address and port pair, 0 = outside
+ *
+ * @return 0 on success, non-zero value otherwise
+ */
+int nat44_ei_del_session (snat_main_t *sm, ip4_address_t *addr, u16 port,
+ nat_protocol_t proto, u32 vrf_id, int is_in);
+
+/**
+ * @brief Match NAT44-EI static mapping.
+ *
+ * @param key address and port to match
+ * @param addr external/local address of the matched mapping
+ * @param port port of the matched mapping
+ * @param fib_index fib index of the matched mapping
+ * @param by_external if 0 match by local address otherwise match by
+ * external address
+ * @param is_addr_only 1 if matched mapping is address only
+ * @param is_identity_nat 1 if indentity mapping
+ *
+ * @returns 0 if match found otherwise 1.
+ */
+int nat44_ei_static_mapping_match (ip4_address_t match_addr, u16 match_port,
+ u32 match_fib_index,
+ nat_protocol_t match_protocol,
+ ip4_address_t *mapping_addr,
+ u16 *mapping_port, u32 *mapping_fib_index,
+ u8 by_external, u8 *is_addr_only,
+ u8 *is_identity_nat);
+
+/**
+ * @brief Clear all active NAT44-EI sessions.
+ */
+void nat44_ei_sessions_clear ();
+
#endif /* __included_nat44_ei_h__ */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/src/plugins/nat/nat44-ei/nat44_ei_in2out.c b/src/plugins/nat/nat44-ei/nat44_ei_in2out.c
index 1c341318957..892518fff97 100644
--- a/src/plugins/nat/nat44-ei/nat44_ei_in2out.c
+++ b/src/plugins/nat/nat44-ei/nat44_ei_in2out.c
@@ -29,6 +29,7 @@
#include <nat/nat_inlines.h>
#include <nat/lib/nat_syslog.h>
#include <nat/nat44-ei/nat44_ei_inlines.h>
+#include <nat/nat44-ei/nat44_ei.h>
#include <vppinfra/hash.h>
#include <vppinfra/error.h>
@@ -130,10 +131,10 @@ snat_not_translate (snat_main_t * sm, vlib_node_runtime_t * node,
ip4_address_t placeholder_addr;
u16 placeholder_port;
u32 placeholder_fib_index;
- if (!snat_static_mapping_match
- (sm, ip0->dst_address, udp0->dst_port, sm->outside_fib_index,
- proto0, &placeholder_addr, &placeholder_port,
- &placeholder_fib_index, 1, 0, 0, 0, 0, 0, 0))
+ if (!nat44_ei_static_mapping_match (ip0->dst_address, udp0->dst_port,
+ sm->outside_fib_index, proto0,
+ &placeholder_addr, &placeholder_port,
+ &placeholder_fib_index, 1, 0, 0))
return 0;
}
else
@@ -270,9 +271,9 @@ slow_path (snat_main_t * sm, vlib_buffer_t * b0,
}
/* First try to match static mapping by local address and port */
- if (snat_static_mapping_match
- (sm, i2o_addr, i2o_port, rx_fib_index0, nat_proto, &sm_addr,
- &sm_port, &sm_fib_index, 0, 0, 0, 0, 0, &identity_nat, 0))
+ if (nat44_ei_static_mapping_match (i2o_addr, i2o_port, rx_fib_index0,
+ nat_proto, &sm_addr, &sm_port,
+ &sm_fib_index, 0, 0, &identity_nat))
{
/* Try to create dynamic translation */
if (sm->alloc_addr_and_port (
@@ -592,9 +593,9 @@ icmp_match_in2out_fast (snat_main_t * sm, vlib_node_runtime_t * node,
u16 sm_port;
u32 sm_fib_index;
- if (snat_static_mapping_match
- (sm, *addr, *port, *fib_index, *proto, &sm_addr, &sm_port,
- &sm_fib_index, 0, &is_addr_only, 0, 0, 0, 0, 0))
+ if (nat44_ei_static_mapping_match (*addr, *port, *fib_index, *proto,
+ &sm_addr, &sm_port, &sm_fib_index, 0,
+ &is_addr_only, 0))
{
if (PREDICT_FALSE (snat_not_translate_fast (sm, node, sw_if_index0, ip0,
IP_PROTOCOL_ICMP,
@@ -1831,9 +1832,9 @@ VLIB_NODE_FN (snat_in2out_fast_node) (vlib_main_t * vm,
goto trace0;
}
- if (snat_static_mapping_match
- (sm, ip0->src_address, udp0->src_port, rx_fib_index0, proto0,
- &sm0_addr, &sm0_port, &sm0_fib_index, 0, 0, 0, 0, 0, 0, 0))
+ if (nat44_ei_static_mapping_match (
+ ip0->src_address, udp0->src_port, rx_fib_index0, proto0,
+ &sm0_addr, &sm0_port, &sm0_fib_index, 0, 0, 0))
{
b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
next0 = SNAT_IN2OUT_NEXT_DROP;
diff --git a/src/plugins/nat/nat44-ei/nat44_ei_out2in.c b/src/plugins/nat/nat44-ei/nat44_ei_out2in.c
index 8220f0dc9d8..b677e9bde89 100644
--- a/src/plugins/nat/nat44-ei/nat44_ei_out2in.c
+++ b/src/plugins/nat/nat44-ei/nat44_ei_out2in.c
@@ -29,6 +29,7 @@
#include <nat/nat_inlines.h>
#include <nat/lib/nat_syslog.h>
#include <nat/nat44-ei/nat44_ei_inlines.h>
+#include <nat/nat44-ei/nat44_ei.h>
#include <vppinfra/hash.h>
#include <vppinfra/error.h>
@@ -354,10 +355,9 @@ icmp_match_out2in_slow (snat_main_t * sm, vlib_node_runtime_t * node,
{
/* Try to match static mapping by external address and port,
destination address and port in packet */
- if (snat_static_mapping_match
- (sm, *addr, *port, *fib_index, *proto,
- &mapping_addr, &mapping_port, &mapping_fib_index, 1, &is_addr_only,
- 0, 0, 0, &identity_nat, 0))
+ if (nat44_ei_static_mapping_match (
+ *addr, *port, *fib_index, *proto, &mapping_addr, &mapping_port,
+ &mapping_fib_index, 1, &is_addr_only, &identity_nat))
{
if (!sm->forwarding_enabled)
{
@@ -481,9 +481,9 @@ icmp_match_out2in_fast (snat_main_t * sm, vlib_node_runtime_t * node,
next0 = SNAT_OUT2IN_NEXT_DROP;
goto out;
}
- if (snat_static_mapping_match
- (sm, addr, port, rx_fib_index0, *proto, mapping_addr, mapping_port,
- mapping_fib_index, 1, &is_addr_only, 0, 0, 0, 0, 0))
+ if (nat44_ei_static_mapping_match (addr, port, rx_fib_index0, *proto,
+ mapping_addr, mapping_port,
+ mapping_fib_index, 1, &is_addr_only, 0))
{
/* Don't NAT packet aimed at the intfc address */
if (is_interface_addr (sm, node, sw_if_index0, ip0->dst_address.as_u32))
@@ -828,11 +828,10 @@ VLIB_NODE_FN (snat_out2in_node) (vlib_main_t * vm,
{
/* Try to match static mapping by external address and port,
destination address and port in packet */
- if (snat_static_mapping_match
- (sm, ip0->dst_address,
- vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0,
- proto0, &sm_addr0, &sm_port0, &sm_fib_index0, 1, 0, 0, 0,
- 0, &identity_nat0, 0))
+ if (nat44_ei_static_mapping_match (
+ ip0->dst_address, vnet_buffer (b0)->ip.reass.l4_dst_port,
+ rx_fib_index0, proto0, &sm_addr0, &sm_port0, &sm_fib_index0, 1,
+ 0, &identity_nat0))
{
/*
* Send DHCP packets to the ipv4 stack, or we won't
@@ -1003,17 +1002,15 @@ VLIB_NODE_FN (snat_out2in_node) (vlib_main_t * vm,
init_nat_k (&kv1, ip1->dst_address,
vnet_buffer (b1)->ip.reass.l4_dst_port, rx_fib_index1,
proto1);
-
if (clib_bihash_search_8_8
(&sm->per_thread_data[thread_index].out2in, &kv1, &value1))
{
/* Try to match static mapping by external address and port,
destination address and port in packet */
- if (snat_static_mapping_match
- (sm, ip1->dst_address,
- vnet_buffer (b1)->ip.reass.l4_dst_port, proto1,
- rx_fib_index1, &sm_addr1, &sm_port1, &sm_fib_index1, 1, 0,
- 0, 0, 0, &identity_nat1, 0))
+ if (nat44_ei_static_mapping_match (
+ ip1->dst_address, vnet_buffer (b1)->ip.reass.l4_dst_port,
+ rx_fib_index1, proto1, &sm_addr1, &sm_port1, &sm_fib_index1, 1,
+ 0, &identity_nat1))
{
/*
* Send DHCP packets to the ipv4 stack, or we won't
@@ -1227,11 +1224,10 @@ VLIB_NODE_FN (snat_out2in_node) (vlib_main_t * vm,
{
/* Try to match static mapping by external address and port,
destination address and port in packet */
- if (snat_static_mapping_match
- (sm, ip0->dst_address,
- vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0,
- proto0, &sm_addr0, &sm_port0, &sm_fib_index0, 1, 0, 0, 0,
- 0, &identity_nat0, 0))
+ if (nat44_ei_static_mapping_match (
+ ip0->dst_address, vnet_buffer (b0)->ip.reass.l4_dst_port,
+ rx_fib_index0, proto0, &sm_addr0, &sm_port0, &sm_fib_index0, 1,
+ 0, &identity_nat0))
{
/*
* Send DHCP packets to the ipv4 stack, or we won't
@@ -1454,9 +1450,9 @@ VLIB_NODE_FN (snat_out2in_fast_node) (vlib_main_t * vm,
goto trace00;
}
- if (snat_static_mapping_match
- (sm, ip0->dst_address, udp0->dst_port, rx_fib_index0, proto0,
- &sm_addr0, &sm_port0, &sm_fib_index0, 1, 0, 0, 0, 0, 0, 0))
+ if (nat44_ei_static_mapping_match (ip0->dst_address, udp0->dst_port,
+ rx_fib_index0, proto0, &sm_addr0,
+ &sm_port0, &sm_fib_index0, 1, 0, 0))
{
b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
goto trace00;
diff --git a/src/plugins/nat/nat44_api.c b/src/plugins/nat/nat44_api.c
index cfe2211acd3..c025db74f2e 100644
--- a/src/plugins/nat/nat44_api.c
+++ b/src/plugins/nat/nat44_api.c
@@ -828,13 +828,10 @@ static void
tag = format (0, "%s", mp->tag);
vec_terminate_c_string (tag);
- rv = snat_add_static_mapping (local_addr, external_addr, local_port,
- external_port, vrf_id,
- mp->flags & NAT_API_IS_ADDR_ONLY,
- external_sw_if_index, proto,
- mp->is_add, twice_nat,
- mp->flags & NAT_API_IS_OUT2IN_ONLY, tag, 0,
- pool_addr, 0);
+ rv = snat_add_static_mapping (
+ local_addr, external_addr, local_port, external_port, vrf_id,
+ mp->flags & NAT_API_IS_ADDR_ONLY, external_sw_if_index, proto, mp->is_add,
+ twice_nat, mp->flags & NAT_API_IS_OUT2IN_ONLY, tag, 0, pool_addr, 0);
vec_free (tag);
REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_REPLY);
@@ -1622,7 +1619,7 @@ vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp)
nat44_del_ed_session (sm, &addr, port, &eh_addr, eh_port, mp->protocol,
vrf_id, is_in);
else
- rv = nat44_del_session (sm, &addr, port, proto, vrf_id, is_in);
+ rv = nat44_ei_del_session (sm, &addr, port, proto, vrf_id, is_in);
REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
}
diff --git a/src/plugins/nat/nat44_cli.c b/src/plugins/nat/nat44_cli.c
index 7415b5fe76f..adcf324850d 100644
--- a/src/plugins/nat/nat44_cli.c
+++ b/src/plugins/nat/nat44_cli.c
@@ -44,8 +44,6 @@ nat44_enable_command_fn (vlib_main_t * vm,
nat44_config_t c = { 0 };
u8 mode_set = 0;
- // TODO: check this also inside the function so it can be
- // safely called from anyplace, also sanity checking required
if (sm->enabled)
return clib_error_return (0, "nat44 already enabled");
@@ -1148,11 +1146,10 @@ add_static_mapping_command_fn (vlib_main_t * vm,
goto done;
}
- rv = snat_add_static_mapping (l_addr, e_addr, clib_host_to_net_u16 (l_port),
- clib_host_to_net_u16 (e_port),
- vrf_id, addr_only, sw_if_index, proto, is_add,
- twice_nat, out2in_only, 0, 0, exact_addr,
- exact);
+ rv = snat_add_static_mapping (
+ l_addr, e_addr, clib_host_to_net_u16 (l_port),
+ clib_host_to_net_u16 (e_port), vrf_id, addr_only, sw_if_index, proto,
+ is_add, twice_nat, out2in_only, 0, 0, exact_addr, exact);
switch (rv)
{
@@ -1230,11 +1227,9 @@ add_identity_mapping_command_fn (vlib_main_t * vm,
}
}
- rv =
- snat_add_static_mapping (addr, addr, clib_host_to_net_u16 (port),
- clib_host_to_net_u16 (port), vrf_id, addr_only,
- sw_if_index, proto, is_add, 0, 0, 0, 1,
- pool_addr, 0);
+ rv = snat_add_static_mapping (
+ addr, addr, clib_host_to_net_u16 (port), clib_host_to_net_u16 (port),
+ vrf_id, addr_only, sw_if_index, proto, is_add, 0, 0, 0, 1, pool_addr, 0);
switch (rv)
{
@@ -1779,9 +1774,8 @@ nat44_del_session_command_fn (vlib_main_t * vm,
clib_host_to_net_u16 (eh_port),
nat_proto_to_ip_proto (proto), vrf_id, is_in);
else
- rv =
- nat44_del_session (sm, &addr, clib_host_to_net_u16 (port), proto,
- vrf_id, is_in);
+ rv = nat44_ei_del_session (sm, &addr, clib_host_to_net_u16 (port), proto,
+ vrf_id, is_in);
switch (rv)
{