{
snat_address_t * ap;
snat_interface_t *i;
+ vlib_thread_main_t *tm = vlib_get_thread_main ();
if (vrf_id != ~0)
sm->vrf_mode = 1;
ap->addr = *addr;
if (vrf_id != ~0)
ap->fib_index =
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id);
+ fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
+ FIB_SOURCE_PLUGIN_HI);
else
ap->fib_index = ~0;
#define _(N, i, n, s) \
- clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535);
+ clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535); \
+ ap->busy_##n##_ports = 0; \
+ vec_validate_init_empty (ap->busy_##n##_ports_per_thread, tm->n_vlib_mains - 1, 0);
foreach_snat_protocol
#undef _
return VNET_API_ERROR_INVALID_VALUE; \
clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
if (e_port > 1024) \
- a->busy_##n##_ports++; \
+ { \
+ a->busy_##n##_ports++; \
+ a->busy_##n##_ports_per_thread[e_port / sm->port_per_thread]++; \
+ } \
break;
foreach_snat_protocol
#undef _
case SNAT_PROTOCOL_##N: \
clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
if (e_port > 1024) \
- a->busy_##n##_ports--; \
+ { \
+ a->busy_##n##_ports--; \
+ a->busy_##n##_ports_per_thread[e_port / sm->port_per_thread]--; \
+ } \
break;
foreach_snat_protocol
#undef _
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 (&sm->user_hash, &kv, &value))
+ if (!clib_bihash_search_8_8 (&sm->worker_by_in, &kv, &value))
+ tsm = vec_elt_at_index (sm->per_thread_data, value.value);
+ else
+ tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
+ if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
{
user_index = value.value;
- if (!clib_bihash_search_8_8 (&sm->worker_by_in, &kv, &value))
- tsm = vec_elt_at_index (sm->per_thread_data, value.value);
- else
- tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
u = pool_elt_at_index (tsm->users, user_index);
if (u->nstaticsessions)
{
if (snat_is_unk_proto_session (s))
{
clib_bihash_kv_16_8_t up_kv;
- snat_unk_proto_ses_key_t up_key;
+ nat_ed_ses_key_t up_key;
up_key.l_addr = s->in2out.addr;
up_key.r_addr = s->ext_host_addr;
up_key.fib_index = s->in2out.fib_index;
up_key.proto = s->in2out.port;
- up_key.rsvd[0] = up_key.rsvd[1] = up_key.rsvd[2] = 0;
+ up_key.rsvd = 0;
+ up_key.l_port = 0;
up_kv.key[0] = up_key.as_u64[0];
up_kv.key[1] = up_key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->in2out_unk_proto,
+ if (clib_bihash_add_del_16_8 (&sm->in2out_ed,
&up_kv, 0))
clib_warning ("in2out key del failed");
up_key.fib_index = s->out2in.fib_index;
up_kv.key[0] = up_key.as_u64[0];
up_kv.key[1] = up_key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->out2in_unk_proto,
+ if (clib_bihash_add_del_16_8 (&sm->out2in_ed,
&up_kv, 0))
clib_warning ("out2in key del failed");
s->in2out.fib_index);
value.key = s->in2out.as_u64;
- if (clib_bihash_add_del_8_8 (&sm->in2out, &value, 0))
+ if (clib_bihash_add_del_8_8 (&tsm->in2out, &value, 0))
clib_warning ("in2out key del failed");
value.key = s->out2in.as_u64;
- if (clib_bihash_add_del_8_8 (&sm->out2in, &value, 0))
+ if (clib_bihash_add_del_8_8 (&tsm->out2in, &value, 0))
clib_warning ("out2in key del failed");
delete:
pool_put (tsm->sessions, s);
if (addr_only)
{
pool_put (tsm->users, u);
- clib_bihash_add_del_8_8 (&sm->user_hash, &kv, 0);
+ clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 0);
}
}
}
return 0;
}
+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)
+{
+ snat_main_t * sm = &snat_main;
+ snat_static_mapping_t *m;
+ snat_session_key_t m_key;
+ clib_bihash_kv_8_8_t kv, value;
+ u32 fib_index;
+ snat_address_t *a = 0;
+ int i;
+ nat44_lb_addr_port_t *local;
+ snat_user_key_t w_key0;
+ snat_worker_key_t w_key1;
+ u32 worker_index = 0;
+ snat_main_per_thread_data_t *tsm;
+
+ m_key.addr = e_addr;
+ m_key.port = e_port;
+ m_key.protocol = proto;
+ m_key.fib_index = sm->outside_fib_index;
+ kv.key = m_key.as_u64;
+ if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
+ m = 0;
+ else
+ m = pool_elt_at_index (sm->static_mappings, value.value);
+
+ if (is_add)
+ {
+ if (m)
+ return VNET_API_ERROR_VALUE_EXIST;
+
+ if (vec_len (locals) < 2)
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
+ vrf_id,
+ FIB_SOURCE_PLUGIN_HI);
+
+ /* Find external address in allocated addresses and reserve port for
+ address and port pair mapping when dynamic translations enabled */
+ if (!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 SNAT_PROTOCOL_##N: \
+ if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \
+ return VNET_API_ERROR_INVALID_VALUE; \
+ clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
+ if (e_port > 1024) \
+ { \
+ a->busy_##n##_ports++; \
+ a->busy_##n##_ports_per_thread[e_port / sm->port_per_thread]++; \
+ } \
+ break;
+ foreach_snat_protocol
+#undef _
+ default:
+ clib_warning("unknown_protocol");
+ return VNET_API_ERROR_INVALID_VALUE_2;
+ }
+ break;
+ }
+ }
+ /* External address must be allocated */
+ if (!a)
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
+
+ pool_get (sm->static_mappings, m);
+ memset (m, 0, sizeof (*m));
+ m->external_addr = e_addr;
+ m->addr_only = 0;
+ m->vrf_id = vrf_id;
+ m->fib_index = fib_index;
+ m->external_port = e_port;
+ m->proto = proto;
+
+ m_key.addr = m->external_addr;
+ m_key.port = m->external_port;
+ m_key.protocol = m->proto;
+ m_key.fib_index = sm->outside_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_external, &kv, 1))
+ {
+ clib_warning ("static_mapping_by_external key add failed");
+ return VNET_API_ERROR_UNSPECIFIED;
+ }
+
+ /* Assign worker */
+ if (sm->workers)
+ {
+ w_key0.addr = locals[0].addr;
+ w_key0.fib_index = fib_index;
+ kv.key = w_key0.as_u64;
+
+ if (clib_bihash_search_8_8 (&sm->worker_by_in, &kv, &value))
+ worker_index = sm->first_worker_index +
+ sm->workers[sm->next_worker++ % vec_len (sm->workers)];
+ else
+ worker_index = value.value;
+
+ w_key1.addr = m->external_addr;
+ w_key1.port = clib_host_to_net_u16 (m->external_port);
+ w_key1.fib_index = sm->outside_fib_index;
+ kv.key = w_key1.as_u64;
+ kv.value = worker_index;
+ if (clib_bihash_add_del_8_8 (&sm->worker_by_out, &kv, 1))
+ {
+ clib_warning ("worker-by-out add key failed");
+ return VNET_API_ERROR_UNSPECIFIED;
+ }
+ tsm = vec_elt_at_index (sm->per_thread_data, worker_index);
+ }
+ else
+ tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
+
+ m_key.port = clib_host_to_net_u16 (m->external_port);
+ kv.key = m_key.as_u64;
+ kv.value = ~0ULL;
+ if (clib_bihash_add_del_8_8(&tsm->out2in, &kv, 1))
+ {
+ clib_warning ("static_mapping_by_local key add failed");
+ return VNET_API_ERROR_UNSPECIFIED;
+ }
+
+ m_key.fib_index = m->fib_index;
+ for (i = 0; i < vec_len (locals); i++)
+ {
+ m_key.addr = locals[i].addr;
+ m_key.port = locals[i].port;
+ 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);
+ locals[i].prefix = (i == 0) ? locals[i].probability :\
+ (locals[i - 1].prefix + locals[i].probability);
+ vec_add1 (m->locals, locals[i]);
+ m_key.port = clib_host_to_net_u16 (locals[i].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");
+ return VNET_API_ERROR_UNSPECIFIED;
+ }
+ /* Assign worker */
+ if (sm->workers)
+ {
+ w_key0.addr = locals[i].addr;
+ w_key0.fib_index = fib_index;
+ kv.key = w_key0.as_u64;
+ kv.value = worker_index;
+ if (clib_bihash_add_del_8_8 (&sm->worker_by_in, &kv, 1))
+ {
+ clib_warning ("worker-by-in key add failed");
+ return VNET_API_ERROR_UNSPECIFIED;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!m)
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+
+ fib_table_unlock (m->fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_HI);
+
+ /* Free external address port */
+ if (!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 SNAT_PROTOCOL_##N: \
+ clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
+ if (e_port > 1024) \
+ { \
+ a->busy_##n##_ports--; \
+ a->busy_##n##_ports_per_thread[e_port / sm->port_per_thread]--; \
+ } \
+ break;
+ foreach_snat_protocol
+#undef _
+ default:
+ clib_warning("unknown_protocol");
+ return VNET_API_ERROR_INVALID_VALUE_2;
+ }
+ break;
+ }
+ }
+ }
+
+ w_key1.addr = m->external_addr;
+ w_key1.port = clib_host_to_net_u16 (m->external_port);
+ w_key1.fib_index = sm->outside_fib_index;
+ kv.key = w_key1.as_u64;
+ if (!clib_bihash_search_8_8 (&sm->worker_by_out, &kv, &value))
+ tsm = vec_elt_at_index (sm->per_thread_data, value.value);
+ else
+ tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
+
+ m_key.addr = m->external_addr;
+ m_key.port = m->external_port;
+ m_key.protocol = m->proto;
+ m_key.fib_index = sm->outside_fib_index;
+ 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");
+ return VNET_API_ERROR_UNSPECIFIED;
+ }
+ m_key.port = clib_host_to_net_u16 (m->external_port);
+ kv.key = m_key.as_u64;
+ if (clib_bihash_add_del_8_8(&tsm->out2in, &kv, 0))
+ {
+ clib_warning ("outi2in key del failed");
+ return VNET_API_ERROR_UNSPECIFIED;
+ }
+
+ vec_foreach (local, m->locals)
+ {
+ m_key.addr = local->addr;
+ m_key.port = local->port;
+ m_key.fib_index = m->fib_index;
+ 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");
+ return VNET_API_ERROR_UNSPECIFIED;
+ }
+ m_key.port = clib_host_to_net_u16 (local->port);
+ kv.key = m_key.as_u64;
+ if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 0))
+ {
+ clib_warning ("in2out key del failed");
+ return VNET_API_ERROR_UNSPECIFIED;
+ }
+ }
+ vec_free(m->locals);
+
+ pool_put (sm->static_mappings, m);
+ }
+
+ return 0;
+}
+
int snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm)
{
snat_address_t *a = 0;
}
if (a->fib_index != ~0)
- fib_table_unlock(a->fib_index, FIB_PROTOCOL_IP4);
+ fib_table_unlock(a->fib_index, FIB_PROTOCOL_IP4,
+ FIB_SOURCE_PLUGIN_HI);
/* Delete sessions using address */
if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
if (snat_is_unk_proto_session (ses))
{
clib_bihash_kv_16_8_t up_kv;
- snat_unk_proto_ses_key_t up_key;
+ nat_ed_ses_key_t up_key;
up_key.l_addr = ses->in2out.addr;
up_key.r_addr = ses->ext_host_addr;
up_key.fib_index = ses->in2out.fib_index;
up_key.proto = ses->in2out.port;
- up_key.rsvd[0] = up_key.rsvd[1] = up_key.rsvd[2] = 0;
+ up_key.rsvd = 0;
+ up_key.l_port = 0;
up_kv.key[0] = up_key.as_u64[0];
up_kv.key[1] = up_key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->in2out_unk_proto,
+ if (clib_bihash_add_del_16_8 (&sm->in2out_ed,
&up_kv, 0))
clib_warning ("in2out key del failed");
up_key.fib_index = ses->out2in.fib_index;
up_kv.key[0] = up_key.as_u64[0];
up_kv.key[1] = up_key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->out2in_unk_proto,
+ if (clib_bihash_add_del_16_8 (&sm->out2in_ed,
&up_kv, 0))
clib_warning ("out2in key del failed");
}
ses->out2in.port,
ses->in2out.fib_index);
kv.key = ses->in2out.as_u64;
- clib_bihash_add_del_8_8 (&sm->in2out, &kv, 0);
+ clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0);
kv.key = ses->out2in.as_u64;
- clib_bihash_add_del_8_8 (&sm->out2in, &kv, 0);
+ clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0);
}
vec_add1 (ses_to_be_removed, ses - tsm->sessions);
clib_dlist_remove (tsm->list_pool, ses->per_user_index);
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 (&sm->user_hash, &kv, &value))
+ if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
{
u = pool_elt_at_index (tsm->users, value.value);
u->nsessions--;
VLIB_INIT_FUNCTION (snat_init);
void snat_free_outside_address_and_port (snat_main_t * sm,
+ u32 thread_index,
snat_session_key_t * k,
u32 address_index)
{
clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
port_host_byte_order, 0); \
a->busy_##n##_ports--; \
+ a->busy_##n##_ports_per_thread[thread_index]--; \
break;
foreach_snat_protocol
#undef _
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;
if (by_external)
mapping_hash = &sm->static_mapping_by_external;
if (by_external)
{
- mapping->addr = m->local_addr;
- /* Address only mapping doesn't change port */
- mapping->port = m->addr_only ? match.port
- : clib_host_to_net_u16 (m->local_port);
+ if (vec_len (m->locals))
+ {
+ hi = vec_len (m->locals) - 1;
+ rand = 1 + (random_u32 (&sm->random_seed) % m->locals[hi].prefix);
+ while (lo < hi)
+ {
+ mid = ((hi - lo) >> 1) + lo;
+ (rand > m->locals[mid].prefix) ? (lo = mid + 1) : (hi = mid);
+ }
+ if (!(m->locals[lo].prefix >= rand))
+ return 1;
+ mapping->addr = m->locals[lo].addr;
+ mapping->port = clib_host_to_net_u16 (m->locals[lo].port);
+ }
+ else
+ {
+ mapping->addr = m->local_addr;
+ /* Address only mapping doesn't change port */
+ mapping->port = m->addr_only ? match.port
+ : clib_host_to_net_u16 (m->local_port);
+ }
mapping->fib_index = m->fib_index;
+ mapping->protocol = m->proto;
}
else
{
{
#define _(N, j, n, s) \
case SNAT_PROTOCOL_##N: \
- if (a->busy_##n##_ports < (sm->port_per_thread * sm->num_snat_thread)) \
+ if (a->busy_##n##_ports_per_thread[thread_index] < sm->port_per_thread) \
{ \
while (1) \
{ \
portnum = (sm->port_per_thread * \
sm->per_thread_data[thread_index].snat_thread_index) + \
- snat_random_port(sm, 0, sm->port_per_thread) + 1024; \
+ snat_random_port(sm, 1, sm->port_per_thread) + 1024; \
if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
continue; \
clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
+ a->busy_##n##_ports_per_thread[thread_index]++; \
a->busy_##n##_ports++; \
k->addr = a->addr; \
k->port = clib_host_to_net_u16(portnum); \
VLIB_CLI_COMMAND (add_address_command, static) = {
.path = "nat44 add address",
- .short_help = "nat44 add addresses <ip4-range-start> [- <ip4-range-end>] "
+ .short_help = "nat44 add address <ip4-range-start> [- <ip4-range-end>] "
"[tenant-vrf <vrf-id>] [del]",
.function = add_address_command_fn,
};
* to to the local network host.
* To create static mapping between local host address 10.0.0.3 port 6303 and
* external address 4.4.4.4 port 3606 for TCP protocol use:
- * vpp# nat44 add static mapping local tcp 10.0.0.3 6303 external 4.4.4.4 3606
+ * vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
* If not runnig "static mapping only" NAT plugin mode use before:
* vpp# nat44 add address 4.4.4.4
* To create static mapping between local and external address use:
.path = "nat44 add static mapping",
.function = add_static_mapping_command_fn,
.short_help =
- "nat44 add static mapping local tcp|udp|icmp <addr> [<port>] external <addr> [<port>] [vrf <table-id>] [del]",
+ "nat44 add static mapping tcp|udp|icmp local <addr> [<port>] external <addr> [<port>] [vrf <table-id>] [del]",
+};
+
+static clib_error_t *
+add_lb_static_mapping_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ clib_error_t * error = 0;
+ ip4_address_t l_addr, e_addr;
+ u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0;
+ int is_add = 1;
+ int rv;
+ snat_protocol_t proto;
+ u8 proto_set = 0;
+ nat44_lb_addr_port_t *locals = 0, local;
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "local %U:%u probability %u",
+ unformat_ip4_address, &l_addr, &l_port, &probability))
+ {
+ memset (&local, 0, sizeof (local));
+ local.addr = l_addr;
+ local.port = (u16) l_port;
+ local.probability = (u8) probability;
+ vec_add1 (locals, local);
+ }
+ else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
+ &e_addr, &e_port))
+ ;
+ else if (unformat (line_input, "vrf %u", &vrf_id))
+ ;
+ else if (unformat (line_input, "protocol %U", unformat_snat_protocol,
+ &proto))
+ proto_set = 1;
+ else if (unformat (line_input, "del"))
+ is_add = 0;
+ else
+ {
+ error = clib_error_return (0, "unknown input: '%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
+ }
+
+ if (vec_len (locals) < 2)
+ {
+ error = clib_error_return (0, "at least two local must be set");
+ goto done;
+ }
+
+ if (!proto_set)
+ {
+ error = clib_error_return (0, "missing protocol");
+ goto done;
+ }
+
+ rv = nat44_add_del_lb_static_mapping (e_addr, (u16) e_port, proto, vrf_id,
+ locals, is_add);
+
+ switch (rv)
+ {
+ case VNET_API_ERROR_INVALID_VALUE:
+ error = clib_error_return (0, "External port already in use.");
+ goto done;
+ case VNET_API_ERROR_NO_SUCH_ENTRY:
+ if (is_add)
+ error = clib_error_return (0, "External addres must be allocated.");
+ else
+ error = clib_error_return (0, "Mapping not exist.");
+ goto done;
+ case VNET_API_ERROR_VALUE_EXIST:
+ error = clib_error_return (0, "Mapping already exist.");
+ goto done;
+ default:
+ break;
+ }
+
+done:
+ unformat_free (line_input);
+ vec_free (locals);
+
+ return error;
+}
+
+VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
+ .path = "nat44 add load-balancing static mapping",
+ .function = add_lb_static_mapping_command_fn,
+ .short_help =
+ "nat44 add load-balancing static mapping protocol tcp|udp external <addr>:<port> local <addr>:<port> probability <n> [vrf <table-id>] [del]",
};
static clib_error_t *
}
/* Add to translated packets worker lookup */
+ key0.port = udp0->dst_port;
+ kv0.key = key0.as_u64;
kv0.value = next_worker_index;
clib_bihash_add_del_8_8 (&sm->worker_by_out, &kv0, 1);
}
u32 static_mapping_memory_size = 64<<20;
u8 static_mapping_only = 0;
u8 static_mapping_connection_tracking = 0;
+ snat_main_per_thread_data_t *tsm;
sm->deterministic = 0;
sm->max_translations_per_user = max_translations_per_user;
sm->outside_vrf_id = outside_vrf_id;
sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
- outside_vrf_id);
+ outside_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);
+ inside_vrf_id,
+ FIB_SOURCE_PLUGIN_HI);
sm->static_mapping_only = static_mapping_only;
sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
sm->icmp_match_in2out_cb = icmp_match_in2out_slow;
sm->icmp_match_out2in_cb = icmp_match_out2in_slow;
- clib_bihash_init_8_8 (&sm->worker_by_in, "worker-by-in", user_buckets,
- user_memory_size);
-
- clib_bihash_init_8_8 (&sm->worker_by_out, "worker-by-out", user_buckets,
- user_memory_size);
+ vec_foreach (tsm, sm->per_thread_data)
+ {
+ clib_bihash_init_8_8 (&tsm->in2out, "in2out", translation_buckets,
+ translation_memory_size);
- clib_bihash_init_8_8 (&sm->in2out, "in2out", translation_buckets,
- translation_memory_size);
+ clib_bihash_init_8_8 (&tsm->out2in, "out2in", translation_buckets,
+ translation_memory_size);
- clib_bihash_init_8_8 (&sm->out2in, "out2in", translation_buckets,
- translation_memory_size);
+ clib_bihash_init_8_8 (&tsm->user_hash, "users", user_buckets,
+ user_memory_size);
+ }
- clib_bihash_init_8_8 (&sm->user_hash, "users", user_buckets,
+ clib_bihash_init_8_8 (&sm->worker_by_in, "worker-by-in", user_buckets,
user_memory_size);
- clib_bihash_init_16_8 (&sm->in2out_unk_proto, "in2out-unk-proto",
+ clib_bihash_init_8_8 (&sm->worker_by_out, "worker-by-out",
+ translation_buckets, translation_memory_size);
+
+ clib_bihash_init_16_8 (&sm->in2out_ed, "in2out-ed",
translation_buckets, translation_memory_size);
- clib_bihash_init_16_8 (&sm->out2in_unk_proto, "out2in-unk-proto",
+ clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed",
translation_buckets, translation_memory_size);
}
else
u8 * format_snat_key (u8 * s, va_list * args)
{
snat_session_key_t * key = va_arg (*args, snat_session_key_t *);
- char * protocol_string = "unknown";
- static char *protocol_strings[] = {
- "UDP",
- "TCP",
- "ICMP",
- };
- if (key->protocol < ARRAY_LEN(protocol_strings))
- protocol_string = protocol_strings[key->protocol];
-
- s = format (s, "%U proto %s port %d fib %d",
- format_ip4_address, &key->addr, protocol_string,
+ s = format (s, "%U proto %U port %d fib %d",
+ format_ip4_address, &key->addr,
+ format_snat_protocol, key->protocol,
clib_net_to_host_u16 (key->port), key->fib_index);
return s;
}
s = format (s, " i2o %U\n", format_snat_key, &sess->in2out);
s = format (s, " o2i %U\n", format_snat_key, &sess->out2in);
}
+ if (sess->ext_host_addr.as_u32)
+ s = format (s, " external host %U\n",
+ format_ip4_address, &sess->ext_host_addr);
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)
+ s = format (s, " load-balancing\n");
return s;
}
u8 * format_snat_static_mapping (u8 * s, va_list * args)
{
snat_static_mapping_t *m = va_arg (*args, snat_static_mapping_t *);
+ nat44_lb_addr_port_t *local;
if (m->addr_only)
s = format (s, "local %U external %U vrf %d",
format_ip4_address, &m->external_addr,
m->vrf_id);
else
- s = format (s, "%U local %U:%d external %U:%d vrf %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);
-
+ {
+ if (vec_len (m->locals))
+ {
+ s = format (s, "%U vrf %d external %U:%d",
+ format_snat_protocol, m->proto,
+ m->vrf_id,
+ format_ip4_address, &m->external_addr, m->external_port);
+ vec_foreach (local, m->locals)
+ s = format (s, "\n local %U:%d probability %d\%",
+ format_ip4_address, &local->addr, local->port,
+ local->probability);
+ }
+ else
+ s = format (s, "%U local %U:%d external %U:%d vrf %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);
+ }
return s;
}
if (verbose > 0)
{
- vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->in2out,
+ vlib_cli_output (vm, "%U", format_bihash_16_8, &sm->in2out_ed,
verbose - 1);
- vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->out2in,
+ vlib_cli_output (vm, "%U", format_bihash_16_8, &sm->out2in_ed,
verbose - 1);
vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->worker_by_in,
verbose - 1);
vlib_worker_thread_t *w = vlib_worker_threads + j;
vlib_cli_output (vm, "Thread %d (%s at lcore %u):", j, w->name,
w->lcore_id);
+ vlib_cli_output (vm, " %U", format_bihash_8_8, &tsm->in2out,
+ verbose - 1);
+ vlib_cli_output (vm, " %U", format_bihash_8_8, &tsm->out2in,
+ verbose - 1);
vlib_cli_output (vm, " %d list pool elements",
pool_elts (tsm->list_pool));