snat_main_per_thread_data_t *tsm =
vec_elt_at_index (sm->per_thread_data, thread_index);
+ if (is_fwd_bypass_session (s))
+ {
+ ed_key.l_addr = s->in2out.addr;
+ ed_key.r_addr = s->ext_host_addr;
+ ed_key.l_port = s->in2out.port;
+ ed_key.r_port = s->ext_host_port;
+ ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
+ ed_key.fib_index = 0;
+ 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");
+ return;
+ }
+
/* Endpoint dependent session lookup tables */
if (is_ed_session (s))
{
/* 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
{
u32 n_left_from, * from, * to_next;
nat44_classify_next_t next_index;
snat_main_t *sm = &snat_main;
+ snat_static_mapping_t *m;
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
kv0.key = m_key0.as_u64;
if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv0, &value0))
{
- next0 = NAT44_CLASSIFY_NEXT_OUT2IN;
+ m = pool_elt_at_index (sm->static_mappings, value0.value);
+ if (m->local_addr.as_u32 != m->external_addr.as_u32)
+ next0 = NAT44_CLASSIFY_NEXT_OUT2IN;
goto enqueue0;
}
udp_header_t * udp0 = ip4_next_header (ip0);
m_key0.protocol = ip_proto_to_snat_proto (ip0->protocol);
kv0.key = m_key0.as_u64;
if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv0, &value0))
- next0 = NAT44_CLASSIFY_NEXT_OUT2IN;
+ {
+ m = pool_elt_at_index (sm->static_mappings, value0.value);
+ if (m->local_addr.as_u32 != m->external_addr.as_u32)
+ next0 = NAT44_CLASSIFY_NEXT_OUT2IN;
+ }
}
enqueue0:
* @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 1 translate external host address and port.
+ * @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
*
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,
- u8 twice_nat, u8 out2in_only, u8 * tag)
+ twice_nat_type_t twice_nat, u8 out2in_only,
+ u8 * tag)
{
snat_main_t * sm = &snat_main;
snat_static_mapping_t *m;
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))
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);
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");
+ clib_warning ("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);
int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
snat_protocol_t proto, u32 vrf_id,
nat44_lb_addr_port_t *locals, u8 is_add,
- u8 twice_nat, u8 out2in_only, u8 *tag)
+ twice_nat_type_t twice_nat, u8 out2in_only,
+ u8 *tag)
{
snat_main_t * sm = &snat_main;
snat_static_mapping_t *m;
if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
{
u = pool_elt_at_index (tsm->users, value.value);
- u->nsessions--;
+ if (snat_is_session_static (ses))
+ u->nstaticsessions--;
+ else
+ u->nsessions--;
}
}
}));
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);
pool_foreach (m, sm->static_mappings,
({
- if (!(m->addr_only))
+ if (!(m->addr_only) || (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_session_key_t * mapping,
u8 by_external,
u8 *is_addr_only,
- u8 *twice_nat,
+ twice_nat_type_t *twice_nat,
u8 *lb)
{
clib_bihash_kv_8_8_t kv, value;
snat_config (vlib_main_t * vm, unformat_input_t * input)
{
snat_main_t * sm = &snat_main;
+ nat66_main_t * nm = &nat66_main;
u32 translation_buckets = 1024;
u32 translation_memory_size = 128<<20;
u32 user_buckets = 128;
u32 user_memory_size = 64<<20;
u32 max_translations_per_user = 100;
u32 outside_vrf_id = 0;
+ u32 outside_ip6_vrf_id = 0;
u32 inside_vrf_id = 0;
u32 static_mapping_buckets = 1024;
u32 static_mapping_memory_size = 64<<20;
else if (unformat (input, "outside VRF id %d",
&outside_vrf_id))
;
+ else if (unformat (input, "outside ip6 VRF id %d",
+ &outside_ip6_vrf_id))
+ ;
else if (unformat (input, "inside VRF id %d",
&inside_vrf_id))
;
sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
outside_vrf_id,
FIB_SOURCE_PLUGIN_HI);
+ nm->outside_vrf_id = outside_ip6_vrf_id;
+ nm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
+ outside_ip6_vrf_id,
+ FIB_SOURCE_PLUGIN_HI);
sm->inside_vrf_id = inside_vrf_id;
sm->inside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
inside_vrf_id,
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, " last heard %.2f\n", sess->last_heard);
s = format (s, " total pkts %d, total bytes %lld\n",
s = format (s, " static translation\n");
else
s = format (s, " dynamic translation\n");
+ if (is_fwd_bypass_session (sess))
+ s = format (s, " forwarding-bypass\n");
if (sess->flags & SNAT_SESSION_FLAG_LOAD_BALANCING)
s = format (s, " load-balancing\n");
if (is_twice_nat_session (sess))
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" : "");
+ m->vrf_id,
+ m->twice_nat == TWICE_NAT ? "twice-nat" :
+ m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
+ m->out2in_only ? "out2in-only" : "");
else
{
if (vec_len (m->locals))
format_snat_protocol, m->proto,
m->vrf_id,
format_ip4_address, &m->external_addr, m->external_port,
- m->twice_nat ? "twice-nat" : "",
+ m->twice_nat == TWICE_NAT ? "twice-nat" :
+ m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
m->out2in_only ? "out2in-only" : "");
vec_foreach (local, m->locals)
s = format (s, "\n local %U:%d probability %d\%",
format_snat_protocol, m->proto,
format_ip4_address, &m->local_addr, m->local_port,
format_ip4_address, &m->external_addr, m->external_port,
- m->vrf_id, m->twice_nat ? "twice-nat" : "",
+ m->vrf_id,
+ m->twice_nat == TWICE_NAT ? "twice-nat" :
+ m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
m->out2in_only ? "out2in-only" : "");
}
return s;
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);
if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
{
u = pool_elt_at_index (tsm->users, value.value);
- u->nsessions--;
+ if (snat_is_session_static (s))
+ u->nstaticsessions--;
+ else
+ u->nsessions--;
}
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);
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)
{