#include <nat/nat_reass.h>
#include <nat/nat_inlines.h>
#include <nat/nat_affinity.h>
+#include <nat/nat_syslog.h>
#include <vnet/fib/fib_table.h>
#include <vnet/fib/ip4_fib.h>
ed_kv.key[1] = ed_key.as_u64[1];
if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
nat_log_warn ("in2out_ed key del failed");
+
+ 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));
}
else
{
kv.key = s->out2in.as_u64;
if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0))
nat_log_warn ("out2in key del failed");
+
+ nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index,
+ &s->in2out.addr, s->in2out.port,
+ &s->out2in.addr, s->out2in.port,
+ s->in2out.protocol);
}
if (snat_is_unk_proto_session (s))
{
/* no, make a new one */
pool_get (tsm->users, u);
- memset (u, 0, sizeof (*u));
+ clib_memset (u, 0, sizeof (*u));
u->addr.as_u32 = addr->as_u32;
u->fib_index = fib_index;
/* add user */
if (clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 1))
nat_log_warn ("user_hash keay add failed");
+
+ vlib_set_simple_counter (&sm->total_users, thread_index, 0,
+ pool_elts (tsm->users));
}
else
{
else
{
pool_get (tsm->sessions, s);
- memset (s, 0, sizeof (*s));
+ clib_memset (s, 0, sizeof (*s));
/* Create list elts */
pool_get (tsm->list_pool, per_user_translation_list_elt);
clib_dlist_addtail (tsm->list_pool,
s->per_user_list_head_index,
per_user_translation_list_elt - tsm->list_pool);
+
+ s->user_index = u - tsm->users;
+ vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
+ pool_elts (tsm->sessions));
}
return s;
}
snat_session_t *
-nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index)
+nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index,
+ f64 now)
{
snat_session_t *s;
snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
- dlist_elt_t *per_user_translation_list_elt;
+ dlist_elt_t *per_user_translation_list_elt, *oldest_elt;
+ u32 oldest_index;
+ u64 sess_timeout_time;
- if ((u->nsessions + u->nstaticsessions) >= sm->max_translations_per_user)
+ if (PREDICT_FALSE (!(u->nsessions) && !(u->nstaticsessions)))
+ goto alloc_new;
+
+ oldest_index =
+ clib_dlist_remove_head (tsm->list_pool,
+ u->sessions_per_user_list_head_index);
+ oldest_elt = pool_elt_at_index (tsm->list_pool, oldest_index);
+ s = pool_elt_at_index (tsm->sessions, oldest_elt->value);
+ sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
+ if (now >= sess_timeout_time)
{
- nat_log_warn ("max translations per user %U", format_ip4_address,
- &u->addr);
- snat_ipfix_logging_max_entries_per_user (sm->max_translations_per_user,
- u->addr.as_u32);
- return 0;
+ clib_dlist_addtail (tsm->list_pool,
+ u->sessions_per_user_list_head_index, oldest_index);
+ nat_free_session_data (sm, s, thread_index);
+ if (snat_is_session_static (s))
+ u->nstaticsessions--;
+ else
+ u->nsessions--;
+ s->flags = 0;
+ s->total_bytes = 0;
+ s->total_pkts = 0;
+ s->state = 0;
+ s->ext_host_addr.as_u32 = 0;
+ s->ext_host_port = 0;
+ s->ext_host_nat_addr.as_u32 = 0;
+ s->ext_host_nat_port = 0;
}
+ else
+ {
+ clib_dlist_addhead (tsm->list_pool,
+ u->sessions_per_user_list_head_index, oldest_index);
+ if ((u->nsessions + u->nstaticsessions) >=
+ sm->max_translations_per_user)
+ {
+ nat_log_warn ("max translations per user %U", format_ip4_address,
+ &u->addr);
+ snat_ipfix_logging_max_entries_per_user
+ (sm->max_translations_per_user, u->addr.as_u32);
+ return 0;
+ }
+ 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);
+ }
- pool_get (tsm->sessions, s);
- memset (s, 0, sizeof (*s));
-
- /* Create list elts */
- pool_get (tsm->list_pool, per_user_translation_list_elt);
- clib_dlist_init (tsm->list_pool,
- per_user_translation_list_elt - tsm->list_pool);
-
- per_user_translation_list_elt->value = s - tsm->sessions;
- s->per_user_index = per_user_translation_list_elt - tsm->list_pool;
- s->per_user_list_head_index = u->sessions_per_user_list_head_index;
-
- clib_dlist_addtail (tsm->list_pool,
- s->per_user_list_head_index,
- per_user_translation_list_elt - tsm->list_pool);
+ vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
+ pool_elts (tsm->sessions));
+ }
return s;
}
/* *INDENT-OFF* */
pool_foreach (m, sm->static_mappings,
({
+ if (is_addr_only_static_mapping (m) ||
+ is_out2in_only_static_mapping (m) ||
+ is_identity_static_mapping (m))
+ continue;
if (m->external_addr.as_u32 == addr.as_u32)
return 1;
}));
u16 e_port,
u32 vrf_id,
snat_protocol_t proto,
- int addr_only, int is_add, u8 * tag)
+ int addr_only, int is_add, u8 * tag,
+ int twice_nat, int out2in_only,
+ int identity_nat)
{
snat_static_map_resolve_t *rp;
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;
rp->tag = vec_dup (tag);
}
return thread_idx;
}
-/**
- * @brief Add static mapping.
- *
- * Create static mapping between local addr+port and external addr+port.
- *
- * @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 vrf_id VRF ID.
- * @param addr_only If 0 address port and pair mapping, otherwise address only.
- * @param sw_if_index External port instead of specific IP address.
- * @param is_add If 0 delete static mapping, otherwise add.
- * @param twice_nat If value is TWICE_NAT then translate external host address
- * and port.
- * If value is TWICE_NAT_SELF then translate external host
- * address and port whenever external host address equals
- * local address of internal host.
- * @param out2in_only If 1 rule match only out2in direction
- * @param tag - opaque string tag
- *
- * @returns
- */
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, snat_protocol_t proto, int is_add,
- twice_nat_type_t twice_nat, u8 out2in_only, u8 * tag)
+ twice_nat_type_t twice_nat, u8 out2in_only, u8 * tag,
+ u8 identity_nat)
{
snat_main_t *sm = &snat_main;
snat_static_mapping_t *m;
clib_bihash_kv_8_8_t kv, value;
snat_address_t *a = 0;
u32 fib_index = ~0;
- uword *p;
snat_interface_t *interface;
int i;
snat_main_per_thread_data_t *tsm;
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;
if (!sm->endpoint_dependent)
{
snat_add_static_mapping_when_resolved
(sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
- addr_only, is_add, tag);
+ addr_only, is_add, tag, twice_nat, out2in_only, identity_nat);
/* DHCP resolution required? */
if (first_int_addr == 0)
if (is_add)
{
if (m)
- return VNET_API_ERROR_VALUE_EXIST;
+ {
+ if (is_identity_static_mapping (m))
+ {
+ /* *INDENT-OFF* */
+ pool_foreach (local, m->locals,
+ ({
+ if (local->vrf_id == vrf_id)
+ return VNET_API_ERROR_VALUE_EXIST;
+ }));
+ /* *INDENT-ON* */
+ 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,
+ FIB_SOURCE_PLUGIN_LOW);
+ m_key.addr = m->local_addr;
+ m_key.port = m->local_port;
+ m_key.protocol = m->proto;
+ m_key.fib_index = local->fib_index;
+ kv.key = m_key.as_u64;
+ kv.value = m - sm->static_mappings;
+ clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
+ return 0;
+ }
+ else
+ return VNET_API_ERROR_VALUE_EXIST;
+ }
if (twice_nat && addr_only)
return VNET_API_ERROR_UNSUPPORTED;
/* Convert VRF id to FIB index */
if (vrf_id != ~0)
- {
- p = hash_get (sm->ip4_main->fib_index_by_table_id, vrf_id);
- if (!p)
- return VNET_API_ERROR_NO_SUCH_FIB;
- fib_index = p[0];
- }
+ fib_index =
+ fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
+ FIB_SOURCE_PLUGIN_LOW);
/* If not specified use inside VRF id from SNAT plugin startup config */
else
{
vrf_id = sm->inside_vrf_id;
}
- if (!out2in_only)
+ if (!(out2in_only || identity_nat))
{
m_key.addr = l_addr;
m_key.port = addr_only ? 0 : l_port;
}
pool_get (sm->static_mappings, m);
- memset (m, 0, sizeof (*m));
+ clib_memset (m, 0, sizeof (*m));
m->tag = vec_dup (tag);
m->local_addr = l_addr;
m->external_addr = e_addr;
- m->addr_only = addr_only;
- m->vrf_id = vrf_id;
- m->fib_index = fib_index;
m->twice_nat = twice_nat;
- m->out2in_only = out2in_only;
+ if (out2in_only)
+ m->flags |= NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY;
+ if (addr_only)
+ m->flags |= NAT_STATIC_MAPPING_FLAG_ADDR_ONLY;
+ 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 (!addr_only)
{
m->local_port = l_port;
m_key.addr = m->local_addr;
m_key.port = m->local_port;
m_key.protocol = m->proto;
- m_key.fib_index = m->fib_index;
+ m_key.fib_index = fib_index;
kv.key = m_key.as_u64;
kv.value = m - sm->static_mappings;
if (!out2in_only)
return VNET_API_ERROR_NO_SUCH_ENTRY;
}
+ if (identity_nat)
+ {
+ if (vrf_id == ~0)
+ vrf_id = sm->inside_vrf_id;
+
+ /* *INDENT-OFF* */
+ pool_foreach (local, m->locals,
+ ({
+ if (local->vrf_id == vrf_id)
+ find = local - m->locals;
+ }));
+ /* *INDENT-ON* */
+ 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 || out2in_only))
{
m_key.addr = m->local_addr;
m_key.port = m->local_port;
m_key.protocol = m->proto;
- m_key.fib_index = m->fib_index;
+ m_key.fib_index = fib_index;
kv.key = m_key.as_u64;
if (!out2in_only)
clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0);
- m_key.addr = m->external_addr;
- m_key.port = m->external_port;
- m_key.fib_index = 0;
- kv.key = m_key.as_u64;
- clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &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 = m->fib_index;
+ u_key.fib_index = fib_index;
kv.key = u_key.as_u64;
if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
{
}
}
+ fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_LOW);
+ if (pool_elts (m->locals))
+ return 0;
+
+ m_key.addr = m->external_addr;
+ m_key.port = m->external_port;
+ m_key.fib_index = 0;
+ kv.key = m_key.as_u64;
+ 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_get (sm->static_mappings, m);
- memset (m, 0, sizeof (*m));
+ clib_memset (m, 0, sizeof (*m));
m->tag = vec_dup (tag);
m->external_addr = e_addr;
- m->addr_only = 0;
m->external_port = e_port;
m->proto = proto;
m->twice_nat = twice_nat;
- m->out2in_only = out2in_only;
+ m->flags |= NAT_STATIC_MAPPING_FLAG_LB;
+ if (out2in_only)
+ m->flags |= NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY;
m->affinity = affinity;
if (affinity)
}
locals[i].prefix = (i == 0) ? locals[i].probability :
(locals[i - 1].prefix + locals[i].probability);
- vec_add1 (m->locals, locals[i]);
+ pool_get (m->locals, local);
+ *local = locals[i];
if (sm->num_workers > 1)
{
ip4_header_t ip = {
if (!m)
return VNET_API_ERROR_NO_SUCH_ENTRY;
+ if (!is_lb_static_mapping (m))
+ return VNET_API_ERROR_INVALID_VALUE;
+
/* Free external address port */
if (!(sm->static_mapping_only || out2in_only))
{
}
/* *INDENT-OFF* */
- vec_foreach (local, m->locals)
- {
+ pool_foreach (local, m->locals,
+ ({
fib_table_unlock (local->fib_index, FIB_PROTOCOL_IP4,
FIB_SOURCE_PLUGIN_LOW);
m_key.addr = local->addr;
/* Delete sessions */
u_key.addr = local->addr;
- u_key.fib_index = m->fib_index;
+ u_key.fib_index = local->fib_index;
kv.key = u_key.as_u64;
if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
{
}
}
}
- }
+ }));
/* *INDENT-ON* */
if (m->affinity)
nat_affinity_flush_service (m->affinity_per_service_list_head_index);
- vec_free (m->locals);
+ pool_free (m->locals);
vec_free (m->tag);
vec_free (m->workers);
return 0;
}
+int
+nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
+ ip4_address_t l_addr, u16 l_port,
+ snat_protocol_t proto, u32 vrf_id,
+ u8 probability, u8 is_add)
+{
+ snat_main_t *sm = &snat_main;
+ snat_static_mapping_t *m = 0;
+ snat_session_key_t m_key;
+ clib_bihash_kv_8_8_t kv, value;
+ nat44_lb_addr_port_t *local, *prev_local, *match_local = 0;
+ snat_main_per_thread_data_t *tsm;
+ snat_user_key_t u_key;
+ snat_user_t *u;
+ snat_session_t *s;
+ dlist_elt_t *head, *elt;
+ u32 elt_index, head_index, ses_index, *locals = 0;
+ uword *bitmap = 0;
+ int i;
+
+ if (!sm->endpoint_dependent)
+ return VNET_API_ERROR_FEATURE_DISABLED;
+
+ m_key.addr = e_addr;
+ m_key.port = e_port;
+ m_key.protocol = proto;
+ m_key.fib_index = 0;
+ kv.key = m_key.as_u64;
+ if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
+ m = pool_elt_at_index (sm->static_mappings, value.value);
+
+ if (!m)
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+
+ if (!is_lb_static_mapping (m))
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ /* *INDENT-OFF* */
+ pool_foreach (local, m->locals,
+ ({
+ if ((local->addr.as_u32 == l_addr.as_u32) && (local->port == l_port) &&
+ (local->vrf_id == vrf_id))
+ {
+ match_local = local;
+ break;
+ }
+ }));
+ /* *INDENT-ON* */
+
+ if (is_add)
+ {
+ if (match_local)
+ return VNET_API_ERROR_VALUE_EXIST;
+
+ pool_get (m->locals, local);
+ clib_memset (local, 0, sizeof (*local));
+ local->addr.as_u32 = l_addr.as_u32;
+ local->port = l_port;
+ local->probability = probability;
+ local->vrf_id = vrf_id;
+ local->fib_index =
+ fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
+ FIB_SOURCE_PLUGIN_LOW);
+
+ if (!is_out2in_only_static_mapping (m))
+ {
+ m_key.addr = l_addr;
+ m_key.port = l_port;
+ m_key.fib_index = local->fib_index;
+ kv.key = m_key.as_u64;
+ kv.value = m - sm->static_mappings;
+ if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1))
+ nat_log_err ("static_mapping_by_local key add failed");
+ }
+ }
+ else
+ {
+ if (!match_local)
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+
+ if (pool_elts (m->locals) < 3)
+ return VNET_API_ERROR_UNSPECIFIED;
+
+ fib_table_unlock (match_local->fib_index, FIB_PROTOCOL_IP4,
+ FIB_SOURCE_PLUGIN_LOW);
+
+ if (!is_out2in_only_static_mapping (m))
+ {
+ m_key.addr = l_addr;
+ m_key.port = l_port;
+ m_key.fib_index = match_local->fib_index;
+ kv.key = m_key.as_u64;
+ if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0))
+ nat_log_err ("static_mapping_by_local key del failed");
+ }
+
+ if (sm->num_workers > 1)
+ {
+ ip4_header_t ip = {
+ .src_address = local->addr,
+ };
+ tsm = vec_elt_at_index (sm->per_thread_data,
+ sm->worker_in2out_cb (&ip, m->fib_index));
+ }
+ else
+ tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
+
+ /* Delete sessions */
+ u_key.addr = match_local->addr;
+ u_key.fib_index = match_local->fib_index;
+ kv.key = u_key.as_u64;
+ if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
+ {
+ u = pool_elt_at_index (tsm->users, value.value);
+ if (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);
+ 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 (!(is_lb_session (s)))
+ continue;
+
+ if ((s->in2out.addr.as_u32 != match_local->addr.as_u32) ||
+ (clib_net_to_host_u16 (s->in2out.port) !=
+ match_local->port))
+ continue;
+
+ nat_free_session_data (sm, s, tsm - sm->per_thread_data);
+ nat44_delete_session (sm, s, tsm - sm->per_thread_data);
+ }
+ }
+ }
+
+ pool_put (m->locals, match_local);
+ }
+
+ vec_free (m->workers);
+
+ /* *INDENT-OFF* */
+ pool_foreach (local, m->locals,
+ ({
+ vec_add1 (locals, local - m->locals);
+ if (sm->num_workers > 1)
+ {
+ ip4_header_t ip;
+ ip.src_address.as_u32 = local->addr.as_u32,
+ bitmap = clib_bitmap_set (bitmap,
+ sm->worker_in2out_cb (&ip, local->fib_index),
+ 1);
+ }
+ }));
+ /* *INDENT-ON* */
+
+ ASSERT (vec_len (locals) > 1);
+
+ local = pool_elt_at_index (m->locals, locals[0]);
+ local->prefix = local->probability;
+ for (i = 1; i < vec_len (locals); i++)
+ {
+ local = pool_elt_at_index (m->locals, locals[i]);
+ prev_local = pool_elt_at_index (m->locals, locals[i - 1]);
+ local->prefix = local->probability + prev_local->prefix;
+ }
+
+ /* Assign workers */
+ if (sm->num_workers > 1)
+ {
+ /* *INDENT-OFF* */
+ clib_bitmap_foreach (i, bitmap, ({ vec_add1(m->workers, i); }));
+ /* *INDENT-ON* */
+ }
+
+ return 0;
+}
+
int
snat_del_address (snat_main_t * sm, ip4_address_t addr, u8 delete_sm,
u8 twice_nat)
if (m->external_addr.as_u32 == addr.as_u32)
(void) snat_add_static_mapping (m->local_addr, m->external_addr,
m->local_port, m->external_port,
- m->vrf_id, m->addr_only, ~0,
+ m->vrf_id, is_addr_only_static_mapping(m), ~0,
m->proto, 0, m->twice_nat,
- m->out2in_only, m->tag);
+ is_out2in_only_static_mapping(m), m->tag, is_identity_static_mapping(m));
}));
/* *INDENT-ON* */
}
pool_foreach (m, sm->static_mappings,
({
- if (!(m->addr_only) || (m->local_addr.as_u32 == m->external_addr.as_u32))
+ if (!(is_addr_only_static_mapping(m)) || (m->local_addr.as_u32 == m->external_addr.as_u32))
continue;
snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
snat_interface_t *i;
snat_address_t *ap;
snat_static_mapping_t *m;
+ nat_outside_fib_t *outside_fib;
+ u32 fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
+ sw_if_index);
+
if (sm->deterministic ||
(sm->static_mapping_only && !(sm->static_mapping_connection_tracking)))
}));
/* *INDENT-ON* */
+ if (!is_inside)
+ {
+ /* *INDENT-OFF* */
+ vec_foreach (outside_fib, sm->outside_fibs)
+ {
+ if (outside_fib->fib_index == fib_index)
+ {
+ if (is_del)
+ {
+ outside_fib->refcount--;
+ if (!outside_fib->refcount)
+ vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
+ }
+ else
+ outside_fib->refcount++;
+ goto feature_set;
+ }
+ }
+ /* *INDENT-ON* */
+ if (!is_del)
+ {
+ vec_add2 (sm->outside_fibs, outside_fib, 1);
+ outside_fib->refcount = 1;
+ outside_fib->fib_index = fib_index;
+ }
+ }
+
+feature_set:
if (is_inside)
{
if (sm->endpoint_dependent)
pool_foreach (m, sm->static_mappings,
({
- if (!(m->addr_only) || (m->local_addr.as_u32 == m->external_addr.as_u32))
+ if (!((is_addr_only_static_mapping(m))) || (m->local_addr.as_u32 == m->external_addr.as_u32))
continue;
snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
nat_dpo_module_init ();
+ /* Init counters */
+ sm->total_users.name = "total-users";
+ sm->total_users.stat_segment_name = "/nat44/total-users";
+ vlib_validate_simple_counter (&sm->total_users, 0);
+ vlib_zero_simple_counter (&sm->total_users, 0);
+ sm->total_sessions.name = "total-sessions";
+ sm->total_sessions.stat_segment_name = "/nat44/total-sessions";
+ vlib_validate_simple_counter (&sm->total_sessions, 0);
+ vlib_zero_simple_counter (&sm->total_sessions, 0);
+
/* Init IPFIX logging */
snat_ipfix_logging_init (vm);
u8 by_external,
u8 * is_addr_only,
twice_nat_type_t * twice_nat,
- lb_nat_type_t * lb, ip4_address_t * ext_host_addr)
+ lb_nat_type_t * lb, ip4_address_t * ext_host_addr,
+ u8 * is_identity_nat)
{
clib_bihash_kv_8_8_t kv, value;
snat_static_mapping_t *m;
snat_session_key_t m_key;
clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
- u32 rand, lo = 0, hi, mid;
+ u32 rand, lo = 0, hi, mid, *tmp = 0, i;
u8 backend_index;
+ nat44_lb_addr_port_t *local;
m_key.fib_index = match.fib_index;
if (by_external)
if (by_external)
{
- if (vec_len (m->locals))
+ if (is_lb_static_mapping (m))
{
if (PREDICT_FALSE (lb != 0))
*lb = m->affinity ? AFFINITY_LB_NAT : LB_NAT;
&backend_index))
goto get_local;
- mapping->addr = m->locals[backend_index].addr;
- mapping->port =
- clib_host_to_net_u16 (m->locals[backend_index].port);
- mapping->fib_index = m->locals[backend_index].fib_index;
+ local = pool_elt_at_index (m->locals, backend_index);
+ mapping->addr = local->addr;
+ mapping->port = clib_host_to_net_u16 (local->port);
+ mapping->fib_index = local->fib_index;
goto end;
}
get_local:
- hi = vec_len (m->locals) - 1;
- rand = 1 + (random_u32 (&sm->random_seed) % m->locals[hi].prefix);
+ /* *INDENT-OFF* */
+ pool_foreach_index (i, m->locals,
+ ({
+ vec_add1 (tmp, i);
+ }));
+ /* *INDENT-ON* */
+ hi = vec_len (tmp) - 1;
+ local = pool_elt_at_index (m->locals, tmp[hi]);
+ rand = 1 + (random_u32 (&sm->random_seed) % local->prefix);
while (lo < hi)
{
mid = ((hi - lo) >> 1) + lo;
- (rand > m->locals[mid].prefix) ? (lo = mid + 1) : (hi = mid);
+ local = pool_elt_at_index (m->locals, tmp[mid]);
+ (rand > local->prefix) ? (lo = mid + 1) : (hi = mid);
}
- if (!(m->locals[lo].prefix >= rand))
+ local = pool_elt_at_index (m->locals, tmp[lo]);
+ if (!(local->prefix >= rand))
return 1;
if (PREDICT_FALSE (sm->num_workers > 1))
{
ip4_header_t ip = {
- .src_address = m->locals[lo].addr,
+ .src_address = local->addr,
};
if (sm->worker_in2out_cb (&ip, m->fib_index) !=
vlib_get_thread_index ())
goto get_local;
}
- mapping->addr = m->locals[lo].addr;
- mapping->port = clib_host_to_net_u16 (m->locals[lo].port);
- mapping->fib_index = m->locals[lo].fib_index;
+ mapping->addr = local->addr;
+ mapping->port = clib_host_to_net_u16 (local->port);
+ mapping->fib_index = local->fib_index;
if (m->affinity)
{
if (nat_affinity_create_and_lock (ext_host_addr[0], match.addr,
match.protocol, match.port,
- lo, m->affinity,
+ tmp[lo], m->affinity,
m->affinity_per_service_list_head_index))
nat_log_info ("create affinity record failed");
}
+ vec_free (tmp);
}
else
{
mapping->fib_index = m->fib_index;
mapping->addr = m->local_addr;
/* Address only mapping doesn't change port */
- mapping->port = m->addr_only ? match.port
+ mapping->port = is_addr_only_static_mapping (m) ? match.port
: clib_host_to_net_u16 (m->local_port);
}
mapping->protocol = m->proto;
{
mapping->addr = m->external_addr;
/* Address only mapping doesn't change port */
- mapping->port = m->addr_only ? match.port
+ mapping->port = is_addr_only_static_mapping (m) ? match.port
: clib_host_to_net_u16 (m->external_port);
mapping->fib_index = sm->outside_fib_index;
}
end:
if (PREDICT_FALSE (is_addr_only != 0))
- *is_addr_only = m->addr_only;
+ *is_addr_only = is_addr_only_static_mapping (m);
if (PREDICT_FALSE (twice_nat != 0))
*twice_nat = m->twice_nat;
+ if (PREDICT_FALSE (is_identity_nat != 0))
+ *is_identity_nat = is_identity_static_mapping (m);
+
return 0;
}
(&sm->static_mapping_by_external, &kv, &value))
{
m = pool_elt_at_index (sm->static_mappings, value.value);
- if (!vec_len (m->locals))
+ if (!is_lb_static_mapping (m))
return m->workers[0];
hash = ip->src_address.as_u32 + (ip->src_address.as_u32 >> 8) +
rp->e_port,
rp->vrf_id,
rp->addr_only, ~0 /* sw_if_index */ ,
- rp->proto, !is_delete, 0, 0, rp->tag);
+ rp->proto, !is_delete, rp->twice_nat,
+ rp->out2in_only, rp->tag, rp->identity_nat);
if (rv)
nat_log_notice ("snat_add_static_mapping returned %d", rv);
}
rp->addr_only,
~0 /* sw_if_index */ ,
rp->proto,
- rp->is_add, 0, 0, rp->tag);
+ rp->is_add, rp->twice_nat,
+ rp->out2in_only, rp->tag,
+ rp->identity_nat);
if (rv)
nat_log_notice ("snat_add_static_mapping returned %d", rv);
}