#include <nat/nat66.h>
#include <nat/dslite.h>
#include <nat/nat_reass.h>
+#include <nat/nat_inlines.h>
#include <vnet/fib/fib_table.h>
#include <vnet/fib/ip4_fib.h>
VNET_FEATURE_INIT (ip4_snat_out2in, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-out2in",
- .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
+ "ip4-dhcp-client-detect"),
};
VNET_FEATURE_INIT (ip4_nat_classify, static) = {
.arc_name = "ip4-unicast",
ed_kv.key[0] = ed_key.as_u64[0];
ed_kv.key[1] = ed_key.as_u64[1];
if (clib_bihash_add_del_16_8 (&sm->in2out_ed, &ed_kv, 0))
- clib_warning ("in2out_ed key del failed");
+ nat_log_warn ("in2out_ed key del failed");
return;
}
ed_kv.key[0] = ed_key.as_u64[0];
ed_kv.key[1] = ed_key.as_u64[1];
if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &ed_kv, 0))
- clib_warning ("out2in_ed key del failed");
+ nat_log_warn ("out2in_ed key del failed");
ed_key.l_addr = s->in2out.addr;
ed_key.fib_index = s->in2out.fib_index;
ed_kv.key[0] = ed_key.as_u64[0];
ed_kv.key[1] = ed_key.as_u64[1];
if (clib_bihash_add_del_16_8 (&sm->in2out_ed, &ed_kv, 0))
- clib_warning ("in2out_ed key del failed");
+ nat_log_warn ("in2out_ed key del failed");
}
if (snat_is_unk_proto_session (s))
/* Session lookup tables */
kv.key = s->in2out.as_u64;
if (clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0))
- clib_warning ("in2out key del failed");
+ nat_log_warn ("in2out key del failed");
kv.key = s->out2in.as_u64;
if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0))
- clib_warning ("out2in key del failed");
+ nat_log_warn ("out2in key del failed");
if (snat_is_session_static (s))
return;
/* add user */
if (clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 1))
- clib_warning ("user_hash keay add failed");
+ nat_log_warn ("user_hash keay add failed");
}
else
{
/* Get the session */
s = pool_elt_at_index (tsm->sessions, session_index);
nat_free_session_data (sm, s, thread_index);
+ if (snat_is_session_static(s))
+ u->nstaticsessions--;
+ else
+ u->nsessions--;
s->outside_address_index = ~0;
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
{
return s;
}
+typedef struct {
+ u8 next_in2out;
+} nat44_classify_trace_t;
+
+static u8 * format_nat44_classify_trace (u8 * s, va_list * args)
+{
+ CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
+ CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
+ nat44_classify_trace_t *t = va_arg (*args, nat44_classify_trace_t *);
+ char *next;
+
+ next = t->next_in2out ? "nat44-in2out" : "nat44-out2in";
+
+ s = format (s, "nat44-classify: next %s", next);
+
+ return s;
+}
+
static inline uword
nat44_classify_node_fn_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
}
enqueue0:
+ if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
+ && (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ nat44_classify_trace_t *t =
+ vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->next_in2out = next0 == NAT44_CLASSIFY_NEXT_IN2OUT ? 1 : 0;
+ }
+
/* verify speculative enqueue, maybe switch current next frame */
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
to_next, n_left_to_next,
.function = nat44_classify_node_fn,
.name = "nat44-classify",
.vector_size = sizeof (u32),
+ .format_trace = format_nat44_classify_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_next_nodes = NAT44_CLASSIFY_N_NEXT,
.next_nodes = {
.function = nat44_det_classify_node_fn,
.name = "nat44-det-classify",
.vector_size = sizeof (u32),
+ .format_trace = format_nat44_classify_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_next_nodes = NAT44_CLASSIFY_N_NEXT,
.next_nodes = {
.function = nat44_handoff_classify_node_fn,
.name = "nat44-handoff-classify",
.vector_size = sizeof (u32),
+ .format_trace = format_nat44_classify_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_next_nodes = NAT44_CLASSIFY_N_NEXT,
.next_nodes = {
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown_protocol");
+ nat_log_info ("unknown protocol");
return VNET_API_ERROR_INVALID_VALUE_2;
}
break;
clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 1);
if (twice_nat || out2in_only)
{
- m_key.port = clib_host_to_net_u16 (l_port);
+ m_key.port = clib_host_to_net_u16 (m->local_port);
kv.key = m_key.as_u64;
kv.value = ~0ULL;
if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 1))
- clib_warning ("in2out key add failed");
+ nat_log_warn ("in2out key add failed");
}
m_key.addr = m->external_addr;
kv.key = m_key.as_u64;
kv.value = ~0ULL;
if (clib_bihash_add_del_8_8(&tsm->out2in, &kv, 1))
- clib_warning ("out2in key add failed");
+ nat_log_warn ("out2in key add failed");
}
/* Delete dynamic sessions matching local address (+ local port) */
if (snat_is_session_static (s))
continue;
- if (!addr_only)
- {
- if ((s->out2in.addr.as_u32 != e_addr.as_u32) &&
- (clib_net_to_host_u16 (s->out2in.port) != e_port))
- continue;
- }
+ if (!addr_only && (clib_net_to_host_u16 (s->in2out.port) != m->local_port))
+ continue;
nat_free_session_data (sm, s, tsm - sm->per_thread_data);
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- pool_put_index (tsm->list_pool, s->per_user_index);
- pool_put (tsm->sessions, s);
- u->nsessions--;
+ nat44_delete_session (sm, s, tsm - sm->per_thread_data);
if (!addr_only)
break;
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown_protocol");
+ nat_log_info ("unknown protocol");
return VNET_API_ERROR_INVALID_VALUE_2;
}
break;
kv.key = m_key.as_u64;
kv.value = ~0ULL;
if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 0))
- clib_warning ("in2out key del failed");
+ nat_log_warn ("in2out key del failed");
}
m_key.addr = m->external_addr;
kv.key = m_key.as_u64;
kv.value = ~0ULL;
if (clib_bihash_add_del_8_8(&tsm->out2in, &kv, 0))
- clib_warning ("in2out key del failed");
+ nat_log_warn ("out2in key del failed");
}
/* Delete session(s) for static mapping if exist */
if (is_lb_session (s))
continue;
+ if (!snat_is_session_static (s))
+ continue;
+
nat_free_session_data (sm, s, tsm - sm->per_thread_data);
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- pool_put_index (tsm->list_pool, s->per_user_index);
- pool_put (tsm->sessions, s);
- u->nstaticsessions--;
+ nat44_delete_session (sm, s, tsm - sm->per_thread_data);
if (!addr_only)
break;
}
- if (addr_only && (u->nstaticsessions == 0))
+ if (addr_only && (u->nstaticsessions == 0) && (u->nsessions == 0))
{
pool_put (tsm->users, u);
clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 0);
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown_protocol");
+ nat_log_info ("unknown protocol");
return VNET_API_ERROR_INVALID_VALUE_2;
}
break;
kv.value = m - sm->static_mappings;
if (clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 1))
{
- clib_warning ("static_mapping_by_external key add failed");
+ nat_log_err ("static_mapping_by_external key add failed");
return VNET_API_ERROR_UNSPECIFIED;
}
kv.value = ~0ULL;
if (clib_bihash_add_del_8_8(&tsm->out2in, &kv, 1))
{
- clib_warning ("out2in key add failed");
+ nat_log_err ("out2in key add failed");
return VNET_API_ERROR_UNSPECIFIED;
}
kv.value = ~0ULL;
if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 1))
{
- clib_warning ("in2out key add failed");
+ nat_log_err ("in2out key add failed");
return VNET_API_ERROR_UNSPECIFIED;
}
}
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown_protocol");
+ nat_log_info ("unknown protocol");
return VNET_API_ERROR_INVALID_VALUE_2;
}
break;
kv.key = m_key.as_u64;
if (clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 0))
{
- clib_warning ("static_mapping_by_external key del failed");
+ nat_log_err ("static_mapping_by_external key del failed");
return VNET_API_ERROR_UNSPECIFIED;
}
kv.key = m_key.as_u64;
if (clib_bihash_add_del_8_8(&tsm->out2in, &kv, 0))
{
- clib_warning ("outi2in key del failed");
+ nat_log_err ("outi2in key del failed");
return VNET_API_ERROR_UNSPECIFIED;
}
kv.key = m_key.as_u64;
if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0))
{
- clib_warning ("static_mapping_by_local key del failed");
+ nat_log_err ("static_mapping_by_local key del failed");
return VNET_API_ERROR_UNSPECIFIED;
}
}
kv.key = m_key.as_u64;
if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 0))
{
- clib_warning ("in2out key del failed");
+ nat_log_err ("in2out key del failed");
return VNET_API_ERROR_UNSPECIFIED;
}
}
continue;
nat_free_session_data (sm, s, tsm - sm->per_thread_data);
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- pool_put_index (tsm->list_pool, s->per_user_index);
- pool_put (tsm->sessions, s);
- u->nstaticsessions--;
+ nat44_delete_session (sm, s, tsm - sm->per_thread_data);
}
}
}
snat_address_t *a = 0;
snat_session_t *ses;
u32 *ses_to_be_removed = 0, *ses_index;
- clib_bihash_kv_8_8_t kv, value;
- snat_user_key_t user_key;
- snat_user_t *u;
snat_main_per_thread_data_t *tsm;
snat_static_mapping_t *m;
snat_interface_t *interface;
/* Check if address is used in some static mapping */
if (is_snat_address_used_in_static_mapping(sm, addr))
{
- clib_warning ("address used in static mapping");
+ nat_log_notice ("address used in static mapping");
return VNET_API_ERROR_UNSPECIFIED;
}
}
{
ses->outside_address_index = ~0;
nat_free_session_data (sm, ses, tsm - sm->per_thread_data);
- clib_dlist_remove (tsm->list_pool, ses->per_user_index);
- pool_put_index (tsm->list_pool, ses->per_user_index);
vec_add1 (ses_to_be_removed, ses - tsm->sessions);
- user_key.addr = ses->in2out.addr;
- user_key.fib_index = ses->in2out.fib_index;
- kv.key = user_key.as_u64;
- if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
- {
- u = pool_elt_at_index (tsm->users, value.value);
- u->nsessions--;
- }
}
}));
vec_foreach (ses_index, ses_to_be_removed)
- pool_put_index (tsm->sessions, ses_index[0]);
+ {
+ ses = pool_elt_at_index (tsm->sessions, ses_index[0]);
+ nat44_delete_session (sm, ses, tsm - sm->per_thread_data);
+ }
vec_free (ses_to_be_removed);
}
}
if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
- sm->fq_in2out_index = vlib_frame_queue_main_init (sm->in2out_node_index, 0);
+ sm->fq_in2out_index = vlib_frame_queue_main_init (sm->in2out_node_index,
+ NAT_FQ_NELTS);
if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
- sm->fq_out2in_index = vlib_frame_queue_main_init (sm->out2in_node_index, 0);
+ sm->fq_out2in_index = vlib_frame_queue_main_init (sm->out2in_node_index,
+ NAT_FQ_NELTS);
pool_foreach (i, sm->interfaces,
({
sw_if_index, 0, 0, 0);
vnet_feature_enable_disable ("ip4-unicast", feature_name,
sw_if_index, 1, 0, 0);
+ if (!is_inside)
+ vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
+ sw_if_index, 1, 0, 0);
}
else
{
vnet_feature_enable_disable ("ip4-unicast", feature_name,
sw_if_index, 0, 0, 0);
pool_put (sm->interfaces, i);
+ if (is_inside)
+ vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
+ sw_if_index, 0, 0, 0);
}
}
else
sw_if_index, 0, 0, 0);
vnet_feature_enable_disable ("ip4-unicast", feature_name,
sw_if_index, 1, 0, 0);
+ if (!is_inside)
+ vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
+ sw_if_index, 0, 0, 0);
goto set_flags;
}
i->flags = 0;
vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, 0, 0);
+ if (is_inside && !sm->out2in_dpo)
+ vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
+ sw_if_index, 1, 0, 0);
+
set_flags:
if (is_inside)
- i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
+ {
+ i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
+ return 0;
+ }
else
i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
/* Add/delete external addresses to FIB */
fib:
- if (is_inside && !sm->out2in_dpo)
- {
- vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
- sw_if_index, !is_del, 0, 0);
- return 0;
- }
-
vec_foreach (ap, sm->addresses)
snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
uword *bitmap = 0;
u32 i;
ip4_add_del_interface_address_callback_t cb4;
+ vlib_node_t * error_drop_node;
sm->vlib_main = vm;
sm->vnet_main = vnet_get_main();
sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
sm->alloc_addr_and_port = nat_alloc_addr_and_port_default;
sm->forwarding_enabled = 0;
+ sm->log_class = vlib_log_register_class ("nat", 0);
+ error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
+ sm->error_node_index = error_drop_node->index;
p = hash_get_mem (tm->thread_registrations_by_name, "workers");
if (p)
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown_protocol");
+ nat_log_info ("unknown protocol");
return;
}
}
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown protocol");
+ nat_log_info ("unknown protocol");
return 1;
}
foreach_snat_protocol
#undef _
default:
- clib_warning ("unknown protocol");
+ nat_log_info ("unknown protocol");
return 1;
}
}
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown protocol");
+ nat_log_info ("unknown protocol");
return 1;
}
return s;
}
+u8 * format_snat_key (u8 * s, va_list * args);
+
+u8 *
+format_session_kvp (u8 * s, va_list * args)
+{
+ clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
+ snat_session_key_t k;
+
+ k.as_u64 = v->key;
+
+ s = format (s, "%U session-index %llu", format_snat_key, &k, v->value);
+
+ return s;
+}
+
+u8 *
+format_static_mapping_kvp (u8 * s, va_list * args)
+{
+ clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
+ snat_session_key_t k;
+
+ k.as_u64 = v->key;
+
+ s = format (s, "%U static-mapping-index %llu", format_snat_key, &k, v->value);
+
+ return s;
+}
+
+u8 *
+format_user_kvp (u8 * s, va_list * args)
+{
+ clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
+ snat_user_key_t k;
+
+ k.as_u64 = v->key;
+
+ s = format (s, "%U fib %d user-index %llu", format_ip4_address, &k.addr,
+ k.fib_index, v->value);
+
+ return s;
+}
+
+u8 *
+format_ed_session_kvp (u8 * s, va_list * args)
+{
+ clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *);
+ nat_ed_ses_key_t k;
+
+ k.as_u64[0] = v->key[0];
+ k.as_u64[1] = v->key[1];
+
+ s = format (s, "local %U:%d remote %U:%d proto %U fib %d session-index %llu",
+ format_ip4_address, &k.l_addr, clib_net_to_host_u16 (k.l_port),
+ format_ip4_address, &k.r_addr, clib_net_to_host_u16 (k.r_port),
+ format_ip_protocol, k.proto, k.fib_index, v->value);
+
+ return s;
+}
+
static u32
snat_get_worker_in2out_cb (ip4_header_t * ip0, u32 rx_fib_index0)
{
{
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);
}
clib_bihash_init_16_8 (&sm->in2out_ed, "in2out-ed",
translation_buckets, translation_memory_size);
+ clib_bihash_set_kvp_format_fn_16_8 (&sm->in2out_ed,
+ format_ed_session_kvp);
clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed",
translation_buckets, translation_memory_size);
+ clib_bihash_set_kvp_format_fn_16_8 (&sm->out2in_ed,
+ format_ed_session_kvp);
}
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);
}
return 0;
u8 * format_snat_session (u8 * s, va_list * args)
{
- snat_main_t * sm __attribute__((unused)) = va_arg (*args, snat_main_t *);
+ snat_main_per_thread_data_t * sm = va_arg (*args, snat_main_per_thread_data_t *);
snat_session_t * sess = va_arg (*args, snat_session_t *);
if (snat_is_unk_proto_session (sess))
s = format (s, " i2o %U\n", format_snat_key, &sess->in2out);
s = format (s, " o2i %U\n", format_snat_key, &sess->out2in);
}
- if (is_twice_nat_session (sess))
+ if (is_ed_session (sess) || is_fwd_bypass_session (sess))
{
- s = format (s, " external host o2i %U:%d i2o %U:%d\n",
- format_ip4_address, &sess->ext_host_addr,
- clib_net_to_host_u16 (sess->ext_host_port),
- format_ip4_address, &sess->ext_host_nat_addr,
- clib_net_to_host_u16 (sess->ext_host_nat_port));
- }
- else
- {
- if (sess->ext_host_addr.as_u32)
- s = format (s, " external host %U\n",
- format_ip4_address, &sess->ext_host_addr);
+ if (is_twice_nat_session (sess))
+ {
+ s = format (s, " external host o2i %U:%d i2o %U:%d\n",
+ format_ip4_address, &sess->ext_host_addr,
+ clib_net_to_host_u16 (sess->ext_host_port),
+ format_ip4_address, &sess->ext_host_nat_addr,
+ clib_net_to_host_u16 (sess->ext_host_nat_port));
+ }
+ else
+ {
+ if (sess->ext_host_addr.as_u32)
+ s = format (s, " external host %U:%u\n",
+ format_ip4_address, &sess->ext_host_addr,
+ clib_net_to_host_u16 (sess->ext_host_port));
+ }
}
+ s = format (s, " index %llu\n", sess - sm->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);
s = format (s, " static translation\n");
else
s = format (s, " dynamic translation\n");
- if (sess->flags & SNAT_SESSION_FLAG_LOAD_BALANCING)
+ if (is_fwd_bypass_session (sess))
+ s = format (s, " forwarding-bypass\n");
+ if (is_lb_session (sess))
s = format (s, " load-balancing\n");
if (is_twice_nat_session (sess))
s = format (s, " twice-nat\n");
nat44_lb_addr_port_t *local;
if (m->addr_only)
- s = format (s, "local %U external %U vrf %d %s",
+ s = format (s, "local %U external %U vrf %d %s %s",
format_ip4_address, &m->local_addr,
format_ip4_address, &m->external_addr,
m->vrf_id,
m->twice_nat == TWICE_NAT ? "twice-nat" :
- m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "");
+ m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
+ m->out2in_only ? "out2in-only" : "");
else
{
if (vec_len (m->locals))
!is_delete,
0, 0, rp->tag);
if (rv)
- clib_warning ("snat_add_static_mapping returned %d", rv);
+ nat_log_notice ("snat_add_static_mapping returned %d", rv);
}
static void
rp->is_add,
0, 0, rp->tag);
if (rv)
- clib_warning ("snat_add_static_mapping returned %d",
- rv);
+ nat_log_notice ("snat_add_static_mapping returned %d", rv);
}
}
return;
snat_session_key_t key;
snat_session_t *s;
clib_bihash_8_8_t *t;
- snat_user_key_t u_key;
- snat_user_t *u;
ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
if (sm->num_workers > 1)
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);
- kv.key = s->in2out.as_u64;
- clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0);
- kv.key = s->out2in.as_u64;
- clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0);
- u_key.addr = s->in2out.addr;
- u_key.fib_index = s->in2out.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);
- u->nsessions--;
- }
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- pool_put (tsm->sessions, s);
+ nat_free_session_data (sm, s, tsm - sm->per_thread_data);
+ 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)
+{
+ ip4_header_t ip;
+ clib_bihash_16_8_t *t;
+ nat_ed_ses_key_t key;
+ clib_bihash_kv_16_8_t kv, value;
+ u32 thread_index;
+ u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
+ snat_session_t *s;
+
+ ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
+ if (sm->num_workers > 1)
+ thread_index = sm->worker_in2out_cb (&ip, fib_index);
+ else
+ thread_index = sm->num_workers;
+
+ t = is_in ? &sm->in2out_ed : &sm->out2in_ed;
+ key.l_addr.as_u32 = addr->as_u32;
+ key.r_addr.as_u32 = eh_addr->as_u32;
+ key.l_port = clib_host_to_net_u16 (port);
+ key.r_port = clib_host_to_net_u16 (eh_port);
+ key.proto = proto;
+ key.fib_index = clib_host_to_net_u32 (fib_index);
+ kv.key[0] = key.as_u64[0];
+ kv.key[1] = key.as_u64[1];
+ if (clib_bihash_search_16_8 (t, &kv, &value))
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+
+ if (pool_is_free_index (sm->per_thread_data[thread_index].sessions, value.value))
+ return VNET_API_ERROR_UNSPECIFIED;
+ s = pool_elt_at_index (sm->per_thread_data[thread_index].sessions, value.value);
+ nat_free_session_data (sm, s, thread_index);
+ nat44_delete_session (sm, s, thread_index);
+ return 0;
+}
+
void
nat_set_alloc_addr_and_port_mape (u16 psid, u16 psid_offset, u16 psid_length)
{