From 5b88feeb7f81905df0cffc5d7cb372c98cfa949e Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Wed, 17 Aug 2022 12:08:31 -0500 Subject: nat: simplify per-protocol code by using an array rather than using obfuscated macro hacery, simplify the per-protocol data management by directly using an array of NAT protocol types. Type: refactor Signed-off-by: Jon Loeliger Change-Id: I6fe987556ac9f402f8d490da0740e2b91440304c --- src/plugins/nat/nat44-ei/nat44_ei.c | 389 +++++++++++++------------------- src/plugins/nat/nat44-ei/nat44_ei.h | 9 +- src/plugins/nat/nat44-ei/nat44_ei_cli.c | 2 +- 3 files changed, 157 insertions(+), 243 deletions(-) (limited to 'src/plugins/nat/nat44-ei') diff --git a/src/plugins/nat/nat44-ei/nat44_ei.c b/src/plugins/nat/nat44-ei/nat44_ei.c index 8446011ec92..448566d93ce 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei.c +++ b/src/plugins/nat/nat44-ei/nat44_ei.c @@ -185,67 +185,26 @@ static int nat44_ei_del_static_mapping_internal ( ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, nat_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags); +always_inline bool +nat44_ei_port_is_used (nat44_ei_address_t *a, u8 proto, u16 port) +{ + return clib_bitmap_get (a->busy_port_bitmap[proto], port); +} + always_inline void nat44_ei_port_get (nat44_ei_address_t *a, u8 proto, u16 port) { - nat44_ei_main_t *nm = &nat44_ei_main; - -#define _(N, i, n, s) \ - case NAT_PROTOCOL_##N: \ - a->busy_##n##_port_bitmap = \ - clib_bitmap_set (a->busy_##n##_port_bitmap, port, 1); \ - break; - - switch (proto) - { - foreach_nat_protocol; - default: - nat_elog_info (nm, "unknown protocol"); - } - -#undef _ + ASSERT (!nat44_ei_port_is_used (a, proto, port)); + a->busy_port_bitmap[proto] = + clib_bitmap_set (a->busy_port_bitmap[proto], port, 1); } always_inline void nat44_ei_port_put (nat44_ei_address_t *a, u8 proto, u16 port) { - nat44_ei_main_t *nm = &nat44_ei_main; - -#define _(N, i, n, s) \ - case NAT_PROTOCOL_##N: \ - a->busy_##n##_port_bitmap = \ - clib_bitmap_set (a->busy_##n##_port_bitmap, port, 0); \ - break; - - switch (proto) - { - foreach_nat_protocol; - default: - nat_elog_info (nm, "unknown protocol"); - } - -#undef _ -} - -always_inline bool -nat44_ei_port_is_used (nat44_ei_address_t *a, u8 proto, u16 port) -{ - nat44_ei_main_t *nm = &nat44_ei_main; - -#define _(N, i, n, s) \ - case NAT_PROTOCOL_##N: \ - return clib_bitmap_get (a->busy_##n##_port_bitmap, port); - - switch (proto) - { - foreach_nat_protocol; - default: - nat_elog_info (nm, "unknown protocol"); - } - -#undef _ - - return 0; + ASSERT (nat44_ei_port_is_used (a, proto, port)); + a->busy_port_bitmap[proto] = + clib_bitmap_set (a->busy_port_bitmap[proto], port, 0); } static u8 * @@ -1304,7 +1263,6 @@ nat44_ei_set_outside_address_and_port (nat44_ei_address_t *addresses, u32 thread_index, ip4_address_t addr, u16 port, nat_protocol_t protocol) { - nat44_ei_main_t *nm = &nat44_ei_main; nat44_ei_address_t *a = 0; u32 address_index; u16 port_host_byte_order = clib_net_to_host_u16 (port); @@ -1315,21 +1273,13 @@ nat44_ei_set_outside_address_and_port (nat44_ei_address_t *addresses, continue; a = addresses + address_index; - switch (protocol) - { -#define _(N, j, n, s) \ - case NAT_PROTOCOL_##N: \ - if (nat44_ei_port_is_used (a, NAT_PROTOCOL_##N, port_host_byte_order)) \ - return VNET_API_ERROR_INSTANCE_IN_USE; \ - nat44_ei_port_get (a, NAT_PROTOCOL_##N, port_host_byte_order); \ - a->busy_##n##_ports_per_thread[thread_index]++; \ - a->busy_##n##_ports++; \ - return 0; - foreach_nat_protocol -#undef _ - default : nat_elog_info (nm, "unknown protocol"); - return 1; - } + if (nat44_ei_port_is_used (a, protocol, port_host_byte_order)) + return VNET_API_ERROR_INSTANCE_IN_USE; + + nat44_ei_port_get (a, protocol, port_host_byte_order); + a->busy_ports_per_thread[protocol][thread_index]++; + a->busy_ports[protocol]++; + return 0; } return VNET_API_ERROR_NO_SUCH_ENTRY; @@ -1364,7 +1314,6 @@ nat44_ei_free_outside_address_and_port (nat44_ei_address_t *addresses, u32 thread_index, ip4_address_t *addr, u16 port, nat_protocol_t protocol) { - nat44_ei_main_t *nm = &nat44_ei_main; nat44_ei_address_t *a; u32 address_index; u16 port_host_byte_order = clib_net_to_host_u16 (port); @@ -1378,22 +1327,9 @@ nat44_ei_free_outside_address_and_port (nat44_ei_address_t *addresses, ASSERT (address_index < vec_len (addresses)); a = addresses + address_index; - - switch (protocol) - { -#define _(N, i, n, s) \ - case NAT_PROTOCOL_##N: \ - ASSERT ( \ - nat44_ei_port_is_used (a, NAT_PROTOCOL_##N, port_host_byte_order)); \ - nat44_ei_port_put (a, NAT_PROTOCOL_##N, port_host_byte_order); \ - a->busy_##n##_ports--; \ - a->busy_##n##_ports_per_thread[thread_index]--; \ - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (nm, "unknown protocol"); - return; - } + nat44_ei_port_put (a, protocol, port_host_byte_order); + a->busy_ports[protocol]--; + a->busy_ports_per_thread[protocol][thread_index]--; } void @@ -1858,75 +1794,95 @@ nat44_ei_alloc_default_cb (nat44_ei_address_t *addresses, u32 fib_index, if (vec_len (addresses) > 0) { - int s_addr_offset = s_addr.as_u32 % vec_len (addresses); for (i = s_addr_offset; i < vec_len (addresses); ++i) { a = addresses + i; - switch (proto) + + if (a->busy_ports_per_thread[proto][thread_index] < port_per_thread) { -#define _(N, j, n, s) \ - case NAT_PROTOCOL_##N: \ - if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \ - { \ - if (a->fib_index == fib_index) \ - { \ - while (1) \ - { \ - portnum = (port_per_thread * snat_thread_index) + \ - nat_random_port (&nm->random_seed, 0, \ - port_per_thread - 1) + \ - 1024; \ - if (nat44_ei_port_is_used (a, NAT_PROTOCOL_##N, portnum)) \ - continue; \ - nat44_ei_port_get (a, NAT_PROTOCOL_##N, portnum); \ - a->busy_##n##_ports_per_thread[thread_index]++; \ - a->busy_##n##_ports++; \ - *addr = a->addr; \ - *port = clib_host_to_net_u16 (portnum); \ - return 0; \ - } \ - } \ - else if (a->fib_index == ~0) \ - { \ - ga = a; \ - } \ - } \ - break; - foreach_nat_protocol; - default: - nat_elog_info (nm, "unknown protocol"); - return 1; + if (a->fib_index == fib_index) + { + while (1) + { + portnum = (port_per_thread * snat_thread_index) + + nat_random_port (&nm->random_seed, 0, + port_per_thread - 1) + + 1024; + if (nat44_ei_port_is_used (a, proto, portnum)) + continue; + nat44_ei_port_get (a, proto, portnum); + a->busy_ports_per_thread[proto][thread_index]++; + a->busy_ports[proto]++; + *addr = a->addr; + *port = clib_host_to_net_u16 (portnum); + return 0; + } + } + else if (a->fib_index == ~0) + { + ga = a; + } } } for (i = 0; i < s_addr_offset; ++i) { a = addresses + i; - switch (proto) + if (a->busy_ports_per_thread[proto][thread_index] < port_per_thread) { - foreach_nat_protocol; - default: - nat_elog_info (nm, "unknown protocol"); - return 1; + if (a->fib_index == fib_index) + { + while (1) + { + portnum = (port_per_thread * snat_thread_index) + + nat_random_port (&nm->random_seed, 0, + port_per_thread - 1) + + 1024; + if (nat44_ei_port_is_used (a, proto, portnum)) + continue; + nat44_ei_port_get (a, proto, portnum); + a->busy_ports_per_thread[proto][thread_index]++; + a->busy_ports[proto]++; + *addr = a->addr; + *port = clib_host_to_net_u16 (portnum); + return 0; + } + } + else if (a->fib_index == ~0) + { + ga = a; + } } } - if (ga) - { - a = ga; - // fake fib index to reuse macro - fib_index = ~0; - switch (proto) + + if (ga) { - foreach_nat_protocol; - default : nat_elog_info (nm, "unknown protocol"); - return 1; + a = ga; + if (a->busy_ports_per_thread[proto][thread_index] < port_per_thread) + { + if (a->fib_index == ~0) + { + while (1) + { + portnum = (port_per_thread * snat_thread_index) + + nat_random_port (&nm->random_seed, 0, + port_per_thread - 1) + + 1024; + if (nat44_ei_port_is_used (a, proto, portnum)) + continue; + nat44_ei_port_get (a, proto, portnum); + a->busy_ports_per_thread[proto][thread_index]++; + a->busy_ports[proto]++; + *addr = a->addr; + *port = clib_host_to_net_u16 (portnum); + return 0; + } + } + } } } - } - -#undef _ /* Totally out of translations to use... */ nat_ipfix_logging_addresses_exhausted (thread_index, 0); @@ -1948,30 +1904,20 @@ nat44_ei_alloc_range_cb (nat44_ei_address_t *addresses, u32 fib_index, if (!vec_len (addresses)) goto exhausted; - switch (proto) - { -#define _(N, i, n, s) \ - case NAT_PROTOCOL_##N: \ - if (a->busy_##n##_ports < ports) \ - { \ - while (1) \ - { \ - portnum = nat_random_port (&nm->random_seed, nm->start_port, \ - nm->end_port); \ - if (nat44_ei_port_is_used (a, NAT_PROTOCOL_##N, portnum)) \ - continue; \ - nat44_ei_port_get (a, NAT_PROTOCOL_##N, portnum); \ - a->busy_##n##_ports++; \ - *addr = a->addr; \ - *port = clib_host_to_net_u16 (portnum); \ - return 0; \ - } \ - } \ - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (nm, "unknown protocol"); - return 1; + if (a->busy_ports[proto] < ports) + { + while (1) + { + portnum = + nat_random_port (&nm->random_seed, nm->start_port, nm->end_port); + if (nat44_ei_port_is_used (a, proto, portnum)) + continue; + nat44_ei_port_get (a, proto, portnum); + a->busy_ports[proto]++; + *addr = a->addr; + *port = clib_host_to_net_u16 (portnum); + return 0; + } } exhausted: @@ -1995,32 +1941,22 @@ nat44_ei_alloc_mape_cb (nat44_ei_address_t *addresses, u32 fib_index, if (!vec_len (addresses)) goto exhausted; - switch (proto) - { -#define _(N, i, n, s) \ - case NAT_PROTOCOL_##N: \ - if (a->busy_##n##_ports < ports) \ - { \ - while (1) \ - { \ - A = nat_random_port (&nm->random_seed, 1, \ - pow2_mask (nm->psid_offset)); \ - j = nat_random_port (&nm->random_seed, 0, pow2_mask (m)); \ - portnum = A | (nm->psid << nm->psid_offset) | (j << (16 - m)); \ - if (nat44_ei_port_is_used (a, NAT_PROTOCOL_##N, portnum)) \ - continue; \ - nat44_ei_port_get (a, NAT_PROTOCOL_##N, portnum); \ - a->busy_##n##_ports++; \ - *addr = a->addr; \ - *port = clib_host_to_net_u16 (portnum); \ - return 0; \ - } \ - } \ - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (nm, "unknown protocol"); - return 1; + if (a->busy_ports[proto] < ports) + { + while (1) + { + A = + nat_random_port (&nm->random_seed, 1, pow2_mask (nm->psid_offset)); + j = nat_random_port (&nm->random_seed, 0, pow2_mask (m)); + portnum = A | (nm->psid << nm->psid_offset) | (j << (16 - m)); + if (nat44_ei_port_is_used (a, proto, portnum)) + continue; + nat44_ei_port_get (a, proto, portnum); + a->busy_ports[proto]++; + *addr = a->addr; + *port = clib_host_to_net_u16 (portnum); + return 0; + } } exhausted: @@ -2171,29 +2107,18 @@ nat44_ei_reserve_port (ip4_address_t addr, u16 port, nat_protocol_t proto) if (a->addr.as_u32 != addr.as_u32) continue; - switch (proto) - { -#define _(N, j, n, s) \ - case NAT_PROTOCOL_##N: \ - if (nat44_ei_port_is_used (a, NAT_PROTOCOL_##N, port)) \ - continue; \ - nat44_ei_port_get (a, NAT_PROTOCOL_##N, port); \ - if (port > 1024) \ - { \ - a->busy_##n##_ports++; \ - a->busy_##n##_ports_per_thread[ti]++; \ - } \ - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (nm, "unknown protocol"); - goto done; - } + if (nat44_ei_port_is_used (a, proto, port)) + continue; + nat44_ei_port_get (a, proto, port); + if (port > 1024) + { + a->busy_ports[proto]++; + a->busy_ports_per_thread[proto][ti]++; + } return 0; } -done: return 1; } @@ -2212,27 +2137,15 @@ nat44_ei_free_port (ip4_address_t addr, u16 port, nat_protocol_t proto) if (a->addr.as_u32 != addr.as_u32) continue; - switch (proto) - { -#define _(N, j, n, s) \ - case NAT_PROTOCOL_##N: \ - nat44_ei_port_put (a, NAT_PROTOCOL_##N, port); \ - if (port > 1024) \ - { \ - a->busy_##n##_ports--; \ - a->busy_##n##_ports_per_thread[ti]--; \ - } \ - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (nm, "unknown protocol"); - goto done; + nat44_ei_port_put (a, proto, port); + if (port > 1024) + { + a->busy_ports[proto]--; + a->busy_ports_per_thread[proto][ti]--; } - return 0; } -done: return 1; } @@ -3053,14 +2966,15 @@ nat44_ei_add_address (ip4_address_t *addr, u32 vrf_id) FIB_PROTOCOL_IP4, vrf_id, nm->fib_src_low); } -#define _(N, i, n, s) \ - ap->busy_##n##_port_bitmap = 0; \ - ap->busy_##n##_ports = 0; \ - ap->busy_##n##_ports_per_thread = 0; \ - vec_validate_init_empty (ap->busy_##n##_ports_per_thread, \ - tm->n_vlib_mains - 1, 0); - foreach_nat_protocol -#undef _ + nat_protocol_t proto; + for (proto = 0; proto < NAT_N_PROTOCOLS; ++proto) + { + ap->busy_port_bitmap[proto] = 0; + ap->busy_ports[proto] = 0; + ap->busy_ports_per_thread[proto] = 0; + vec_validate_init_empty (ap->busy_ports_per_thread[proto], + tm->n_vlib_mains - 1, 0); + } nat44_ei_add_del_addr_to_fib_foreach_out_if (addr, 1); @@ -3116,7 +3030,8 @@ nat44_ei_del_address (ip4_address_t addr, u8 delete_sm) } /* Delete sessions using address */ - if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports) + if (a->busy_ports[NAT_PROTOCOL_TCP] || a->busy_ports[NAT_PROTOCOL_UDP] || + a->busy_ports[NAT_PROTOCOL_ICMP]) { vec_foreach (tnm, nm->per_thread_data) { @@ -3145,11 +3060,13 @@ nat44_ei_del_address (ip4_address_t addr, u8 delete_sm) fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP4, nm->fib_src_low); } -#define _(N, i, n, s) vec_free (a->busy_##n##_ports_per_thread); - foreach_nat_protocol -#undef _ + nat_protocol_t proto; + for (proto = 0; proto < NAT_N_PROTOCOLS; ++proto) + { + vec_free (a->busy_ports_per_thread[proto]); + } - vec_del1 (nm->addresses, j); + vec_del1 (nm->addresses, j); return 0; } diff --git a/src/plugins/nat/nat44-ei/nat44_ei.h b/src/plugins/nat/nat44-ei/nat44_ei.h index c79cbfe5d57..b4aa0f26c0b 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei.h +++ b/src/plugins/nat/nat44-ei/nat44_ei.h @@ -71,12 +71,9 @@ typedef struct { ip4_address_t addr; u32 fib_index; -#define _(N, i, n, s) \ - u32 busy_##n##_ports; \ - u32 *busy_##n##_ports_per_thread; \ - uword *busy_##n##_port_bitmap; - foreach_nat_protocol -#undef _ + u32 busy_ports[NAT_N_PROTOCOLS]; + u32 *busy_ports_per_thread[NAT_N_PROTOCOLS]; + uword *busy_port_bitmap[NAT_N_PROTOCOLS]; } nat44_ei_address_t; clib_error_t *nat44_ei_api_hookup (vlib_main_t *vm); diff --git a/src/plugins/nat/nat44-ei/nat44_ei_cli.c b/src/plugins/nat/nat44-ei/nat44_ei_cli.c index 2fe01b07c9e..75c95179b40 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei_cli.c +++ b/src/plugins/nat/nat44-ei/nat44_ei_cli.c @@ -841,7 +841,7 @@ nat44_ei_show_addresses_command_fn (vlib_main_t *vm, unformat_input_t *input, else vlib_cli_output (vm, " tenant VRF independent"); #define _(N, i, n, s) \ - vlib_cli_output (vm, " %d busy %s ports", ap->busy_##n##_ports, s); + vlib_cli_output (vm, " %d busy %s ports", ap->busy_ports[i], s); foreach_nat_protocol #undef _ } -- cgit 1.2.3-korg