diff options
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/gbp/test/test_gbp.py | 39 | ||||
-rw-r--r-- | src/plugins/nat/nat.api | 43 | ||||
-rw-r--r-- | src/plugins/nat/nat.c | 887 | ||||
-rw-r--r-- | src/plugins/nat/nat.h | 86 | ||||
-rw-r--r-- | src/plugins/nat/nat44_cli.c | 133 | ||||
-rw-r--r-- | src/plugins/nat/nat_affinity.c | 25 | ||||
-rw-r--r-- | src/plugins/nat/nat_affinity.h | 10 | ||||
-rw-r--r-- | src/plugins/nat/nat_api.c | 84 | ||||
-rw-r--r-- | src/plugins/nat/nat_ha.c | 38 | ||||
-rw-r--r-- | src/plugins/nat/nat_ha.h | 9 | ||||
-rw-r--r-- | src/plugins/nat/test/test_nat.py | 231 |
11 files changed, 1008 insertions, 577 deletions
diff --git a/src/plugins/gbp/test/test_gbp.py b/src/plugins/gbp/test/test_gbp.py index 5ff71f42aa2..df3c3ad54f0 100644 --- a/src/plugins/gbp/test/test_gbp.py +++ b/src/plugins/gbp/test/test_gbp.py @@ -576,9 +576,13 @@ class TestGBP(VppTestCase): """ GBP Test Case """ @property - def config_flags(self): + def nat_config_flags(self): return VppEnum.vl_api_nat_config_flags_t + @property + def nat44_config_flags(self): + return VppEnum.vl_api_nat44_config_flags_t + @classmethod def setUpClass(cls): super(TestGBP, cls).setUpClass() @@ -826,6 +830,8 @@ class TestGBP(VppTestCase): "10.0.2.1", "11.0.0.4", "2001:10:2::1", "3001::4")] + self.vapi.nat44_plugin_enable_disable(enable=1) + # # Config related to each of the EPGs # @@ -839,7 +845,7 @@ class TestGBP(VppTestCase): epg.bvi.set_mac(self.router_mac) # The BVIs are NAT inside interfaces - flags = self.config_flags.NAT_IS_INSIDE + flags = self.nat_config_flags.NAT_IS_INSIDE self.vapi.nat44_interface_add_del_feature( sw_if_index=epg.bvi.sw_if_index, flags=flags, is_add=1) @@ -902,7 +908,7 @@ class TestGBP(VppTestCase): for (ip, fip) in zip(ep.ips, ep.fips): # Add static mappings for each EP from the 10/8 to 11/8 network if ip_address(ip).version == 4: - flags = self.config_flags.NAT_IS_ADDR_ONLY + flags = self.nat_config_flags.NAT_IS_ADDR_ONLY self.vapi.nat44_add_del_static_mapping( is_add=1, local_ip_address=ip, @@ -1468,16 +1474,11 @@ class TestGBP(VppTestCase): # # cleanup # + self.vapi.nat44_plugin_enable_disable(enable=0) + for ep in eps: # del static mappings for each EP from the 10/8 to 11/8 network - flags = self.config_flags.NAT_IS_ADDR_ONLY - self.vapi.nat44_add_del_static_mapping( - is_add=0, - local_ip_address=ep.ip4, - external_ip_address=ep.fip4, - external_sw_if_index=0xFFFFFFFF, - vrf_id=0, - flags=flags) + flags = self.nat_config_flags.NAT_IS_ADDR_ONLY self.vapi.nat66_add_del_static_mapping( local_ip_address=ep.ip6, external_ip_address=ep.fip6, @@ -1486,22 +1487,14 @@ class TestGBP(VppTestCase): for epg in epgs: # IP config on the BVI interfaces if epg != epgs[0] and epg != epgs[3]: - flags = self.config_flags.NAT_IS_INSIDE - self.vapi.nat44_interface_add_del_feature( - sw_if_index=epg.bvi.sw_if_index, - flags=flags, - is_add=0) + flags = self.nat_config_flags.NAT_IS_INSIDE self.vapi.nat66_add_del_interface( - is_add=0, flags=flags, - sw_if_index=epg.bvi.sw_if_index) + sw_if_index=epg.bvi.sw_if_index, + flags=flags, is_add=0) for recirc in recircs: - self.vapi.nat44_interface_add_del_feature( - sw_if_index=recirc.recirc.sw_if_index, - is_add=0) self.vapi.nat66_add_del_interface( - is_add=0, - sw_if_index=recirc.recirc.sw_if_index) + sw_if_index=recirc.recirc.sw_if_index, is_add=0) def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None, tep=None, n_tries=100, s_time=1): diff --git a/src/plugins/nat/nat.api b/src/plugins/nat/nat.api index 09c4d4a10b7..753cfdfc9be 100644 --- a/src/plugins/nat/nat.api +++ b/src/plugins/nat/nat.api @@ -30,6 +30,49 @@ import "plugins/nat/nat_types.api"; * Common NAT plugin APIs */ +enum nat44_config_flags : u8 +{ + NAT44_IS_ENDPOINT_INDEPENDENT = 0x00, + NAT44_IS_ENDPOINT_DEPENDENT = 0x01, + NAT44_IS_STATIC_MAPPING_ONLY = 0x02, + NAT44_IS_CONNECTION_TRACKING = 0x04, + NAT44_IS_OUT2IN_DPO = 0x08, +}; + +/** \brief Enable/disable NAT44 plugin + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param inside_vrf - inside vrf id + @param outside_vrf - outside vrf id + @param users - maximum number of users per thread + (NAT44_IS_ENDPOINT_INDEPENDENT) + @param user_memory - overwrite hash allocation parameter + (NAT44_IS_ENDPOINT_INDEPENDENT) + @param sessions - maximum number of sessions per thread + @param session_memory - overwrite hash allocation parameter + @param user_sessions - maximum number of sessions per user + (NAT44_IS_ENDPOINT_INDEPENDENT) + @param enable - true if enable, false if disable + @param flags - flag NAT44_IS_ENDPOINT_INDEPENDENT, + NAT44_IS_ENDPOINT_DEPENDENT, + NAT44_IS_STATIC_MAPPING_ONLY, + NAT44_IS_CONNECTION_TRACKING, + NAT44_IS_OUT2IN_DPO +*/ +autoreply define nat44_plugin_enable_disable { + u32 client_index; + u32 context; + u32 inside_vrf; + u32 outside_vrf; + u32 users; + u32 user_memory; + u32 sessions; + u32 session_memory; + u32 user_sessions; + bool enable; + vl_api_nat44_config_flags_t flags; +}; + /** \brief Control ping from client to api server request @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index b5195502719..232c26addf1 100644 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -181,6 +181,70 @@ VLIB_PLUGIN_REGISTER () = { }; /* *INDENT-ON* */ +static u32 +nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip, + u32 rx_fib_index, u8 is_output); + +static u32 +nat44_ed_get_worker_in2out_cb (ip4_header_t * ip, u32 rx_fib_index, + u8 is_output); + +static u32 +snat_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip0, + u32 rx_fib_index0, u8 is_output); + +static u32 +snat_get_worker_in2out_cb (ip4_header_t * ip0, u32 rx_fib_index0, + u8 is_output); + +static u32 nat_calc_bihash_buckets (u32 n_elts); + +static u32 nat_calc_bihash_memory (u32 n_buckets, uword kv_size); + +u8 *format_static_mapping_kvp (u8 * s, va_list * args); + +u8 *format_ed_session_kvp (u8 * s, va_list * args); + +void +nat_ha_sadd_cb (ip4_address_t * in_addr, u16 in_port, + ip4_address_t * out_addr, u16 out_port, + ip4_address_t * eh_addr, u16 eh_port, + ip4_address_t * ehn_addr, u16 ehn_port, u8 proto, + u32 fib_index, u16 flags, u32 thread_index); + +void +nat_ha_sdel_cb (ip4_address_t * out_addr, u16 out_port, + ip4_address_t * eh_addr, u16 eh_port, u8 proto, u32 fib_index, + u32 ti); + +void +nat_ha_sref_cb (ip4_address_t * out_addr, u16 out_port, + ip4_address_t * eh_addr, u16 eh_port, u8 proto, u32 fib_index, + u32 total_pkts, u64 total_bytes, u32 thread_index); + +void +nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port, + ip4_address_t * out_addr, u16 out_port, + ip4_address_t * eh_addr, u16 eh_port, + ip4_address_t * ehn_addr, u16 ehn_port, u8 proto, + u32 fib_index, u16 flags, u32 thread_index); + +void +nat_ha_sdel_ed_cb (ip4_address_t * out_addr, u16 out_port, + ip4_address_t * eh_addr, u16 eh_port, u8 proto, + u32 fib_index, u32 ti); + +void +nat_ha_sdel_ed_cb (ip4_address_t * out_addr, u16 out_port, + ip4_address_t * eh_addr, u16 eh_port, u8 proto, + u32 fib_index, u32 ti); + +void +nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port, + ip4_address_t * eh_addr, u16 eh_port, u8 proto, + u32 fib_index, u32 total_pkts, u64 total_bytes, + u32 thread_index); + void nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index, u8 is_ha) @@ -613,14 +677,20 @@ snat_add_address (snat_main_t * sm, ip4_address_t * addr, u32 vrf_id, vlib_thread_main_t *tm = vlib_get_thread_main (); if (twice_nat && !sm->endpoint_dependent) - return VNET_API_ERROR_FEATURE_DISABLED; + { + nat_log_err ("unsupported"); + return VNET_API_ERROR_UNSUPPORTED; + } /* Check if address already exists */ /* *INDENT-OFF* */ vec_foreach (ap, twice_nat ? sm->twice_nat_addresses : sm->addresses) { if (ap->addr.as_u32 == addr->as_u32) - return VNET_API_ERROR_VALUE_EXIST; + { + nat_log_err ("address exist"); + return VNET_API_ERROR_VALUE_EXIST; + } } /* *INDENT-ON* */ @@ -636,14 +706,18 @@ snat_add_address (snat_main_t * sm, ip4_address_t * addr, u32 vrf_id, nat_fib_src_low); else ap->fib_index = ~0; -#define _(N, i, n, s) \ - clib_memset(ap->busy_##n##_port_refcounts, 0, sizeof(ap->busy_##n##_port_refcounts));\ - 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 _ - if (twice_nat) + + /* *INDENT-OFF* */ + #define _(N, i, n, s) \ + clib_memset(ap->busy_##n##_port_refcounts, 0, sizeof(ap->busy_##n##_port_refcounts));\ + 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 _ + /* *INDENT-ON* */ + + if (twice_nat) return 0; /* Add external address to FIB */ @@ -1686,7 +1760,10 @@ snat_del_address (snat_main_t * sm, ip4_address_t addr, u8 delete_sm, } } if (!a) - return VNET_API_ERROR_NO_SUCH_ENTRY; + { + nat_log_err ("no such address"); + return VNET_API_ERROR_NO_SUCH_ENTRY; + } if (delete_sm) { @@ -1713,7 +1790,7 @@ snat_del_address (snat_main_t * sm, ip4_address_t addr, u8 delete_sm, /* Check if address is used in some static mapping */ if (is_snat_address_used_in_static_mapping (sm, addr)) { - nat_elog_notice ("address used in static mapping"); + nat_log_err ("address used in static mapping"); return VNET_API_ERROR_UNSPECIFIED; } } @@ -1894,14 +1971,26 @@ snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del) u32 fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index); + if (!sm->enabled) + { + nat_log_err ("nat44 is disabled"); + return VNET_API_ERROR_UNSUPPORTED; + } + if (sm->out2in_dpo && !is_inside) - return VNET_API_ERROR_UNSUPPORTED; + { + nat_log_err ("error unsupported"); + return VNET_API_ERROR_UNSUPPORTED; + } /* *INDENT-OFF* */ pool_foreach (i, sm->output_feature_interfaces, ({ if (i->sw_if_index == sw_if_index) - return VNET_API_ERROR_VALUE_EXIST; + { + nat_log_err ("error interface already configured"); + return VNET_API_ERROR_VALUE_EXIST; + } })); /* *INDENT-ON* */ @@ -2082,7 +2171,10 @@ feature_set: /* *INDENT-ON* */ if (is_del) - return VNET_API_ERROR_NO_SUCH_ENTRY; + { + nat_log_err ("error interface couldn't be found"); + return VNET_API_ERROR_NO_SUCH_ENTRY; + } pool_get (sm->interfaces, i); i->sw_if_index = sw_if_index; @@ -2145,14 +2237,26 @@ snat_interface_add_del_output_feature (u32 sw_if_index, u32 fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index); + if (!sm->enabled) + { + nat_log_err ("nat44 is disabled"); + return VNET_API_ERROR_UNSUPPORTED; + } + if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking)) - return VNET_API_ERROR_UNSUPPORTED; + { + nat_log_err ("error unsupported"); + return VNET_API_ERROR_UNSUPPORTED; + } /* *INDENT-OFF* */ pool_foreach (i, sm->interfaces, ({ if (i->sw_if_index == sw_if_index) - return VNET_API_ERROR_VALUE_EXIST; + { + nat_log_err ("error interface already configured"); + return VNET_API_ERROR_VALUE_EXIST; + } })); /* *INDENT-ON* */ @@ -2301,7 +2405,10 @@ fq: /* *INDENT-ON* */ if (is_del) - return VNET_API_ERROR_NO_SUCH_ENTRY; + { + nat_log_err ("error interface couldn't be found"); + return VNET_API_ERROR_NO_SUCH_ENTRY; + } pool_get (sm->output_feature_interfaces, i); i->sw_if_index = sw_if_index; @@ -2362,7 +2469,8 @@ snat_set_workers (uword * bitmap) } static void -snat_update_outside_fib (u32 sw_if_index, u32 new_fib_index, +snat_update_outside_fib (ip4_main_t * im, uword opaque, + u32 sw_if_index, u32 new_fib_index, u32 old_fib_index) { snat_main_t *sm = &snat_main; @@ -2371,11 +2479,11 @@ snat_update_outside_fib (u32 sw_if_index, u32 new_fib_index, u8 is_add = 1; u8 match = 0; - if (new_fib_index == old_fib_index) - return; - - if (!vec_len (sm->outside_fibs)) - return; + if (!sm->enabled || (new_fib_index == old_fib_index) + || (!vec_len (sm->outside_fibs))) + { + return; + } /* *INDENT-OFF* */ pool_foreach (i, sm->interfaces, @@ -2432,12 +2540,9 @@ snat_update_outside_fib (u32 sw_if_index, u32 new_fib_index, } static void -snat_ip4_table_bind (ip4_main_t * im, - uword opaque, - u32 sw_if_index, u32 new_fib_index, u32 old_fib_index) -{ - snat_update_outside_fib (sw_if_index, new_fib_index, old_fib_index); -} +snat_update_outside_fib (ip4_main_t * im, uword opaque, + u32 sw_if_index, u32 new_fib_index, + u32 old_fib_index); static void snat_ip4_add_del_interface_address_cb (ip4_main_t * im, @@ -2535,81 +2640,47 @@ nat_ip_table_add_del (vnet_main_t * vnm, u32 table_id, u32 is_add) VNET_IP_TABLE_ADD_DEL_FUNCTION (nat_ip_table_add_del); - -static clib_error_t * -snat_init (vlib_main_t * vm) +void +nat44_set_node_indexes (snat_main_t * sm, vlib_main_t * vm) { - snat_main_t *sm = &snat_main; - clib_error_t *error = 0; - ip4_main_t *im = &ip4_main; - ip_lookup_main_t *lm = &im->lookup_main; - uword *p; - vlib_thread_registration_t *tr; - vlib_thread_main_t *tm = vlib_get_thread_main (); - uword *bitmap = 0; - u32 i; - ip4_add_del_interface_address_callback_t cb4; vlib_node_t *node; - sm->vnet_main = vnet_get_main (); - sm->ip4_main = im; - sm->ip4_lookup_main = lm; - sm->api_main = vlibapi_get_main (); - sm->first_worker_index = 0; - sm->num_workers = 0; - sm->workers = 0; - sm->port_per_thread = 0xffff - 1024; - sm->fq_in2out_index = ~0; - sm->fq_in2out_output_index = ~0; - sm->fq_out2in_index = ~0; + node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in"); + sm->ei_out2in_node_index = node->index; + node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out"); + sm->ei_in2out_node_index = node->index; + node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output"); + sm->ei_in2out_output_node_index = node->index; - sm->alloc_addr_and_port = nat_alloc_addr_and_port_default; - sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT; - sm->forwarding_enabled = 0; - sm->log_class = vlib_log_register_class ("nat", 0); - sm->log_level = SNAT_LOG_ERROR; - sm->mss_clamping = 0; + node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in"); + sm->ed_out2in_node_index = node->index; + node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out"); + sm->ed_in2out_node_index = node->index; + node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-output"); + sm->ed_in2out_output_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "error-drop"); sm->error_node_index = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-in2out"); sm->pre_in2out_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-out2in"); sm->pre_out2in_node_index = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-in2out"); sm->pre_in2out_node_index = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-out2in"); sm->pre_out2in_node_index = node->index; - - node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out"); - sm->in2out_node_index = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output"); - sm->in2out_output_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-fast"); sm->in2out_fast_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-slowpath"); sm->in2out_slowpath_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output-slowpath"); sm->in2out_slowpath_output_node_index = node->index; - - node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out"); - sm->ed_in2out_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-slowpath"); sm->ed_in2out_slowpath_node_index = node->index; - - node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in"); - sm->out2in_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in-fast"); sm->out2in_fast_node_index = node->index; - - node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in"); - sm->ed_out2in_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in-slowpath"); sm->ed_out2in_slowpath_node_index = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpinning"); sm->hairpinning_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpin-dst"); @@ -2622,63 +2693,55 @@ snat_init (vlib_main_t * vm) sm->ed_hairpin_dst_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpin-src"); sm->ed_hairpin_src_node_index = node->index; +} - p = hash_get_mem (tm->thread_registrations_by_name, "workers"); - if (p) - { - tr = (vlib_thread_registration_t *) p[0]; - if (tr) - { - sm->num_workers = tr->count; - sm->first_worker_index = tr->first_index; - } - } - - vec_validate (sm->per_thread_data, tm->n_vlib_mains - 1); - - /* Use all available workers by default */ - if (sm->num_workers > 1) - { - for (i = 0; i < sm->num_workers; i++) - bitmap = clib_bitmap_set (bitmap, i, 1); - snat_set_workers (bitmap); - clib_bitmap_free (bitmap); - } - else - { - sm->per_thread_data[0].snat_thread_index = 0; - } +#define nat_init_simple_counter(c, n, sn) \ +do \ + { \ + c.name = n; \ + c.stat_segment_name = sn; \ + vlib_validate_simple_counter (&c, 0); \ + vlib_zero_simple_counter (&c, 0); \ + } while (0); - error = snat_api_init (vm, sm); - if (error) - return error; +static clib_error_t * +nat_init (vlib_main_t * vm) +{ + snat_main_t *sm = &snat_main; + clib_error_t *error = 0; + vlib_thread_main_t *tm = vlib_get_thread_main (); + vlib_thread_registration_t *tr; + ip4_add_del_interface_address_callback_t cbi = { 0 }; + ip4_table_bind_callback_t cbt = { 0 }; + u32 i, num_threads = 0; + uword *p, *bitmap = 0; - /* Set up the interface address add/del callback */ - cb4.function = snat_ip4_add_del_interface_address_cb; - cb4.function_opaque = 0; + clib_memset (sm, 0, sizeof (*sm)); - vec_add1 (im->add_del_interface_address_callbacks, cb4); + // required + sm->vnet_main = vnet_get_main (); + // convenience + sm->ip4_main = &ip4_main; + sm->api_main = vlibapi_get_main (); + sm->ip4_lookup_main = &ip4_main.lookup_main; - cb4.function = nat_ip4_add_del_addr_only_sm_cb; - cb4.function_opaque = 0; + // frame queue indices used for handoff + sm->fq_out2in_index = ~0; + sm->fq_in2out_index = ~0; + sm->fq_in2out_output_index = ~0; - vec_add1 (im->add_del_interface_address_callbacks, cb4); + sm->log_level = SNAT_LOG_ERROR; - nat_dpo_module_init (); + nat44_set_node_indexes (sm, vm); + sm->log_class = vlib_log_register_class ("nat", 0); + nat_ipfix_logging_init (vm); - /* Init counters */ - sm->total_users.name = "total-users"; - sm->total_users.stat_segment_name = "/nat44/total-users"; - vlib_validate_simple_counter (&sm->total_users, 0); - vlib_zero_simple_counter (&sm->total_users, 0); - sm->total_sessions.name = "total-sessions"; - sm->total_sessions.stat_segment_name = "/nat44/total-sessions"; - vlib_validate_simple_counter (&sm->total_sessions, 0); - vlib_zero_simple_counter (&sm->total_sessions, 0); - sm->user_limit_reached.name = "user-limit-reached"; - sm->user_limit_reached.stat_segment_name = "/nat44/user-limit-reached"; - vlib_validate_simple_counter (&sm->user_limit_reached, 0); - vlib_zero_simple_counter (&sm->user_limit_reached, 0); + nat_init_simple_counter (sm->total_users, "total-users", + "/nat44/total-users"); + nat_init_simple_counter (sm->total_sessions, "total-sessions", + "/nat44/total-sessions"); + nat_init_simple_counter (sm->user_limit_reached, "user-limit-reached", + "/nat44/user-limit-reached"); #define _(x) \ sm->counters.fastpath.in2out.x.name = #x; \ @@ -2710,26 +2773,345 @@ snat_init (vlib_main_t * vm) sm->counters.hairpinning.name = "hairpinning"; sm->counters.hairpinning.stat_segment_name = "/nat44/hairpinning"; - /* Init IPFIX logging */ - nat_ipfix_logging_init (vm); + p = hash_get_mem (tm->thread_registrations_by_name, "workers"); + if (p) + { + tr = (vlib_thread_registration_t *) p[0]; + if (tr) + { + sm->num_workers = tr->count; + sm->first_worker_index = tr->first_index; + } + } + num_threads = tm->n_vlib_mains - 1; + sm->port_per_thread = 0xffff - 1024; + vec_validate (sm->per_thread_data, num_threads); - ip4_table_bind_callback_t cbt4 = { - .function = snat_ip4_table_bind, - }; - vec_add1 (ip4_main.table_bind_callbacks, cbt4); + /* Use all available workers by default */ + if (sm->num_workers > 1) + { - nat_fib_src_hi = fib_source_allocate ("nat-hi", - FIB_SOURCE_PRIORITY_HI, - FIB_SOURCE_BH_SIMPLE); - nat_fib_src_low = fib_source_allocate ("nat-low", - FIB_SOURCE_PRIORITY_LOW, - FIB_SOURCE_BH_SIMPLE); + for (i = 0; i < sm->num_workers; i++) + bitmap = clib_bitmap_set (bitmap, i, 1); + snat_set_workers (bitmap); + clib_bitmap_free (bitmap); + } + else + sm->per_thread_data[0].snat_thread_index = 0; + + /* callbacks to call when interface address changes. */ + cbi.function = snat_ip4_add_del_interface_address_cb; + vec_add1 (sm->ip4_main->add_del_interface_address_callbacks, cbi); + cbi.function = nat_ip4_add_del_addr_only_sm_cb; + vec_add1 (sm->ip4_main->add_del_interface_address_callbacks, cbi); + + /* callbacks to call when interface to table biding changes */ + cbt.function = snat_update_outside_fib; + vec_add1 (sm->ip4_main->table_bind_callbacks, cbt); + + // TODO: is it possible to move it into snat_main ? + nat_fib_src_low = + fib_source_allocate ("nat-low", FIB_SOURCE_PRIORITY_LOW, + FIB_SOURCE_BH_SIMPLE); + nat_fib_src_hi = + fib_source_allocate ("nat-hi", FIB_SOURCE_PRIORITY_HI, + FIB_SOURCE_BH_SIMPLE); + + /* used only by out2in-dpo feature */ + nat_dpo_module_init (); + + nat_affinity_init (vm); + nat_ha_init (vm, sm->num_workers, num_threads); test_key_calc_split (); + error = snat_api_init (vm, sm); return error; } -VLIB_INIT_FUNCTION (snat_init); +VLIB_INIT_FUNCTION (nat_init); + +int +nat44_plugin_enable (nat44_config_t c) +{ + snat_main_t *sm = &snat_main; + u32 static_mapping_buckets = 1024; + u32 static_mapping_memory_size = 64 << 20; + + if (sm->enabled) + { + nat_log_err ("nat44 is enabled"); + return 1; + } + + // c.static_mapping_only + c.connection_tracking + // - supported in NAT EI & NAT ED + // c.out2in_dpo, c.static_mapping_only + // - supported in NAT EI + + if (c.endpoint_dependent) + { + if ((c.static_mapping_only && !c.connection_tracking) || c.out2in_dpo) + { + nat_log_err ("unsupported combination of configuration"); + return 1; + } + if (c.users || c.user_sessions) + { + nat_log_err ("unsupported combination of configuration"); + return 1; + } + } + + // reset to defaults: + sm->alloc_addr_and_port = nat_alloc_addr_and_port_default; + sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT; + // + sm->udp_timeout = SNAT_UDP_TIMEOUT; + sm->icmp_timeout = SNAT_ICMP_TIMEOUT; + sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT; + sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT; + + // nat44 feature configuration + sm->endpoint_dependent = c.endpoint_dependent; + sm->static_mapping_only = c.static_mapping_only; + sm->static_mapping_connection_tracking = c.connection_tracking; + sm->forwarding_enabled = 0; + sm->mss_clamping = 0; + + if (!c.users) + { + c.users = 1024; + } + sm->max_users_per_thread = c.users; + sm->user_buckets = nat_calc_bihash_buckets (c.users); + + if (!c.user_memory) + { + c.user_memory = + nat_calc_bihash_memory (c.users, sizeof (clib_bihash_8_8_t)); + } + sm->user_memory_size = c.user_memory; + + if (!c.sessions) + { + // default value based on legacy setting of load factor 10 * default + // translation buckets 1024 + c.sessions = 10 * 1024; + } + sm->max_translations_per_thread = c.sessions; + sm->translation_buckets = nat_calc_bihash_buckets (c.sessions); + + if (!c.session_memory) + { + c.session_memory = + nat_calc_bihash_memory + (sm->translation_buckets, sizeof (clib_bihash_16_8_t)); + } + sm->translation_memory_size = c.session_memory; + vec_add1 (sm->max_translations_per_fib, sm->max_translations_per_thread); + sm->max_translations_per_user + = c.user_sessions ? c.user_sessions : sm->max_translations_per_thread; + + sm->outside_vrf_id = c.outside_vrf; + sm->outside_fib_index = + fib_table_find_or_create_and_lock + (FIB_PROTOCOL_IP4, c.outside_vrf, nat_fib_src_hi); + + sm->inside_vrf_id = c.inside_vrf; + sm->inside_fib_index = + fib_table_find_or_create_and_lock + (FIB_PROTOCOL_IP4, c.inside_vrf, nat_fib_src_hi); + + if (c.endpoint_dependent) + { + sm->worker_out2in_cb = nat44_ed_get_worker_out2in_cb; + sm->worker_in2out_cb = nat44_ed_get_worker_in2out_cb; + sm->out2in_node_index = sm->ed_out2in_node_index; + sm->in2out_node_index = sm->ed_in2out_node_index; + sm->in2out_output_node_index = sm->ed_in2out_output_node_index; + sm->icmp_match_out2in_cb = icmp_match_out2in_ed; + sm->icmp_match_in2out_cb = icmp_match_in2out_ed; + + clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed", + sm->translation_buckets, + sm->translation_memory_size); + clib_bihash_set_kvp_format_fn_16_8 (&sm->out2in_ed, + format_ed_session_kvp); + + + nat_affinity_enable (); + + nat_ha_enable (nat_ha_sadd_ed_cb, nat_ha_sdel_ed_cb, nat_ha_sref_ed_cb); + } + else + { + sm->worker_out2in_cb = snat_get_worker_out2in_cb; + sm->worker_in2out_cb = snat_get_worker_in2out_cb; + sm->out2in_node_index = sm->ei_out2in_node_index; + sm->in2out_node_index = sm->ei_in2out_node_index; + sm->in2out_output_node_index = sm->ei_in2out_output_node_index; + sm->icmp_match_out2in_cb = icmp_match_out2in_slow; + sm->icmp_match_in2out_cb = icmp_match_in2out_slow; + + nat_ha_enable (nat_ha_sadd_cb, nat_ha_sdel_cb, nat_ha_sref_cb); + } + + // c.static_mapping & c.connection_tracking require + // session database + if (!c.static_mapping_only + || (c.static_mapping_only && c.connection_tracking)) + { + snat_main_per_thread_data_t *tsm; + /* *INDENT-OFF* */ + vec_foreach (tsm, sm->per_thread_data) + { + nat44_db_init (tsm); + } + /* *INDENT-ON* */ + } + else + { + sm->icmp_match_in2out_cb = icmp_match_in2out_fast; + sm->icmp_match_out2in_cb = icmp_match_out2in_fast; + } + + clib_bihash_init_8_8 (&sm->static_mapping_by_local, + "static_mapping_by_local", static_mapping_buckets, + static_mapping_memory_size); + clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local, + format_static_mapping_kvp); + + clib_bihash_init_8_8 (&sm->static_mapping_by_external, + "static_mapping_by_external", + static_mapping_buckets, static_mapping_memory_size); + clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external, + format_static_mapping_kvp); + + // last: reset counters + vlib_zero_simple_counter (&sm->total_users, 0); + vlib_zero_simple_counter (&sm->total_sessions, 0); + vlib_zero_simple_counter (&sm->user_limit_reached, 0); + + sm->enabled = 1; + + + nat_log_err ("nat44 enable"); + + return 0; +} + +void +nat44_addresses_free (snat_address_t ** addresses) +{ + snat_address_t *ap; + /* *INDENT-OFF* */ + vec_foreach (ap, *addresses) + { + #define _(N, i, n, s) \ + vec_free (ap->busy_##n##_ports_per_thread); + foreach_nat_protocol + #undef _ + } + /* *INDENT-ON* */ + vec_free (*addresses); + *addresses = 0; +} + +int +nat44_plugin_disable () +{ + snat_main_t *sm = &snat_main; + snat_interface_t *i, *vec; + int error = 0; + + if (!sm->enabled) + { + nat_log_err ("nat44 is disabled"); + return 1; + } + + // first unregister all nodes from interfaces + vec = vec_dup (sm->interfaces); + /* *INDENT-OFF* */ + vec_foreach (i, vec) + { + if (nat_interface_is_inside(i)) + error = snat_interface_add_del (i->sw_if_index, 1, 1); + if (nat_interface_is_outside(i)) + error = snat_interface_add_del (i->sw_if_index, 0, 1); + + if (error) + { + nat_log_err ("error occurred while removing interface %u", + i->sw_if_index); + } + } + /* *INDENT-ON* */ + vec_free (vec); + sm->interfaces = 0; + + vec = vec_dup (sm->output_feature_interfaces); + /* *INDENT-OFF* */ + vec_foreach (i, vec) + { + if (nat_interface_is_inside(i)) + error = snat_interface_add_del_output_feature (i->sw_if_index, 1, 1); + if (nat_interface_is_outside(i)) + error = snat_interface_add_del_output_feature (i->sw_if_index, 0, 1); + + if (error) + { + nat_log_err ("error occurred while removing interface %u", + i->sw_if_index); + } + } + /* *INDENT-ON* */ + vec_free (vec); + sm->output_feature_interfaces = 0; + + vec_free (sm->max_translations_per_fib); + + if (sm->endpoint_dependent) + { + nat_affinity_disable (); + clib_bihash_free_16_8 (&sm->out2in_ed); + } + + clib_bihash_free_8_8 (&sm->static_mapping_by_local); + clib_bihash_free_8_8 (&sm->static_mapping_by_external); + + if (!sm->static_mapping_only || + (sm->static_mapping_only && sm->static_mapping_connection_tracking)) + { + snat_main_per_thread_data_t *tsm; + /* *INDENT-OFF* */ + vec_foreach (tsm, sm->per_thread_data) + { + nat44_db_free (tsm); + } + /* *INDENT-ON* */ + } + + pool_free (sm->static_mappings); + + nat44_addresses_free (&sm->addresses); + nat44_addresses_free (&sm->twice_nat_addresses); + + + vec_free (sm->to_resolve); + vec_free (sm->auto_add_sw_if_indices); + vec_free (sm->auto_add_sw_if_indices_twice_nat); + + sm->to_resolve = 0; + sm->auto_add_sw_if_indices = 0; + sm->auto_add_sw_if_indices_twice_nat = 0; + + sm->forwarding_enabled = 0; + + sm->enabled = 0; + + return 0; +} void snat_free_outside_address_and_port (snat_address_t * addresses, @@ -4017,7 +4399,8 @@ nat44_db_init (snat_main_per_thread_data_t * tsm) clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in, format_session_kvp); } - // TODO: resolve static mappings (put only to !ED) + // TODO: ED nat is not using these + // before removal large refactor required pool_alloc (tsm->list_pool, sm->max_translations_per_thread); clib_bihash_init_8_8 (&tsm->user_hash, "users", sm->user_buckets, sm->user_memory_size); @@ -4082,222 +4465,6 @@ nat44_sessions_clear () /* *INDENT-ON* */ } -static clib_error_t * -snat_config (vlib_main_t * vm, unformat_input_t * input) -{ - snat_main_t *sm = &snat_main; - snat_main_per_thread_data_t *tsm; - - u32 static_mapping_buckets = 1024; - uword static_mapping_memory_size = 64 << 20; - - u32 max_users_per_thread = 0; - u32 user_memory_size = 0; - u32 max_translations_per_thread = 0; - u32 translation_memory_size = 0; - - u32 max_translations_per_user = ~0; - - u32 outside_vrf_id = 0; - u32 outside_ip6_vrf_id = 0; - u32 inside_vrf_id = 0; - u8 static_mapping_only = 0; - u8 static_mapping_connection_tracking = 0; - - u32 udp_timeout = SNAT_UDP_TIMEOUT; - u32 icmp_timeout = SNAT_ICMP_TIMEOUT; - u32 tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT; - u32 tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT; - - sm->out2in_dpo = 0; - sm->endpoint_dependent = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat - (input, "max translations per thread %d", - &max_translations_per_thread)) - ; - else if (unformat (input, "udp timeout %d", &udp_timeout)) - ; - else if (unformat (input, "icmp timeout %d", &icmp_timeout)) - ; - else if (unformat (input, "tcp transitory timeout %d", - &tcp_transitory_timeout)); - else if (unformat (input, "tcp established timeout %d", - &tcp_established_timeout)); - else if (unformat (input, "translation hash memory %d", - &translation_memory_size)); - else - if (unformat - (input, "max users per thread %d", &max_users_per_thread)) - ; - else if (unformat (input, "user hash memory %d", &user_memory_size)) - ; - else if (unformat (input, "max translations per user %d", - &max_translations_per_user)) - ; - 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)) - ; - else if (unformat (input, "static mapping only")) - { - static_mapping_only = 1; - if (unformat (input, "connection tracking")) - static_mapping_connection_tracking = 1; - } - else if (unformat (input, "out2in dpo")) - sm->out2in_dpo = 1; - else if (unformat (input, "endpoint-dependent")) - sm->endpoint_dependent = 1; - else - return clib_error_return (0, "unknown input '%U'", - format_unformat_error, input); - } - - if (static_mapping_only && (sm->endpoint_dependent)) - return clib_error_return (0, - "static mapping only mode available only for simple nat"); - - if (sm->out2in_dpo && (sm->endpoint_dependent)) - return clib_error_return (0, - "out2in dpo mode available only for simple nat"); - if (sm->endpoint_dependent && max_users_per_thread > 0) - { - return clib_error_return (0, - "setting 'max users' in endpoint-dependent mode is not supported"); - } - - if (sm->endpoint_dependent && max_translations_per_user != ~0) - { - return clib_error_return (0, - "setting 'max translations per user' in endpoint-dependent mode is not supported"); - } - - /* optionally configurable timeouts for testing purposes */ - sm->udp_timeout = udp_timeout; - sm->tcp_transitory_timeout = tcp_transitory_timeout; - sm->tcp_established_timeout = tcp_established_timeout; - sm->icmp_timeout = icmp_timeout; - - if (0 == max_users_per_thread) - { - max_users_per_thread = 1024; - } - sm->max_users_per_thread = max_users_per_thread; - sm->user_buckets = nat_calc_bihash_buckets (sm->max_users_per_thread); - - if (0 == max_translations_per_thread) - { - // default value based on legacy setting of load factor 10 * default - // translation buckets 1024 - max_translations_per_thread = 10 * 1024; - } - sm->translation_memory_size_set = translation_memory_size != 0; - - sm->max_translations_per_thread = max_translations_per_thread; - sm->translation_buckets = - nat_calc_bihash_buckets (sm->max_translations_per_thread); - if (0 == translation_memory_size) - { - translation_memory_size = - nat_calc_bihash_memory (sm->translation_buckets, - sizeof (clib_bihash_16_8_t)); - } - sm->translation_memory_size = translation_memory_size; - if (0 == user_memory_size) - { - user_memory_size = - nat_calc_bihash_memory (sm->max_users_per_thread, - sizeof (clib_bihash_8_8_t)); - } - sm->user_memory_size = user_memory_size; - vec_add1 (sm->max_translations_per_fib, sm->max_translations_per_thread); - - sm->max_translations_per_user = max_translations_per_user == ~0 ? - sm->max_translations_per_thread : 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, - nat_fib_src_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, - nat_fib_src_hi); - sm->static_mapping_only = static_mapping_only; - sm->static_mapping_connection_tracking = static_mapping_connection_tracking; - - if (sm->endpoint_dependent) - { - sm->worker_in2out_cb = nat44_ed_get_worker_in2out_cb; - sm->worker_out2in_cb = nat44_ed_get_worker_out2in_cb; - - sm->in2out_node_index = nat44_ed_in2out_node.index; - sm->in2out_output_node_index = nat44_ed_in2out_output_node.index; - sm->out2in_node_index = nat44_ed_out2in_node.index; - - sm->icmp_match_in2out_cb = icmp_match_in2out_ed; - sm->icmp_match_out2in_cb = icmp_match_out2in_ed; - nat_affinity_init (vm); - nat_ha_init (vm, nat_ha_sadd_ed_cb, nat_ha_sdel_ed_cb, - nat_ha_sref_ed_cb); - clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed", - clib_max (1, sm->num_workers) * - sm->translation_buckets, - clib_max (1, sm->num_workers) * - sm->translation_memory_size); - clib_bihash_set_kvp_format_fn_16_8 (&sm->out2in_ed, - format_ed_session_kvp); - } - else - { - sm->worker_in2out_cb = snat_get_worker_in2out_cb; - sm->worker_out2in_cb = snat_get_worker_out2in_cb; - - sm->in2out_node_index = snat_in2out_node.index; - sm->in2out_output_node_index = snat_in2out_output_node.index; - sm->out2in_node_index = snat_out2in_node.index; - - sm->icmp_match_in2out_cb = icmp_match_in2out_slow; - sm->icmp_match_out2in_cb = icmp_match_out2in_slow; - nat_ha_init (vm, nat_ha_sadd_cb, nat_ha_sdel_cb, nat_ha_sref_cb); - } - if (!static_mapping_only || - (static_mapping_only && static_mapping_connection_tracking)) - { - /* *INDENT-OFF* */ - vec_foreach (tsm, sm->per_thread_data) - { - nat44_db_init (tsm); - } - /* *INDENT-ON* */ - } - else - { - sm->icmp_match_in2out_cb = icmp_match_in2out_fast; - sm->icmp_match_out2in_cb = icmp_match_out2in_fast; - } - clib_bihash_init_8_8 (&sm->static_mapping_by_local, - "static_mapping_by_local", static_mapping_buckets, - static_mapping_memory_size); - clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local, - format_static_mapping_kvp); - - clib_bihash_init_8_8 (&sm->static_mapping_by_external, - "static_mapping_by_external", - static_mapping_buckets, static_mapping_memory_size); - clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external, - format_static_mapping_kvp); - - return 0; -} - -VLIB_CONFIG_FUNCTION (snat_config, "nat"); - static void nat_ip4_add_del_addr_only_sm_cb (ip4_main_t * im, uword opaque, @@ -4313,6 +4480,9 @@ nat_ip4_add_del_addr_only_sm_cb (ip4_main_t * im, int i, rv; ip4_address_t l_addr; + if (!sm->enabled) + return; + for (i = 0; i < vec_len (sm->to_resolve); i++) { rp = sm->to_resolve + i; @@ -4379,6 +4549,9 @@ snat_ip4_add_del_interface_address_cb (ip4_main_t * im, u8 twice_nat = 0; snat_address_t *addresses = sm->addresses; + if (!sm->enabled) + return; + for (i = 0; i < vec_len (sm->auto_add_sw_if_indices); i++) { if (sw_if_index == sm->auto_add_sw_if_indices[i]) diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h index 123bea57a81..2d16507df7a 100644 --- a/src/plugins/nat/nat.h +++ b/src/plugins/nat/nat.h @@ -48,6 +48,44 @@ /* NAT buffer flags */ #define SNAT_FLAG_HAIRPINNING (1 << 0) +/* NAT44 API Configuration flags */ +#define foreach_nat44_config_flag \ + _(0x00, IS_ENDPOINT_INDEPENDENT) \ + _(0x01, IS_ENDPOINT_DEPENDENT) \ + _(0x02, IS_STATIC_MAPPING_ONLY) \ + _(0x04, IS_CONNECTION_TRACKING) \ + _(0x08, IS_OUT2IN_DPO) + +typedef enum nat44_config_flags_t_ +{ +#define _(n,f) NAT44_API_##f = n, + foreach_nat44_config_flag +#undef _ +} nat44_config_flags_t; + +typedef struct +{ + /* nat44 plugin features */ + u8 static_mapping_only; + u8 connection_tracking; + u8 endpoint_dependent; + u8 out2in_dpo; + + u32 inside_vrf; + u32 outside_vrf; + + /* maximum number of users */ + u32 users; + u32 user_memory; + + /* maximum number of sessions */ + u32 sessions; + u32 session_memory; + + /* maximum number of ssessions per user */ + u32 user_sessions; +} nat44_config_t; + typedef enum { NAT_NEXT_DROP, @@ -551,16 +589,24 @@ typedef struct snat_main_s u32 pre_out2in_node_index; u32 pre_in2out_node_index; + u32 out2in_node_index; u32 in2out_node_index; u32 in2out_output_node_index; + u32 in2out_fast_node_index; u32 in2out_slowpath_node_index; u32 in2out_slowpath_output_node_index; - u32 ed_in2out_node_index; - u32 ed_in2out_slowpath_node_index; - u32 out2in_node_index; u32 out2in_fast_node_index; + + u32 ei_out2in_node_index; + u32 ei_in2out_node_index; + u32 ei_in2out_output_node_index; + u32 ed_out2in_node_index; + u32 ed_in2out_node_index; + u32 ed_in2out_output_node_index; + + u32 ed_in2out_slowpath_node_index; u32 ed_out2in_slowpath_node_index; u32 hairpinning_node_index; @@ -574,10 +620,12 @@ typedef struct snat_main_s u8 forwarding_enabled; /* Config parameters */ + u8 endpoint_dependent; + + u8 out2in_dpo; + /* static mapping config */ u8 static_mapping_only; u8 static_mapping_connection_tracking; - u8 out2in_dpo; - u8 endpoint_dependent; /* Is translation memory size calculated or user defined */ u8 translation_memory_size_set; @@ -597,7 +645,6 @@ typedef struct snat_main_s u32 inside_fib_index; /* values of various timeouts */ - // proto timeouts u32 udp_timeout; u32 tcp_transitory_timeout; u32 tcp_established_timeout; @@ -606,7 +653,7 @@ typedef struct snat_main_s /* TCP MSS clamping */ u16 mss_clamping; - /* counters/gauges */ + /* counters */ vlib_simple_counter_main_t total_users; vlib_simple_counter_main_t total_sessions; vlib_simple_counter_main_t user_limit_reached; @@ -673,10 +720,14 @@ typedef struct snat_main_s u8 log_level; /* convenience */ - vnet_main_t *vnet_main; + api_main_t *api_main; ip4_main_t *ip4_main; ip_lookup_main_t *ip4_lookup_main; - api_main_t *api_main; + + /* nat44 plugin enabled */ + u8 enabled; + + vnet_main_t *vnet_main; } snat_main_t; typedef struct @@ -1087,6 +1138,23 @@ int nat44_o2i_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg); int nat44_i2o_is_idle_session_cb (clib_bihash_kv_8_8_t * kv, void *arg); int nat44_o2i_is_idle_session_cb (clib_bihash_kv_8_8_t * kv, void *arg); + +/** + * @brief Enable NAT44 plugin + * + * @param c nat44_config_t + * + * @return 0 on success, non-zero value otherwise + */ +int nat44_plugin_enable (nat44_config_t c); + +/** + * @brief Disable NAT44 plugin + * + * @return 0 on success, non-zero value otherwise + */ +int nat44_plugin_disable (); + /** * @brief Add external address to NAT44 pool * diff --git a/src/plugins/nat/nat44_cli.c b/src/plugins/nat/nat44_cli.c index 680a1e2a18a..a84c8204143 100644 --- a/src/plugins/nat/nat44_cli.c +++ b/src/plugins/nat/nat44_cli.c @@ -32,6 +32,97 @@ "This command is supported only in endpoint dependent mode" static clib_error_t * +nat44_enable_command_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + snat_main_t *sm = &snat_main; + unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = 0; + + nat44_config_t c = { 0 }; + u8 mode_set = 0; + + // TODO: check this also inside the function so it can be + // safely called from anyplace, also sanity checking required + if (sm->enabled) + return clib_error_return (0, "nat44 already enabled"); + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + { + if (nat44_plugin_enable (c) != 0) + return clib_error_return (0, "nat44 enable failed"); + return 0; + } + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (!mode_set && unformat (line_input, "static-mapping-only")) + { + mode_set = 1; + c.static_mapping_only = 1; + if (unformat (line_input, "connection-tracking")) + { + c.connection_tracking = 1; + } + } + else if (!mode_set && unformat (line_input, "out2in-dpo")) + { + mode_set = 1; + c.out2in_dpo = 1; + } + else if (!mode_set && unformat (line_input, "endpoint-dependent")) + { + mode_set = 1; + c.endpoint_dependent = 1; + } + else if (unformat (input, "inside-vrf %u", &c.inside_vrf)); + else if (unformat (input, "outside-vrf %u", &c.outside_vrf)); + else if (unformat (input, "users %u", &c.users)); + else if (unformat (input, "user-memory %u", &c.user_memory)); + else if (unformat (input, "sessions %u", &c.sessions)); + else if (unformat (input, "session-memory %u", &c.session_memory)); + else if (unformat (input, "user-sessions %u", &c.user_sessions)); + else + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } + } + + if (!(c.sessions && c.session_memory)) + { + error = + clib_error_return (0, + "either number of sessions or size of the memory is required"); + goto done; + } + + if (nat44_plugin_enable (c) != 0) + error = clib_error_return (0, "nat44 enable failed"); +done: + unformat_free (line_input); + return error; +} + +static clib_error_t * +nat44_disable_command_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + snat_main_t *sm = &snat_main; + clib_error_t *error = 0; + + if (sm->enabled) + return clib_error_return (0, "nat44 already disabled"); + + if (nat44_plugin_disable () != 0) + error = clib_error_return (0, "nat44 disable failed"); + + return error; +} + +static clib_error_t * set_workers_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { @@ -1891,6 +1982,48 @@ VLIB_CLI_COMMAND (nat44_debug_fib_registration_command, static) = { /*? * @cliexpar + * @cliexstart{nat44 enable} + * Enable nat44 plugin + * To enable nat44, use: + * vpp# nat44 enable sessions <n> + * To enable nat44 static mapping only, use: + * vpp# nat44 enable sessions <n> static-mapping + * To enable nat44 static mapping with connection tracking, use: + * vpp# nat44 enable sessions <n> static-mapping connection-tracking + * To enable nat44 out2in dpo, use: + * vpp# nat44 enable sessions <n> out2in-dpo + * To enable nat44 endpoint-dependent, use: + * vpp# nat44 enable sessions <n> endpoint-dependent + * To overwrite user hash configuration, use: + * vpp# nat44 enable sessions <n> user-memory <n> + * To overwrite session hash configuration, use: + * vpp# nat44 enable session-memory <n> + * To set inside-vrf outside-vrf, use: + * vpp# nat44 enable sessions <n> inside-vrf <id> outside-vrf <id> + * @cliexend +?*/ +VLIB_CLI_COMMAND (nat44_enable_command, static) = { + .path = "nat44 enable", + .short_help = "nat44 enable sessions <max-number> [users <max-number>] [static-mappig-only [connection-tracking]|out2in-dpo|endpoint-dependent] [inside-vrf <vrf-id>] [outside-vrf <vrf-id>] [user-memory <number>] [session-memory <number>] [user-sessions <max-number>]", + .function = nat44_enable_command_fn, +}; + +/*? + * @cliexpar + * @cliexstart{nat44 disable} + * Disable nat44 plugin + * To disable nat44, use: + * vpp# nat44 disable + * @cliexend +?*/ +VLIB_CLI_COMMAND (nat44_disable_command, static) = { + .path = "nat44 disable", + .short_help = "nat44 disable", + .function = nat44_disable_command_fn, +}; + +/*? + * @cliexpar * @cliexstart{set snat workers} * Set NAT workers if 2 or more workers available, use: * vpp# set snat workers 0-2,5 diff --git a/src/plugins/nat/nat_affinity.c b/src/plugins/nat/nat_affinity.c index 2c22ae0e097..e7a7354c18d 100644 --- a/src/plugins/nat/nat_affinity.c +++ b/src/plugins/nat/nat_affinity.c @@ -43,24 +43,37 @@ format_affinity_kvp (u8 * s, va_list * args) return s; } -clib_error_t * -nat_affinity_init (vlib_main_t * vm) +void +nat_affinity_enable () { nat_affinity_main_t *nam = &nat_affinity_main; vlib_thread_main_t *tm = vlib_get_thread_main (); - clib_error_t *error = 0; if (tm->n_vlib_mains > 1) clib_spinlock_init (&nam->affinity_lock); - clib_bihash_init_16_8 (&nam->affinity_hash, "nat-affinity", AFFINITY_HASH_BUCKETS, AFFINITY_HASH_MEMORY); clib_bihash_set_kvp_format_fn_16_8 (&nam->affinity_hash, format_affinity_kvp); +} - nam->vlib_main = vm; +void +nat_affinity_disable () +{ + nat_affinity_main_t *nam = &nat_affinity_main; + vlib_thread_main_t *tm = vlib_get_thread_main (); - return error; + if (tm->n_vlib_mains > 1) + clib_spinlock_free (&nam->affinity_lock); + clib_bihash_free_16_8 (&nam->affinity_hash); +} + +clib_error_t * +nat_affinity_init (vlib_main_t * vm) +{ + nat_affinity_main_t *nam = &nat_affinity_main; + nam->vlib_main = vm; + return 0; } static_always_inline void diff --git a/src/plugins/nat/nat_affinity.h b/src/plugins/nat/nat_affinity.h index 358e682eb49..d6bda6a8ee1 100644 --- a/src/plugins/nat/nat_affinity.h +++ b/src/plugins/nat/nat_affinity.h @@ -79,6 +79,16 @@ u32 nat_affinity_get_per_service_list_head_index (void); void nat_affinity_flush_service (u32 affinity_per_service_list_head_index); /** + * @brief NAT affinity enable + */ +void nat_affinity_enable (); + +/** + * @brief NAT affinity disable + */ +void nat_affinity_disable (); + +/** * @brief Initialize NAT client-IP based affinity. * * @param vm vlib main. diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c index 11d4ded48a9..39f1af70f9d 100644 --- a/src/plugins/nat/nat_api.c +++ b/src/plugins/nat/nat_api.c @@ -334,6 +334,89 @@ vl_api_nat_set_log_level_t_print (vl_api_nat_set_log_level_t * } static void + vl_api_nat44_plugin_enable_disable_t_handler + (vl_api_nat44_plugin_enable_disable_t * mp) +{ + snat_main_t *sm = &snat_main; + nat44_config_t c = { 0 }; + vl_api_nat44_plugin_enable_disable_reply_t *rmp; + int rv = 0; + + if (mp->enable) + { + c.endpoint_dependent = mp->flags & NAT44_API_IS_ENDPOINT_DEPENDENT; + c.static_mapping_only = mp->flags & NAT44_API_IS_STATIC_MAPPING_ONLY; + c.connection_tracking = mp->flags & NAT44_API_IS_CONNECTION_TRACKING; + c.out2in_dpo = mp->flags & NAT44_API_IS_OUT2IN_DPO; + + c.inside_vrf = ntohl (mp->inside_vrf); + c.outside_vrf = ntohl (mp->outside_vrf); + + c.users = ntohl (mp->users); + c.user_memory = ntohl (mp->user_memory); + + c.sessions = ntohl (mp->sessions); + c.session_memory = ntohl (mp->session_memory); + + c.user_sessions = ntohl (mp->user_sessions); + + rv = nat44_plugin_enable (c); + } + else + rv = nat44_plugin_disable (); + + REPLY_MACRO (VL_API_NAT44_PLUGIN_ENABLE_DISABLE_REPLY); +} + +static void *vl_api_nat44_plugin_enable_disable_t_print + (vl_api_nat44_plugin_enable_disable_t * mp, void *handle) +{ + u8 *s; + u32 val; + + s = format (0, "SCRIPT: nat44_plugin_enable_disable "); + if (mp->enable) + { + s = format (s, "enable "); + if (mp->flags & NAT44_API_IS_ENDPOINT_DEPENDENT) + s = format (s, "endpoint-dependent "); + else + s = format (s, "endpoint-indepenednet "); + if (mp->flags & NAT44_API_IS_STATIC_MAPPING_ONLY) + s = format (s, "static_mapping_only "); + if (mp->flags & NAT44_API_IS_CONNECTION_TRACKING) + s = format (s, "connection_tracking "); + if (mp->flags & NAT44_API_IS_OUT2IN_DPO) + s = format (s, "out2in_dpo "); + val = ntohl (mp->inside_vrf); + if (val) + s = format (s, "inside_vrf %u ", val); + val = ntohl (mp->outside_vrf); + if (val) + s = format (s, "outside_vrf %u ", val); + val = ntohl (mp->users); + if (val) + s = format (s, "users %u ", val); + val = ntohl (mp->user_memory); + if (val) + s = format (s, "user_memory %u ", val); + val = ntohl (mp->sessions); + if (val) + s = format (s, "sessions %u ", val); + val = ntohl (mp->session_memory); + if (val) + s = format (s, "session_memory %u ", val); + val = ntohl (mp->user_sessions); + if (val) + s = format (s, "user_sessions %u ", val); + } + else + s = format (s, "disable "); + + FINISH; +} + +static void vl_api_nat_ipfix_enable_disable_t_handler (vl_api_nat_ipfix_enable_disable_t * mp) { @@ -2228,6 +2311,7 @@ _(NAT_SHOW_CONFIG, nat_show_config) \ _(NAT_SHOW_CONFIG_2, nat_show_config_2) \ _(NAT_SET_WORKERS, nat_set_workers) \ _(NAT_WORKER_DUMP, nat_worker_dump) \ +_(NAT44_PLUGIN_ENABLE_DISABLE, nat44_plugin_enable_disable) \ _(NAT44_DEL_USER, nat44_del_user) \ _(NAT44_SET_SESSION_LIMIT, nat44_set_session_limit) \ _(NAT_SET_LOG_LEVEL, nat_set_log_level) \ diff --git a/src/plugins/nat/nat_ha.c b/src/plugins/nat/nat_ha.c index ddfa3e49183..93f762f61ae 100644 --- a/src/plugins/nat/nat_ha.c +++ b/src/plugins/nat/nat_ha.c @@ -310,35 +310,27 @@ nat_ha_resend_scan (f64 now, u32 thread_index) } void -nat_ha_init (vlib_main_t * vm, nat_ha_sadd_cb_t sadd_cb, - nat_ha_sdel_cb_t sdel_cb, nat_ha_sref_cb_t sref_cb) +nat_ha_enable (nat_ha_sadd_cb_t sadd_cb, + nat_ha_sdel_cb_t sdel_cb, nat_ha_sref_cb_t sref_cb) { nat_ha_main_t *ha = &nat_ha_main; - vlib_thread_main_t *tm = vlib_get_thread_main (); - vlib_thread_registration_t *tr; - uword *p; - - ha->src_ip_address.as_u32 = 0; - ha->src_port = 0; - ha->dst_ip_address.as_u32 = 0; - ha->dst_port = 0; - ha->in_resync = 0; - ha->resync_ack_count = 0; - ha->resync_ack_missed = 0; - ha->vlib_main = vm; + ha->sadd_cb = sadd_cb; ha->sdel_cb = sdel_cb; ha->sref_cb = sref_cb; - ha->num_workers = 0; - vec_validate (ha->per_thread_data, tm->n_vlib_mains - 1); +} + +void +nat_ha_init (vlib_main_t * vm, u32 num_workers, u32 num_threads) +{ + nat_ha_main_t *ha = &nat_ha_main; + clib_memset (ha, 0, sizeof (*ha)); + + ha->vlib_main = vm; ha->fq_index = ~0; - p = hash_get_mem (tm->thread_registrations_by_name, "workers"); - if (p) - { - tr = (vlib_thread_registration_t *) p[0]; - if (tr) - ha->num_workers = tr->count; - } + + ha->num_workers = num_workers; + vec_validate (ha->per_thread_data, num_threads); #define _(N, s, v) ha->counters[v].name = s; \ ha->counters[v].stat_segment_name = "/nat44/ha/" s; \ diff --git a/src/plugins/nat/nat_ha.h b/src/plugins/nat/nat_ha.h index ec627899a3f..92fc3373673 100644 --- a/src/plugins/nat/nat_ha.h +++ b/src/plugins/nat/nat_ha.h @@ -39,10 +39,15 @@ typedef void (*nat_ha_sref_cb_t) (ip4_address_t * out_addr, u16 out_port, u64 total_bytes, u32 thread_index); /** + * @brief Enable NAT HA, set callbacks + */ +void nat_ha_enable (nat_ha_sadd_cb_t sadd_cb, nat_ha_sdel_cb_t sdel_cb, + nat_ha_sref_cb_t sref_cb); + +/** * @brief Initialize NAT HA */ -void nat_ha_init (vlib_main_t * vm, nat_ha_sadd_cb_t sadd_cb, - nat_ha_sdel_cb_t sdel_cb, nat_ha_sref_cb_t sref_cb); +void nat_ha_init (vlib_main_t * vm, u32 num_workers, u32 num_threads); /** * @brief Set HA listener (local settings) diff --git a/src/plugins/nat/test/test_nat.py b/src/plugins/nat/test/test_nat.py index a64f6c03617..3b19b71f199 100644 --- a/src/plugins/nat/test/test_nat.py +++ b/src/plugins/nat/test/test_nat.py @@ -76,103 +76,13 @@ class MethodHolder(VppTestCase): return VppEnum.vl_api_nat_config_flags_t @property + def nat44_config_flags(self): + return VppEnum.vl_api_nat44_config_flags_t + + @property def SYSLOG_SEVERITY(self): return VppEnum.vl_api_syslog_severity_t - def clear_nat44(self): - """ - Clear NAT44 configuration. - """ - if hasattr(self, 'pg7') and hasattr(self, 'pg8'): - if self.pg7.has_ip4_config: - self.pg7.unconfig_ip4() - - self.vapi.nat44_forwarding_enable_disable(enable=0) - - interfaces = self.vapi.nat44_interface_addr_dump() - for intf in interfaces: - self.vapi.nat44_add_del_interface_addr( - is_add=0, - sw_if_index=intf.sw_if_index, - flags=intf.flags) - - self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id, - src_port=self.ipfix_src_port, - enable=0) - self.ipfix_src_port = 4739 - self.ipfix_domain_id = 1 - - self.vapi.syslog_set_filter( - self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG) - - self.vapi.nat_ha_set_listener(ip_address='0.0.0.0', port=0, - path_mtu=512) - self.vapi.nat_ha_set_failover(ip_address='0.0.0.0', port=0, - session_refresh_interval=10) - - interfaces = self.vapi.nat44_interface_dump() - for intf in interfaces: - if intf.flags & self.config_flags.NAT_IS_INSIDE and \ - intf.flags & self.config_flags.NAT_IS_OUTSIDE: - self.vapi.nat44_interface_add_del_feature( - sw_if_index=intf.sw_if_index) - self.vapi.nat44_interface_add_del_feature( - sw_if_index=intf.sw_if_index, - flags=intf.flags) - - interfaces = self.vapi.nat44_interface_output_feature_dump() - for intf in interfaces: - self.vapi.nat44_interface_add_del_output_feature( - is_add=0, - flags=intf.flags, - sw_if_index=intf.sw_if_index) - static_mappings = self.vapi.nat44_static_mapping_dump() - for sm in static_mappings: - self.vapi.nat44_add_del_static_mapping( - is_add=0, - local_ip_address=sm.local_ip_address, - external_ip_address=sm.external_ip_address, - external_sw_if_index=sm.external_sw_if_index, - local_port=sm.local_port, - external_port=sm.external_port, - vrf_id=sm.vrf_id, - protocol=sm.protocol, - flags=sm.flags, tag=sm.tag) - - lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump() - for lb_sm in lb_static_mappings: - self.vapi.nat44_add_del_lb_static_mapping( - is_add=0, - flags=lb_sm.flags, - external_addr=lb_sm.external_addr, - external_port=lb_sm.external_port, - protocol=lb_sm.protocol, - local_num=0, locals=[], - tag=lb_sm.tag) - - identity_mappings = self.vapi.nat44_identity_mapping_dump() - for id_m in identity_mappings: - self.vapi.nat44_add_del_identity_mapping( - ip_address=id_m.ip_address, - sw_if_index=id_m.sw_if_index, - port=id_m.port, - flags=id_m.flags, - vrf_id=id_m.vrf_id, - protocol=id_m.protocol) - - addresses = self.vapi.nat44_address_dump() - for addr in addresses: - self.vapi.nat44_add_del_address_range( - first_ip_address=addr.ip_address, - last_ip_address=addr.ip_address, - vrf_id=0xFFFFFFFF, flags=addr.flags) - - self.verify_no_nat44_user() - self.vapi.nat_set_timeouts(udp=300, tcp_established=7440, - tcp_transitory=240, icmp=60) - self.vapi.nat_set_addr_and_port_alloc_alg() - self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500) - def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0', local_port=0, external_port=0, vrf_id=0, is_add=1, external_sw_if_index=0xFFFFFFFF, @@ -1256,19 +1166,17 @@ class TestNATMisc(MethodHolder): max_translations = 10240 max_users = 10240 - @classmethod - def setUpConstants(cls): - super(TestNATMisc, cls).setUpConstants() - cls.vpp_cmdline.extend([ - "nat", "{", - "max translations per thread %d" % cls.max_translations, - "max users per thread %d" % cls.max_users, - "}" - ]) + def setUp(self): + super(TestNATMisc, self).setUp() + self.vapi.nat44_plugin_enable_disable( + sessions=self.max_translations, + users=self.max_users, enable=1) - @classmethod - def tearDownClass(cls): - super(TestNATMisc, cls).tearDownClass() + def tearDown(self): + super(TestNATMisc, self).tearDown() + if not self.vpp_dead: + self.vapi.nat44_plugin_enable_disable(enable=0) + self.vapi.cli("clear logging") def test_show_config(self): """ NAT config translation memory """ @@ -1300,16 +1208,6 @@ class TestNAT44(MethodHolder): max_users = 10240 @classmethod - def setUpConstants(cls): - super(TestNAT44, cls).setUpConstants() - cls.vpp_cmdline.extend([ - "nat", "{", - "max translations per thread %d" % cls.max_translations, - "max users per thread %d" % cls.max_users, - "}" - ]) - - @classmethod def setUpClass(cls): super(TestNAT44, cls).setUpClass() cls.vapi.cli("set log class nat level debug") @@ -1373,10 +1271,28 @@ class TestNAT44(MethodHolder): cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2" cls.pg9.resolve_arp() + def setUp(self): + super(TestNAT44, self).setUp() + self.vapi.nat44_plugin_enable_disable( + sessions=self.max_translations, + users=self.max_users, enable=1) + @classmethod def tearDownClass(cls): super(TestNAT44, cls).tearDownClass() + def tearDown(self): + super(TestNAT44, self).tearDown() + if not self.vpp_dead: + self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id, + src_port=self.ipfix_src_port, + enable=0) + self.ipfix_src_port = 4739 + self.ipfix_domain_id = 1 + + self.vapi.nat44_plugin_enable_disable(enable=0) + self.vapi.cli("clear logging") + def test_clear_sessions(self): """ NAT44 session clearing test """ @@ -4094,11 +4010,6 @@ class TestNAT44(MethodHolder): self.assertEqual(tcp.sport, self.tcp_external_port) self.assertEqual(tcp.dport, self.tcp_port_in) - def tearDown(self): - super(TestNAT44, self).tearDown() - self.clear_nat44() - self.vapi.cli("clear logging") - def show_commands_at_teardown(self): self.logger.info(self.vapi.cli("show nat44 addresses")) self.logger.info(self.vapi.cli("show nat44 interfaces")) @@ -4116,11 +4027,6 @@ class TestNAT44EndpointDependent2(MethodHolder): """ Endpoint-Dependent mapping and filtering test cases """ @classmethod - def setUpConstants(cls): - super(TestNAT44EndpointDependent2, cls).setUpConstants() - cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"]) - - @classmethod def tearDownClass(cls): super(TestNAT44EndpointDependent2, cls).tearDownClass() @@ -4151,9 +4057,14 @@ class TestNAT44EndpointDependent2(MethodHolder): def setUp(self): super(TestNAT44EndpointDependent2, self).setUp() + flags = self.nat44_config_flags.NAT44_IS_ENDPOINT_DEPENDENT + self.vapi.nat44_plugin_enable_disable(enable=1, flags=flags) - nat_config = self.vapi.nat_show_config() - self.assertEqual(1, nat_config.endpoint_dependent) + def tearDown(self): + super(TestNAT44EndpointDependent2, self).tearDown() + if not self.vpp_dead: + self.vapi.nat44_plugin_enable_disable(enable=0) + self.vapi.cli("clear logging") def nat_add_inside_interface(self, i): self.vapi.nat44_interface_add_del_feature( @@ -4249,11 +4160,6 @@ class TestNAT44EndpointDependent(MethodHolder): """ Endpoint-Dependent mapping and filtering test cases """ @classmethod - def setUpConstants(cls): - super(TestNAT44EndpointDependent, cls).setUpConstants() - cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"]) - - @classmethod def setUpClass(cls): super(TestNAT44EndpointDependent, cls).setUpClass() cls.vapi.cli("set log class nat level debug") @@ -4352,14 +4258,23 @@ class TestNAT44EndpointDependent(MethodHolder): cls.pg8.config_ip4() cls.pg8.resolve_arp() + @classmethod + def tearDownClass(cls): + super(TestNAT44EndpointDependent, cls).tearDownClass() + def setUp(self): super(TestNAT44EndpointDependent, self).setUp() + flags = self.nat44_config_flags.NAT44_IS_ENDPOINT_DEPENDENT + self.vapi.nat44_plugin_enable_disable(enable=1, flags=flags) self.vapi.nat_set_timeouts( - udp=300, tcp_established=7440, tcp_transitory=240, icmp=60) + udp=300, tcp_established=7440, + tcp_transitory=240, icmp=60) - @classmethod - def tearDownClass(cls): - super(TestNAT44EndpointDependent, cls).tearDownClass() + def tearDown(self): + super(TestNAT44EndpointDependent, self).tearDown() + if not self.vpp_dead: + self.vapi.nat44_plugin_enable_disable(enable=0) + self.vapi.cli("clear logging") def test_frag_in_order(self): """ NAT44 translate fragments arriving in order """ @@ -7120,12 +7035,6 @@ class TestNAT44EndpointDependent(MethodHolder): external_sw_if_index=0xFFFFFFFF, flags=flags) - def tearDown(self): - super(TestNAT44EndpointDependent, self).tearDown() - if not self.vpp_dead: - self.clear_nat44() - self.vapi.cli("clear logging") - def show_commands_at_teardown(self): self.logger.info(self.vapi.cli("show errors")) self.logger.info(self.vapi.cli("show nat44 addresses")) @@ -7144,15 +7053,6 @@ class TestNAT44EndpointDependent3(MethodHolder): max_translations = 50 @classmethod - def setUpConstants(cls): - super(TestNAT44EndpointDependent3, cls).setUpConstants() - cls.vpp_cmdline.extend([ - "nat", "{", "endpoint-dependent", - "max translations per thread %d" % cls.max_translations, - "}" - ]) - - @classmethod def setUpClass(cls): super(TestNAT44EndpointDependent3, cls).setUpClass() cls.vapi.cli("set log class nat level debug") @@ -7168,8 +7068,13 @@ class TestNAT44EndpointDependent3(MethodHolder): def setUp(self): super(TestNAT44EndpointDependent3, self).setUp() + flags = self.nat44_config_flags.NAT44_IS_ENDPOINT_DEPENDENT + self.vapi.nat44_plugin_enable_disable( + sessions=self.max_translations, + flags=flags, enable=1) self.vapi.nat_set_timeouts( udp=1, tcp_established=7440, tcp_transitory=30, icmp=1) + self.nat44_add_address(self.nat_addr) flags = self.config_flags.NAT_IS_INSIDE self.vapi.nat44_interface_add_del_feature( @@ -7181,6 +7086,12 @@ class TestNAT44EndpointDependent3(MethodHolder): def tearDownClass(cls): super(TestNAT44EndpointDependent3, cls).tearDownClass() + def tearDown(self): + super(TestNAT44EndpointDependent3, self).tearDown() + if not self.vpp_dead: + self.vapi.nat44_plugin_enable_disable(enable=0) + self.vapi.cli("clear logging") + def init_tcp_session(self, in_if, out_if, sport, ext_dport): # SYN packet in->out p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) / @@ -7246,11 +7157,6 @@ class TestNAT44Out2InDPO(MethodHolder): """ NAT44 Test Cases using out2in DPO """ @classmethod - def setUpConstants(cls): - super(TestNAT44Out2InDPO, cls).setUpConstants() - cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"]) - - @classmethod def setUpClass(cls): super(TestNAT44Out2InDPO, cls).setUpClass() cls.vapi.cli("set log class nat level debug") @@ -7284,6 +7190,17 @@ class TestNAT44Out2InDPO(MethodHolder): def tearDownClass(cls): super(TestNAT44Out2InDPO, cls).tearDownClass() + def setUp(self): + super(TestNAT44Out2InDPO, self).setUp() + flags = self.nat44_config_flags.NAT44_API_IS_OUT2IN_DPO + self.vapi.nat44_plugin_enable_disable(enable=1, flags=flags) + + def tearDown(self): + super(TestNAT44Out2InDPO, self).tearDown() + if not self.vpp_dead: + self.vapi.nat44_plugin_enable_disable(enable=0) + self.vapi.cli("clear logging") + def configure_xlat(self): self.dst_ip6_pfx = '1:2:3::' self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6, |