From 624b8d9807ac449c4077df4d2d4f40313597a224 Mon Sep 17 00:00:00 2001 From: Matus Fabian Date: Tue, 12 Sep 2017 04:15:30 -0700 Subject: NAT: fixed bug in snat_alloc_outside_address_and_port (VPP-981) Change-Id: I6c5eccd4193c44604da3fd27c108defe71b38a4b Signed-off-by: Matus Fabian --- src/plugins/nat/in2out.c | 4 ++-- src/plugins/nat/nat.c | 30 ++++++++++++++++++++++++------ src/plugins/nat/nat.h | 4 +++- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/plugins/nat/in2out.c b/src/plugins/nat/in2out.c index efb3856b..d0a13237 100644 --- a/src/plugins/nat/in2out.c +++ b/src/plugins/nat/in2out.c @@ -354,7 +354,7 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, s->in2out.fib_index); snat_free_outside_address_and_port - (sm, &s->out2in, s->outside_address_index); + (sm, thread_index, &s->out2in, s->outside_address_index); } s->outside_address_index = ~0; @@ -1283,7 +1283,7 @@ create_ses: s->out2in.port, s->in2out.fib_index); - snat_free_outside_address_and_port (sm, &s->out2in, + snat_free_outside_address_and_port (sm, thread_index, &s->out2in, s->outside_address_index); /* Remove in2out, out2in keys */ diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index faf75fcb..b98b8347 100644 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -152,6 +152,7 @@ void snat_add_address (snat_main_t *sm, ip4_address_t *addr, u32 vrf_id) { 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; @@ -172,7 +173,9 @@ void snat_add_address (snat_main_t *sm, ip4_address_t *addr, u32 vrf_id) 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 _ @@ -339,7 +342,10 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, 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 _ @@ -432,7 +438,10 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, 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 _ @@ -647,7 +656,10 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 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++; \ + a->busy_##n##_ports_per_thread[e_port / sm->port_per_thread]++; \ + } \ break; foreach_snat_protocol #undef _ @@ -773,7 +785,10 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, 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 _ @@ -1241,6 +1256,7 @@ static clib_error_t * snat_init (vlib_main_t * vm) 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) { @@ -1260,6 +1276,7 @@ void snat_free_outside_address_and_port (snat_main_t * sm, 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 _ @@ -1382,7 +1399,7 @@ int snat_alloc_outside_address_and_port (snat_main_t * sm, { #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) \ { \ @@ -1392,6 +1409,7 @@ int snat_alloc_outside_address_and_port (snat_main_t * sm, 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); \ diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h index 8935144d..d1ba5d55 100644 --- a/src/plugins/nat/nat.h +++ b/src/plugins/nat/nat.h @@ -182,7 +182,8 @@ typedef struct { ip4_address_t addr; u32 fib_index; #define _(N, i, n, s) \ - u32 busy_##n##_ports; \ + u16 busy_##n##_ports; \ + u16 * busy_##n##_ports_per_thread; \ uword * busy_##n##_port_bitmap; foreach_snat_protocol #undef _ @@ -389,6 +390,7 @@ extern vlib_node_registration_t snat_hairpin_dst_node; extern vlib_node_registration_t snat_hairpin_src_node; void snat_free_outside_address_and_port (snat_main_t * sm, + u32 thread_index, snat_session_key_t * k, u32 address_index); -- cgit 1.2.3-korg