.node_name = "snat-out2in-fast",
.runs_before = VNET_FEATURES ("ip4-lookup"),
};
+VNET_FEATURE_INIT (ip4_snat_hairpin_dst, static) = {
+ .arc_name = "ip4-unicast",
+ .node_name = "snat-hairpin-dst",
+ .runs_before = VNET_FEATURES ("ip4-lookup"),
+};
/* Hook up output features */
VNET_FEATURE_INIT (ip4_snat_in2out_output, static) = {
.node_name = "snat-in2out-output",
.runs_before = VNET_FEATURES ("interface-output"),
};
-
VNET_FEATURE_INIT (ip4_snat_in2out_output_worker_handoff, static) = {
.arc_name = "ip4-output",
.node_name = "snat-in2out-output-worker-handoff",
.runs_before = VNET_FEATURES ("interface-output"),
};
+VNET_FEATURE_INIT (ip4_snat_hairpin_src, static) = {
+ .arc_name = "ip4-output",
+ .node_name = "snat-hairpin-src",
+ .runs_before = VNET_FEATURES ("interface-output"),
+};
/* *INDENT-OFF* */
(FIB_ENTRY_FLAG_CONNECTED |
FIB_ENTRY_FLAG_LOCAL |
FIB_ENTRY_FLAG_EXCLUSIVE),
- FIB_PROTOCOL_IP4,
+ DPO_PROTO_IP4,
NULL,
sw_if_index,
~0,
vec_add2 (sm->addresses, ap, 1);
ap->addr = *addr;
- ap->fib_index = ip4_fib_index_from_table_id(vrf_id);
+ if (vrf_id != ~0)
+ ap->fib_index =
+ fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id);
+ else
+ ap->fib_index = ~0;
#define _(N, i, n, s) \
clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535);
foreach_snat_protocol
}
}
+ if (a->fib_index != ~0)
+ fib_table_unlock(a->fib_index, FIB_PROTOCOL_IP4);
+
/* Delete sessions using address */
if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
{
return VNET_API_ERROR_UNSUPPORTED;
if (is_inside)
- goto find;
+ {
+ vnet_feature_enable_disable ("ip4-unicast", "snat-hairpin-dst",
+ sw_if_index, !is_del, 0, 0);
+ vnet_feature_enable_disable ("ip4-output", "snat-hairpin-src",
+ sw_if_index, !is_del, 0, 0);
+ goto fq;
+ }
if (sm->num_workers > 1)
{
sw_if_index, !is_del, 0, 0);
}
+fq:
if (sm->fq_in2out_output_index == ~0 && sm->num_workers > 1)
sm->fq_in2out_output_index =
vlib_frame_queue_main_init (sm->in2out_output_node_index, 0);
if (sm->fq_out2in_index == ~0 && sm->num_workers > 1)
sm->fq_out2in_index = vlib_frame_queue_main_init (sm->out2in_node_index, 0);
-find:
pool_foreach (i, sm->output_feature_interfaces,
({
if (i->sw_if_index == sw_if_index)
int snat_set_workers (uword * bitmap)
{
snat_main_t *sm = &snat_main;
- int i;
+ int i, j = 0;
if (sm->num_workers < 2)
return VNET_API_ERROR_FEATURE_DISABLED;
clib_bitmap_foreach (i, bitmap,
({
vec_add1(sm->workers, i);
+ sm->per_thread_data[i].snat_thread_index = j;
+ j++;
}));
+ sm->port_per_thread = (0xffff - 1024) / _vec_len (sm->workers);
+ sm->num_snat_thread = _vec_len (sm->workers);
+
return 0;
}
sm->first_worker_index = 0;
sm->next_worker = 0;
sm->num_workers = 0;
+ sm->num_snat_thread = 1;
sm->workers = 0;
+ sm->port_per_thread = 0xffff - 1024;
sm->fq_in2out_index = ~0;
sm->fq_out2in_index = ~0;
sm->udp_timeout = SNAT_UDP_TIMEOUT;
}
}
+ vec_validate (sm->per_thread_data, tm->n_vlib_mains - 1);
+
/* Use all available workers by default */
if (sm->num_workers > 1)
{
snat_set_workers(bitmap);
clib_bitmap_free (bitmap);
}
+ else
+ {
+ sm->per_thread_data[0].snat_thread_index = 0;
+ }
error = snat_api_init(vm, sm);
if (error)
return 0;
}
-int snat_alloc_outside_address_and_port (snat_main_t * sm,
+static_always_inline u16
+snat_random_port (snat_main_t * sm, u16 min, u16 max)
+{
+ return min + random_u32 (&sm->random_seed) /
+ (random_u32_max() / (max - min + 1) + 1);
+}
+
+int snat_alloc_outside_address_and_port (snat_main_t * sm,
u32 fib_index,
+ u32 thread_index,
snat_session_key_t * k,
u32 * address_indexp)
{
{
#define _(N, j, n, s) \
case SNAT_PROTOCOL_##N: \
- if (a->busy_##n##_ports < (65535-1024)) \
+ if (a->busy_##n##_ports < (sm->port_per_thread * sm->num_snat_thread)) \
{ \
while (1) \
{ \
- portnum = random_u32 (&sm->random_seed); \
- portnum &= 0xFFFF; \
- if (portnum < 1024) \
- continue; \
+ portnum = (sm->port_per_thread * \
+ sm->per_thread_data[thread_index].snat_thread_index) + \
+ snat_random_port(sm, 0, 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); \
u32 static_mapping_memory_size = 64<<20;
u8 static_mapping_only = 0;
u8 static_mapping_connection_tracking = 0;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
sm->deterministic = 0;
clib_bihash_init_8_8 (&sm->worker_by_out, "worker-by-out", user_buckets,
user_memory_size);
- vec_validate (sm->per_thread_data, tm->n_vlib_mains - 1);
-
clib_bihash_init_8_8 (&sm->in2out, "in2out", translation_buckets,
translation_memory_size);