diff options
author | Filip Varga <fivarga@cisco.com> | 2021-11-12 17:22:11 +0100 |
---|---|---|
committer | Ole Tr�an <otroan@employees.org> | 2022-01-04 12:06:00 +0000 |
commit | 67cc0a6922d41b34d251e08ce0ba0c9c58525e4f (patch) | |
tree | 1288bb88cfe9f30fa63500bfba334fca1cd1d640 /src/plugins/nat/nat44-ed/nat44_ed.c | |
parent | aed42948510a94922566fa1a4bfb6eec281e5dee (diff) |
nat: remove nat44-ed relation between SM and addr
Change [1] put static mappings in flow hash. This change also broke
relationship between nat pool addresses and static mappings. Port and
address are no longer reserved in nat pool address records for a new
static mapping.
Because of this change both nat objects and their configuration can
function independently. This change also removed already broken logic of
having static-mapping-only configuration.
In this patch i have cleaned up and removed unnecessary logic for static
mapping configuration functions, address configuration functions,
interface configuraiton functions and all callback functions used for
resolving interface address bound records.
No more viable configuration option static-mapping-only is also removed
because there is no more option to run traffic through vpp for static
mappings without having flow hash table allocated. Instead user is now
able to create static mapping records without using nat pool addresses.
Fixed and improved management of required fib entries (ensuring VPP will
reply to ARP for all external addresses on outside interfaces) through
holding a refcount for their creation and removal.
[1] https://gerrit.fd.io/r/c/vpp/+/34077
Type: improvement
Change-Id: Ic16deefbede833d574c2a5972155c9afa5bc62ce
Signed-off-by: Filip Varga <fivarga@cisco.com>
Diffstat (limited to 'src/plugins/nat/nat44-ed/nat44_ed.c')
-rw-r--r-- | src/plugins/nat/nat44-ed/nat44_ed.c | 806 |
1 files changed, 363 insertions, 443 deletions
diff --git a/src/plugins/nat/nat44-ed/nat44_ed.c b/src/plugins/nat/nat44-ed/nat44_ed.c index 7907d8ffa6b..d3ef3d54f89 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.c +++ b/src/plugins/nat/nat44-ed/nat44_ed.c @@ -185,9 +185,11 @@ static int nat44_ed_add_static_mapping_internal ( ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags, ip4_address_t pool_addr, u8 *tag); -static int nat44_ed_del_static_mapping_internal ( - ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, - ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags); +static int nat44_ed_del_static_mapping_internal (ip4_address_t l_addr, + ip4_address_t e_addr, + u16 l_port, u16 e_port, + ip_protocol_t proto, + u32 vrf_id, u32 flags); u32 nat_calc_bihash_buckets (u32 n_elts); @@ -290,25 +292,6 @@ nat44_ed_free_session_data (snat_main_t *sm, snat_session_t *s, } } -static int -is_snat_address_used_in_static_mapping (snat_main_t *sm, ip4_address_t addr) -{ - snat_static_mapping_t *m; - pool_foreach (m, sm->static_mappings) - { - if (is_sm_addr_only (m->flags) || is_sm_out2in_only (m->flags) || - is_sm_identity_nat (m->flags)) - { - continue; - } - if (m->external_addr.as_u32 == addr.as_u32) - { - return 1; - } - } - return 0; -} - static ip_interface_address_t * nat44_ed_get_ip_interface_address (u32 sw_if_index, ip4_address_t addr) { @@ -415,41 +398,91 @@ nat44_ed_bind_if_addr_to_nat_addr (u32 sw_if_index) } } +static_always_inline snat_fib_entry_reg_t * +nat44_ed_get_fib_entry_reg (ip4_address_t addr, u32 sw_if_index, int *out_idx) +{ + snat_main_t *sm = &snat_main; + snat_fib_entry_reg_t *fe; + int i; + + for (i = 0; i < vec_len (sm->fib_entry_reg); i++) + { + fe = sm->fib_entry_reg + i; + if ((addr.as_u32 == fe->addr.as_u32) && (sw_if_index == fe->sw_if_index)) + { + if (out_idx) + { + *out_idx = i; + } + return fe; + } + } + return NULL; +} + static void -nat44_ed_add_del_addr_to_fib (ip4_address_t *addr, u8 p_len, u32 sw_if_index, - int is_add) +nat44_ed_add_fib_entry_reg (ip4_address_t addr, u32 sw_if_index) { // Add the external NAT address to the FIB as receive entries. This ensures // that VPP will reply to ARP for this address and we don't need to enable // proxy ARP on the outside interface. - snat_main_t *sm = &snat_main; - fib_prefix_t prefix = { - .fp_len = p_len, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = addr->as_u32, - }, - }; - u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index); + snat_fib_entry_reg_t *fe; - if (is_add) + if (!(fe = nat44_ed_get_fib_entry_reg (addr, sw_if_index, 0))) { + fib_prefix_t prefix = { + .fp_len = 32, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = { + .ip4.as_u32 = addr.as_u32, + }, + }; + u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index); fib_table_entry_update_one_path (fib_index, &prefix, sm->fib_src_low, (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_EXCLUSIVE), DPO_PROTO_IP4, NULL, sw_if_index, ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE); + + vec_add2 (sm->fib_entry_reg, fe, 1); + clib_memset (fe, 0, sizeof (*fe)); + fe->addr.as_u32 = addr.as_u32; + fe->sw_if_index = sw_if_index; } - else + fe->count++; +} + +static void +nat44_ed_del_fib_entry_reg (ip4_address_t addr, u32 sw_if_index) +{ + snat_main_t *sm = &snat_main; + snat_fib_entry_reg_t *fe; + int i; + + if ((fe = nat44_ed_get_fib_entry_reg (addr, sw_if_index, &i))) { - fib_table_entry_delete (fib_index, &prefix, sm->fib_src_low); + fe->count--; + if (0 == fe->count) + { + fib_prefix_t prefix = { + .fp_len = 32, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = { + .ip4.as_u32 = addr.as_u32, + }, + }; + u32 fib_index = + ip4_fib_table_get_index_for_sw_if_index (sw_if_index); + fib_table_entry_delete (fib_index, &prefix, sm->fib_src_low); + vec_del1 (sm->fib_entry_reg, i); + } } } static void -nat44_ed_add_del_addr_to_fib_foreach_out_if (ip4_address_t *addr, u8 is_add) +nat44_ed_add_del_interface_fib_reg_entries (ip4_address_t addr, u8 is_add) { snat_main_t *sm = &snat_main; snat_interface_t *i; @@ -458,42 +491,66 @@ nat44_ed_add_del_addr_to_fib_foreach_out_if (ip4_address_t *addr, u8 is_add) { if (nat44_ed_is_interface_outside (i)) { - nat44_ed_add_del_addr_to_fib (addr, 32, i->sw_if_index, is_add); + if (is_add) + { + nat44_ed_add_fib_entry_reg (addr, i->sw_if_index); + } + else + { + nat44_ed_del_fib_entry_reg (addr, i->sw_if_index); + } } } pool_foreach (i, sm->output_feature_interfaces) { if (nat44_ed_is_interface_outside (i)) { - nat44_ed_add_del_addr_to_fib (addr, 32, i->sw_if_index, is_add); + if (is_add) + { + nat44_ed_add_fib_entry_reg (addr, i->sw_if_index); + } + else + { + nat44_ed_del_fib_entry_reg (addr, i->sw_if_index); + } } } } static_always_inline void -nat44_ed_add_del_addr_to_fib_foreach_addr (u32 sw_if_index, u8 is_add) +nat44_ed_add_del_nat_addr_fib_reg_entries (u32 sw_if_index, u8 is_add) { snat_main_t *sm = &snat_main; snat_address_t *ap; vec_foreach (ap, sm->addresses) { - nat44_ed_add_del_addr_to_fib (&ap->addr, 32, sw_if_index, is_add); + if (is_add) + { + nat44_ed_add_fib_entry_reg (ap->addr, sw_if_index); + } + else + { + nat44_ed_del_fib_entry_reg (ap->addr, sw_if_index); + } } } static_always_inline void -nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (u32 sw_if_index, u8 is_add) +nat44_ed_add_del_sm_fib_reg_entries (u32 sw_if_index, u8 is_add) { snat_main_t *sm = &snat_main; snat_static_mapping_t *m; pool_foreach (m, sm->static_mappings) { - if (is_sm_addr_only (m->flags) && !is_sm_identity_nat (m->flags)) + if (is_add) { - nat44_ed_add_del_addr_to_fib (&m->external_addr, 32, sw_if_index, - is_add); + nat44_ed_add_fib_entry_reg (m->external_addr, sw_if_index); + } + else + { + nat44_ed_del_fib_entry_reg (m->external_addr, sw_if_index); } } } @@ -544,21 +601,20 @@ nat44_ed_add_address (ip4_address_t *addr, u32 vrf_id, u8 twice_nat) { // if we don't have enabled interface we don't add address // to fib - nat44_ed_add_del_addr_to_fib_foreach_out_if (addr, 1); + nat44_ed_add_del_interface_fib_reg_entries (*addr, 1); nat44_ed_update_outside_if_addresses (ap); } return 0; } int -nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat) +nat44_ed_del_address (ip4_address_t addr, u8 twice_nat) { snat_main_t *sm = &snat_main; snat_address_t *a = 0, *addresses; snat_session_t *ses; u32 *ses_to_be_removed = 0, *ses_index; snat_main_per_thread_data_t *tsm; - snat_static_mapping_t *m; int j; addresses = twice_nat ? sm->twice_nat_addresses : sm->addresses; @@ -577,33 +633,15 @@ nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat) return VNET_API_ERROR_NO_SUCH_ENTRY; } - if (delete_sm) - { - pool_foreach (m, sm->static_mappings) - { - if (m->external_addr.as_u32 == addr.as_u32) - { - nat44_ed_del_static_mapping_internal ( - m->local_addr, m->external_addr, m->local_port, - m->external_port, ip_proto_to_nat_proto (m->proto), m->vrf_id, - ~0, m->flags); - } - } - } - else - { - if (is_snat_address_used_in_static_mapping (sm, addr)) - { - nat_log_err ("address used in static mapping"); - return VNET_API_ERROR_UNSPECIFIED; - } - } - - // delete sessions using address + // delete dynamic sessions only vec_foreach (tsm, sm->per_thread_data) { pool_foreach (ses, tsm->sessions) { + if (ses->flags & SNAT_SESSION_FLAG_STATIC_MAPPING) + { + continue; + } if (ses->out2in.addr.as_u32 == addr.as_u32) { nat44_ed_free_session_data (sm, ses, tsm - sm->per_thread_data, @@ -621,7 +659,7 @@ nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat) if (!twice_nat) { - nat44_ed_add_del_addr_to_fib_foreach_out_if (&addr, 0); + nat44_ed_add_del_interface_fib_reg_entries (addr, 0); } if (a->fib_index != ~0) @@ -730,38 +768,18 @@ nat44_ed_sm_i2o_lookup (snat_main_t *sm, ip4_address_t addr, u16 port, return nat44_ed_sm_lookup (sm, &kv); } -void -nat44_ed_add_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, - ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, - u32 flags, ip4_address_t pool_addr, u8 *tag) -{ - snat_static_map_resolve_t *rp; - snat_main_t *sm = &snat_main; - - vec_add2 (sm->to_resolve, rp, 1); - rp->l_addr.as_u32 = l_addr.as_u32; - rp->l_port = l_port; - rp->e_port = e_port; - rp->sw_if_index = sw_if_index; - rp->vrf_id = vrf_id; - rp->proto = proto; - rp->flags = flags; - rp->pool_addr = pool_addr; - rp->tag = vec_dup (tag); -} - -int +static snat_static_mapping_resolve_t * nat44_ed_get_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, - u32 flags, int *out) + u32 flags, int *out_idx) { - snat_static_map_resolve_t *rp; + snat_static_mapping_resolve_t *rp; snat_main_t *sm = &snat_main; int i; - for (i = 0; i < vec_len (sm->to_resolve); i++) + for (i = 0; i < vec_len (sm->sm_to_resolve); i++) { - rp = sm->to_resolve + i; + rp = sm->sm_to_resolve + i; if (rp->sw_if_index == sw_if_index && rp->vrf_id == vrf_id) { @@ -790,27 +808,27 @@ nat44_ed_get_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, { continue; } - if (out) + if (out_idx) { - *out = i; + *out_idx = i; } - return 0; + return rp; } } - return 1; + return NULL; } -int +static int nat44_ed_del_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags) { snat_main_t *sm = &snat_main; int i; - if (!nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id, - sw_if_index, flags, &i)) + if (nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id, + sw_if_index, flags, &i)) { - vec_del1 (sm->to_resolve, i); + vec_del1 (sm->sm_to_resolve, i); return 0; } return 1; @@ -835,50 +853,69 @@ nat44_ed_validate_sm_input (u32 flags) return 0; } -snat_address_t * -nat44_ed_addr_lookup (snat_main_t *sm, u32 addr) -{ - for (int i = 0; i < vec_len (sm->addresses); ++i) - { - if (sm->addresses[i].addr.as_u32 == addr) - return &sm->addresses[i]; - } - return NULL; -} - int nat44_ed_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags, ip4_address_t pool_addr, u8 *tag) { + snat_static_mapping_resolve_t *rp; snat_main_t *sm = &snat_main; + int rv; + + if (!sm->enabled) + { + return VNET_API_ERROR_UNSUPPORTED; + } + + rv = nat44_ed_validate_sm_input (flags); + if (rv != 0) + { + return rv; + } // interface bound mapping if (is_sm_switch_address (flags)) { - if (!nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id, - sw_if_index, flags, 0)) + if (nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id, + sw_if_index, flags, 0)) { return VNET_API_ERROR_VALUE_EXIST; } - nat44_ed_add_resolve_record (l_addr, l_port, e_port, proto, vrf_id, - sw_if_index, flags, pool_addr, tag); + vec_add2 (sm->sm_to_resolve, rp, 1); + rp->l_addr.as_u32 = l_addr.as_u32; + rp->l_port = l_port; + rp->e_port = e_port; + rp->sw_if_index = sw_if_index; + rp->vrf_id = vrf_id; + rp->proto = proto; + rp->flags = flags; + rp->pool_addr = pool_addr; + rp->tag = vec_dup (tag); + rp->is_resolved = 0; + ip4_address_t *first_int_addr = ip4_interface_first_address (sm->ip4_main, sw_if_index, 0); if (!first_int_addr) { - // dhcp resolution required return 0; } e_addr.as_u32 = first_int_addr->as_u32; + rp->is_resolved = 1; + } + + rv = nat44_ed_add_static_mapping_internal (l_addr, e_addr, l_port, e_port, + proto, vrf_id, sw_if_index, flags, + pool_addr, tag); + if ((0 != rv) && is_sm_switch_address (flags)) + { + nat44_ed_del_resolve_record (l_addr, l_port, e_port, proto, vrf_id, + sw_if_index, flags); } - return nat44_ed_add_static_mapping_internal (l_addr, e_addr, l_port, e_port, - proto, vrf_id, sw_if_index, - flags, pool_addr, tag); + return rv; } int @@ -886,8 +923,19 @@ nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags) { - snat_main_t *sm = &snat_main; + int rv; + + if (!sm->enabled) + { + return VNET_API_ERROR_UNSUPPORTED; + } + + rv = nat44_ed_validate_sm_input (flags); + if (rv != 0) + { + return rv; + } // interface bound mapping if (is_sm_switch_address (flags)) @@ -909,8 +957,8 @@ nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, e_addr.as_u32 = first_int_addr->as_u32; } - return nat44_ed_del_static_mapping_internal ( - l_addr, e_addr, l_port, e_port, proto, vrf_id, sw_if_index, flags); + return nat44_ed_del_static_mapping_internal (l_addr, e_addr, l_port, e_port, + proto, vrf_id, flags); } static int @@ -924,18 +972,6 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr, nat44_lb_addr_port_t *local; snat_static_mapping_t *m; u32 fib_index = ~0; - int rv; - - if (!sm->enabled) - { - return VNET_API_ERROR_UNSUPPORTED; - } - - rv = nat44_ed_validate_sm_input (flags); - if (rv != 0) - { - return rv; - } if (is_sm_addr_only (flags)) { @@ -951,13 +987,14 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr, m = nat44_ed_sm_o2i_lookup (sm, e_addr, e_port, 0, proto); if (m) { + // case: + // adding local identity nat record for different vrf table + if (!is_sm_identity_nat (m->flags)) { return VNET_API_ERROR_VALUE_EXIST; } - // case: - // adding local identity nat record for different vrf table pool_foreach (local, m->locals) { if (local->vrf_id == vrf_id) @@ -1001,21 +1038,6 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr, } } - if (!(is_sm_out2in_only (flags) || is_sm_addr_only (flags) || - sm->static_mapping_only)) - { - if (!nat44_ed_addr_lookup (sm, e_addr.as_u32)) - { - // remove resolve record - if (is_sm_switch_address (flags) && !is_sm_identity_nat (flags)) - { - nat44_ed_del_resolve_record (l_addr, l_port, e_port, proto, - vrf_id, sw_if_index, flags); - } - return VNET_API_ERROR_NO_SUCH_ENTRY; - } - } - pool_get (sm->static_mappings, m); clib_memset (m, 0, sizeof (*m)); @@ -1023,13 +1045,9 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr, m->local_addr = l_addr; m->external_addr = e_addr; + m->pool_addr = pool_addr; m->tag = vec_dup (tag); - if (is_sm_exact_address (flags) && is_sm_twice_nat (flags)) - { - m->pool_addr = pool_addr; - } - if (!is_sm_addr_only (flags)) { m->local_port = l_port; @@ -1048,12 +1066,6 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr, { m->vrf_id = vrf_id; m->fib_index = fib_index; - - // not identity && addr only - if (is_sm_addr_only (flags)) - { - nat44_ed_add_del_addr_to_fib_foreach_out_if (&e_addr, 1); - } } if (!is_sm_out2in_only (flags)) @@ -1076,6 +1088,8 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr, vec_add1 (m->workers, worker_index); } + nat44_ed_add_del_interface_fib_reg_entries (e_addr, 1); + return 0; } @@ -1083,7 +1097,7 @@ static int nat44_ed_del_static_mapping_internal (ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, ip_protocol_t proto, - u32 vrf_id, u32 sw_if_index, u32 flags) + u32 vrf_id, u32 flags) { snat_main_per_thread_data_t *tsm; snat_main_t *sm = &snat_main; @@ -1091,18 +1105,6 @@ nat44_ed_del_static_mapping_internal (ip4_address_t l_addr, nat44_lb_addr_port_t *local; snat_static_mapping_t *m; u32 fib_index = ~0; - int rv; - - if (!sm->enabled) - { - return VNET_API_ERROR_UNSUPPORTED; - } - - rv = nat44_ed_validate_sm_input (flags); - if (rv != 0) - { - return rv; - } if (is_sm_addr_only (flags)) { @@ -1117,13 +1119,8 @@ nat44_ed_del_static_mapping_internal (ip4_address_t l_addr, // fib index 0 m = nat44_ed_sm_o2i_lookup (sm, e_addr, e_port, 0, proto); - if (!m) { - if (is_sm_switch_address (flags)) - { - return 0; - } return VNET_API_ERROR_NO_SUCH_ENTRY; } @@ -1157,33 +1154,25 @@ nat44_ed_del_static_mapping_internal (ip4_address_t l_addr, fib_index = m->fib_index; } - if (!(is_sm_out2in_only (flags) || is_sm_addr_only (flags) || - sm->static_mapping_only)) - { - if (!nat44_ed_addr_lookup (sm, e_addr.as_u32)) - { - return VNET_API_ERROR_INVALID_VALUE; - } - } - if (!is_sm_out2in_only (flags)) { nat44_ed_sm_i2o_del (sm, l_addr, l_port, fib_index, proto); } - if (!sm->static_mapping_only || sm->static_mapping_connection_tracking) + // delete sessions for static mapping + if (sm->num_workers > 1) { - // delete sessions for static mapping - if (sm->num_workers > 1) - tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]); - else - tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); - - nat_ed_static_mapping_del_sessions ( - sm, tsm, m->local_addr, m->local_port, m->proto, fib_index, - is_sm_addr_only (flags), e_addr, e_port); + tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]); + } + else + { + tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); } + nat_ed_static_mapping_del_sessions (sm, tsm, m->local_addr, m->local_port, + m->proto, fib_index, + is_sm_addr_only (flags), e_addr, e_port); + fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low); if (!pool_elts (m->locals)) @@ -1196,10 +1185,7 @@ nat44_ed_del_static_mapping_internal (ip4_address_t l_addr, vec_free (m->workers); pool_put (sm->static_mappings, m); - if (is_sm_addr_only (flags) && !is_sm_identity_nat (flags)) - { - nat44_ed_add_del_addr_to_fib_foreach_out_if (&e_addr, 0); - } + nat44_ed_add_del_interface_fib_reg_entries (e_addr, 0); } return 0; @@ -1238,7 +1224,7 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port, return VNET_API_ERROR_INVALID_VALUE; } - if (!(sm->static_mapping_only || is_sm_out2in_only (flags))) + if (!is_sm_out2in_only (flags)) { /* Find external address in allocated addresses and reserve port for address and port pair mapping when dynamic translations enabled */ @@ -1282,7 +1268,7 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port, if (nat44_ed_sm_o2i_add (sm, m, m->external_addr, m->external_port, 0, m->proto)) { - nat_elog_err (sm, "sm o2i key add failed"); + nat_log_err ("sm o2i key add failed"); return VNET_API_ERROR_UNSPECIFIED; } @@ -1294,7 +1280,7 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port, { if (nat44_ed_sm_o2i_add (sm, m, e_addr, e_port, 0, proto)) { - nat_elog_err (sm, "sm o2i key add failed"); + nat_log_err ("sm o2i key add failed"); rc = VNET_API_ERROR_UNSPECIFIED; // here we continue with add operation so that it can be safely // reversed in delete path - otherwise we'd have to track what @@ -1357,7 +1343,7 @@ nat44_ed_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, if (nat44_ed_sm_o2i_del (sm, m->external_addr, m->external_port, 0, m->proto)) { - nat_elog_err (sm, "sm o2i key del failed"); + nat_log_err ("sm o2i key del failed"); return VNET_API_ERROR_UNSPECIFIED; } @@ -1369,7 +1355,7 @@ nat44_ed_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, if (nat44_ed_sm_i2o_del (sm, local->addr, local->port, local->fib_index, m->proto)) { - nat_elog_err (sm, "sm i2o key del failed"); + nat_log_err ("sm i2o key del failed"); return VNET_API_ERROR_UNSPECIFIED; } } @@ -1478,7 +1464,7 @@ nat44_ed_add_del_lb_static_mapping_local (ip4_address_t e_addr, u16 e_port, if (nat44_ed_sm_i2o_add (sm, m, l_addr, l_port, local->fib_index, proto)) { - nat_elog_err (sm, "sm i2o key add failed"); + nat_log_err ("sm i2o key add failed"); pool_put (m->locals, local); return VNET_API_ERROR_UNSPECIFIED; } @@ -1499,7 +1485,7 @@ nat44_ed_add_del_lb_static_mapping_local (ip4_address_t e_addr, u16 e_port, { if (nat44_ed_sm_i2o_del (sm, l_addr, l_port, match_local->fib_index, proto)) - nat_elog_err (sm, "sm i2o key del failed"); + nat_log_err ("sm i2o key del failed"); } if (sm->num_workers > 1) @@ -1747,8 +1733,8 @@ nat44_ed_add_interface (u32 sw_if_index, u8 is_inside) outside_fib->refcount = 1; } - nat44_ed_add_del_addr_to_fib_foreach_addr (sw_if_index, 1); - nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 1); + nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 1); + nat44_ed_add_del_sm_fib_reg_entries (sw_if_index, 1); nat44_ed_bind_if_addr_to_nat_addr (sw_if_index); } @@ -1858,8 +1844,8 @@ nat44_ed_del_interface (u32 sw_if_index, u8 is_inside) } } - nat44_ed_add_del_addr_to_fib_foreach_addr (sw_if_index, 0); - nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 0); + nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 0); + nat44_ed_add_del_sm_fib_reg_entries (sw_if_index, 0); } return 0; @@ -1957,8 +1943,8 @@ nat44_ed_add_output_interface (u32 sw_if_index) outside_fib->refcount = 1; } - nat44_ed_add_del_addr_to_fib_foreach_addr (sw_if_index, 1); - nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 1); + nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 1); + nat44_ed_add_del_sm_fib_reg_entries (sw_if_index, 1); nat44_ed_bind_if_addr_to_nat_addr (sw_if_index); @@ -2045,8 +2031,8 @@ nat44_ed_del_output_interface (u32 sw_if_index) } } - nat44_ed_add_del_addr_to_fib_foreach_addr (sw_if_index, 0); - nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 0); + nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 0); + nat44_ed_add_del_sm_fib_reg_entries (sw_if_index, 0); return 0; } @@ -2103,7 +2089,7 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index, } pool_foreach (i, sm->interfaces) - { + { if (i->sw_if_index == sw_if_index) { if (!(nat44_ed_is_interface_outside (i))) @@ -2113,7 +2099,7 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index, } pool_foreach (i, sm->output_feature_interfaces) - { + { if (i->sw_if_index == sw_if_index) { if (!(nat44_ed_is_interface_outside (i))) @@ -2126,25 +2112,25 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index, return; vec_foreach (outside_fib, sm->outside_fibs) - { - if (outside_fib->fib_index == old_fib_index) - { - outside_fib->refcount--; - if (!outside_fib->refcount) - vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs); - break; - } - } + { + if (outside_fib->fib_index == old_fib_index) + { + outside_fib->refcount--; + if (!outside_fib->refcount) + vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs); + break; + } + } vec_foreach (outside_fib, sm->outside_fibs) - { - if (outside_fib->fib_index == new_fib_index) - { - outside_fib->refcount++; - is_add = 0; - break; - } - } + { + if (outside_fib->fib_index == new_fib_index) + { + outside_fib->refcount++; + is_add = 0; + break; + } + } if (is_add) { @@ -2162,7 +2148,7 @@ static void nat44_ed_add_del_interface_address_cb ( ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_delete); -static void nat44_ed_add_del_static_mapping_addr_only_cb ( +static void nat44_ed_add_del_static_mapping_cb ( ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_delete); @@ -2351,7 +2337,7 @@ nat_init (vlib_main_t * vm) /* callbacks to call when interface address changes. */ cbi.function = nat44_ed_add_del_interface_address_cb; vec_add1 (sm->ip4_main->add_del_interface_address_callbacks, cbi); - cbi.function = nat44_ed_add_del_static_mapping_addr_only_cb; + cbi.function = nat44_ed_add_del_static_mapping_cb; vec_add1 (sm->ip4_main->add_del_interface_address_callbacks, cbi); /* callbacks to call when interface to table biding changes */ @@ -2380,19 +2366,8 @@ nat44_plugin_enable (nat44_config_t c) fail_if_enabled (); - if (c.static_mapping_only && !c.connection_tracking) - { - nat_log_err ("unsupported combination of configuration"); - return 1; - } - - sm->static_mapping_only = c.static_mapping_only; - sm->static_mapping_connection_tracking = c.connection_tracking; - sm->forwarding_enabled = 0; sm->mss_clamping = 0; - sm->pat = (!c.static_mapping_only || - (c.static_mapping_only && c.connection_tracking)); if (!c.sessions) c.sessions = 63 * 1024; @@ -2461,7 +2436,7 @@ nat44_ed_del_addresses () vec = vec_dup (sm->addresses); vec_foreach (a, vec) { - error = nat44_ed_del_address (a->addr, 0, 0); + error = nat44_ed_del_address (a->addr, 0); if (error) { nat_log_err ("error occurred while removing adderess"); @@ -2474,7 +2449,7 @@ nat44_ed_del_addresses () vec = vec_dup (sm->twice_nat_addresses); vec_foreach (a, vec) { - error = nat44_ed_del_address (a->addr, 0, 1); + error = nat44_ed_del_address (a->addr, 1); if (error) { nat_log_err ("error occurred while removing adderess"); @@ -2484,11 +2459,8 @@ nat44_ed_del_addresses () vec_free (sm->twice_nat_addresses); sm->twice_nat_addresses = 0; - vec_free (sm->auto_add_sw_if_indices_twice_nat); - sm->auto_add_sw_if_indices_twice_nat = 0; - - vec_free (sm->auto_add_sw_if_indices); - sm->auto_add_sw_if_indices = 0; + vec_free (sm->addr_to_resolve); + sm->addr_to_resolve = 0; return error; } @@ -2557,7 +2529,7 @@ nat44_ed_del_static_mappings () { error = nat44_ed_del_static_mapping_internal ( m->local_addr, m->external_addr, m->local_port, m->external_port, - m->proto, m->vrf_id, ~0, m->flags); + m->proto, m->vrf_id, m->flags); if (error) { nat_log_err ("error occurred while removing mapping"); @@ -2567,8 +2539,8 @@ nat44_ed_del_static_mappings () pool_free (sm->static_mappings); sm->static_mappings = 0; - vec_free (sm->to_resolve); - sm->to_resolve = 0; + vec_free (sm->sm_to_resolve); + sm->sm_to_resolve = 0; return error; } @@ -2603,12 +2575,9 @@ nat44_plugin_disable () clib_bihash_free_16_8 (&sm->flow_hash); - if (sm->pat) + vec_foreach (tsm, sm->per_thread_data) { - vec_foreach (tsm, sm->per_thread_data) - { - nat44_ed_worker_db_free (tsm); - } + nat44_ed_worker_db_free (tsm); } clib_memset (&sm->rconfig, 0, sizeof (sm->rconfig)); @@ -3231,13 +3200,10 @@ nat44_ed_db_init (u32 translations, u32 translation_buckets) reinit_ed_flow_hash (); - if (sm->pat) + vec_foreach (tsm, sm->per_thread_data) { - vec_foreach (tsm, sm->per_thread_data) - { - nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread, - sm->translation_buckets); - } + nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread, + sm->translation_buckets); } } @@ -3257,95 +3223,105 @@ nat44_ed_sessions_clear () reinit_ed_flow_hash (); - if (sm->pat) + vec_foreach (tsm, sm->per_thread_data) { - vec_foreach (tsm, sm->per_thread_data) - { - - nat44_ed_worker_db_free (tsm); - nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread, - sm->translation_buckets); - } + nat44_ed_worker_db_free (tsm); + nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread, + sm->translation_buckets); } vlib_zero_simple_counter (&sm->total_sessions, 0); } static void -nat44_ed_add_del_static_mapping_addr_only_cb ( - ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, - u32 address_length, u32 if_address_index, u32 is_delete) +nat44_ed_add_del_static_mapping_cb (ip4_main_t *im, uword opaque, + u32 sw_if_index, ip4_address_t *address, + u32 address_length, u32 if_address_index, + u32 is_delete) { - snat_static_map_resolve_t *rp; + snat_static_mapping_resolve_t *rp; snat_main_t *sm = &snat_main; - snat_static_mapping_t *m; - int i, rv = 0, match = 0; + int rv = 0; if (!sm->enabled) { return; } - // find first addr_only resolve record by sw_if_index - for (i = 0; i < vec_len (sm->to_resolve); i++) + vec_foreach (rp, sm->sm_to_resolve) { - rp = sm->to_resolve + i; - if (is_sm_addr_only (rp->flags) && rp->sw_if_index == sw_if_index) + if (sw_if_index == rp->sw_if_index) { - match = 1; - break; + if (is_delete) + { + if (rp->is_resolved) + { + rv = nat44_ed_del_static_mapping_internal ( + rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto, + rp->vrf_id, rp->flags); + if (rv) + { + nat_log_err ("ed del static mapping failed"); + } + else + { + rp->is_resolved = 0; + } + } + } + else + { + if (!rp->is_resolved) + { + rv = nat44_ed_add_static_mapping_internal ( + rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto, + rp->vrf_id, ~0, rp->flags, rp->pool_addr, rp->tag); + if (rv) + { + nat_log_err ("ed add static mapping failed"); + } + else + { + rp->is_resolved = 1; + } + } + } } } - if (!match) - { - return; - } +} - m = nat44_ed_sm_o2i_lookup ( - sm, *address, is_sm_addr_only (rp->flags) ? 0 : rp->e_port, 0, rp->proto); +static int +nat44_ed_get_addr_resolve_record (u32 sw_if_index, u8 twice_nat, int *out) +{ + snat_main_t *sm = &snat_main; + snat_address_resolve_t *rp; + int i; - if (is_delete) - { - if (m) - { - rv = nat44_ed_del_static_mapping_internal ( - rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto, - rp->vrf_id, ~0, rp->flags); - } - if (rv) - { - nat_elog_notice_X1 (sm, "nat44_ed_del_static_mapping returned %d", - "i4", rv); - } - } - else + for (i = 0; i < vec_len (sm->addr_to_resolve); i++) { - if (!m) - { - rv = nat44_ed_add_static_mapping_internal ( - rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto, - rp->vrf_id, ~0, rp->flags, rp->pool_addr, rp->tag); - } - // else: don't trip over lease renewal, static config - if (rv) + rp = sm->addr_to_resolve + i; + + if ((rp->sw_if_index == sw_if_index) && (rp->is_twice_nat == twice_nat)) { - nat_elog_notice_X1 (sm, "nat44_ed_add_static_mapping returned %d", - "i4", rv); + if (out) + { + *out = i; + } + return 0; } } + return 1; } - -static_always_inline int -is_sw_if_index_reg_for_auto_resolve (u32 *sw_if_indices, u32 sw_if_index) +static int +nat44_ed_del_addr_resolve_record (u32 sw_if_index, u8 twice_nat) { - u32 *i; - vec_foreach (i, sw_if_indices) + snat_main_t *sm = &snat_main; + int i; + if (!nat44_ed_get_addr_resolve_record (sw_if_index, twice_nat, &i)) { - if (*i == sw_if_index) - { - return 1; - } + vec_del1 (sm->addr_to_resolve, i); + return 0; } - return 0; + return 1; } static void @@ -3355,23 +3331,21 @@ nat44_ed_add_del_interface_address_cb (ip4_main_t *im, uword opaque, u32 if_address_index, u32 is_delete) { snat_main_t *sm = &snat_main; - snat_static_map_resolve_t *rp; - snat_address_t *ap, *addresses = sm->addresses; + snat_address_resolve_t *arp; + snat_address_t *ap; u8 twice_nat = 0; - int rv, i; + int i, rv; if (!sm->enabled) { return; } - if (!is_sw_if_index_reg_for_auto_resolve (sm->auto_add_sw_if_indices, - sw_if_index)) + if (nat44_ed_get_addr_resolve_record (sw_if_index, twice_nat, &i)) { - if (!is_sw_if_index_reg_for_auto_resolve ( - sm->auto_add_sw_if_indices_twice_nat, sw_if_index)) + twice_nat = 1; + if (nat44_ed_get_addr_resolve_record (sw_if_index, twice_nat, &i)) { - // interface resolve u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index); vec_foreach (ap, sm->addresses) @@ -3400,51 +3374,35 @@ nat44_ed_add_del_interface_address_cb (ip4_main_t *im, uword opaque, } return; } - else - { - addresses = sm->twice_nat_addresses; - twice_nat = 1; - } } + arp = sm->addr_to_resolve + i; + if (!is_delete) { - // don't trip over lease renewal, static config - for (i = 0; i < vec_len (addresses); i++) + if (arp->is_resolved) { - if (addresses[i].addr.as_u32 == address->as_u32) - { - return; - } + return; } - (void) nat44_ed_add_address (address, ~0, twice_nat); - - // scan static mapping switch address resolution record vector - for (i = 0; i < vec_len (sm->to_resolve); i++) + rv = nat44_ed_add_address (address, ~0, arp->is_twice_nat); + if (0 == rv) { - rp = sm->to_resolve + i; - if (is_sm_addr_only (rp->flags)) - { - continue; - } - if (rp->sw_if_index == sw_if_index) - { - rv = nat44_ed_add_static_mapping_internal ( - rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto, - rp->vrf_id, sw_if_index, rp->flags, rp->pool_addr, rp->tag); - if (rv) - { - nat_elog_notice_X1 ( - sm, "add_static_mapping_internal returned %d", "i4", rv); - } - } + arp->is_resolved = 1; } } else { - // remove all static mapping records - (void) nat44_ed_del_address (address[0], 1, twice_nat); + if (!arp->is_resolved) + { + return; + } + + rv = nat44_ed_del_address (address[0], arp->is_twice_nat); + if (0 == rv) + { + arp->is_resolved = 0; + } } } @@ -3454,34 +3412,34 @@ nat44_ed_add_interface_address (u32 sw_if_index, u8 twice_nat) snat_main_t *sm = &snat_main; ip4_main_t *ip4_main = sm->ip4_main; ip4_address_t *first_int_addr; - u32 *auto_add_sw_if_indices = twice_nat ? - sm->auto_add_sw_if_indices_twice_nat : - sm->auto_add_sw_if_indices; - int i; + snat_address_resolve_t *ap; + int rv; - for (i = 0; i < vec_len (auto_add_sw_if_indices); i++) + if (!sm->enabled) { - if (auto_add_sw_if_indices[i] == sw_if_index) - { - return VNET_API_ERROR_VALUE_EXIST; - } + return VNET_API_ERROR_UNSUPPORTED; } - // add to the auto-address list - if (twice_nat) - { - vec_add1 (sm->auto_add_sw_if_indices_twice_nat, sw_if_index); - } - else + if (!nat44_ed_get_addr_resolve_record (sw_if_index, twice_nat, 0)) { - vec_add1 (sm->auto_add_sw_if_indices, sw_if_index); + return VNET_API_ERROR_VALUE_EXIST; } - // if the address is already bound - or static - add it now + vec_add2 (sm->addr_to_resolve, ap, 1); + ap->sw_if_index = sw_if_index; + ap->is_twice_nat = twice_nat; + ap->is_resolved = 0; + first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0); if (first_int_addr) { - (void) nat44_ed_add_address (first_int_addr, ~0, twice_nat); + rv = nat44_ed_add_address (first_int_addr, ~0, twice_nat); + if (0 != rv) + { + nat44_ed_del_addr_resolve_record (sw_if_index, twice_nat); + return rv; + } + ap->is_resolved = 1; } return 0; @@ -3493,62 +3451,24 @@ nat44_ed_del_interface_address (u32 sw_if_index, u8 twice_nat) snat_main_t *sm = &snat_main; ip4_main_t *ip4_main = sm->ip4_main; ip4_address_t *first_int_addr; - snat_static_map_resolve_t *rp; - u32 *indices_to_delete = 0; - int i, j; - u32 *auto_add_sw_if_indices; if (!sm->enabled) { return VNET_API_ERROR_UNSUPPORTED; } - auto_add_sw_if_indices = twice_nat ? sm->auto_add_sw_if_indices_twice_nat : - sm->auto_add_sw_if_indices; - - for (i = 0; i < vec_len (auto_add_sw_if_indices); i++) + if (nat44_ed_del_addr_resolve_record (sw_if_index, twice_nat)) { - if (auto_add_sw_if_indices[i] == sw_if_index) - { - first_int_addr = - ip4_interface_first_address (ip4_main, sw_if_index, 0); - if (first_int_addr) - { - // remove all static mapping records - (void) nat44_ed_del_address (first_int_addr[0], 1, twice_nat); - } - else - { - for (j = 0; j < vec_len (sm->to_resolve); j++) - { - rp = sm->to_resolve + j; - if (rp->sw_if_index == sw_if_index) - { - vec_add1 (indices_to_delete, j); - } - } - if (vec_len (indices_to_delete)) - { - for (j = vec_len (indices_to_delete) - 1; j >= 0; j--) - { - vec_del1 (sm->to_resolve, j); - } - vec_free (indices_to_delete); - } - } + return VNET_API_ERROR_NO_SUCH_ENTRY; + } - if (twice_nat) - { - vec_del1 (sm->auto_add_sw_if_indices_twice_nat, i); - } - else - { - vec_del1 (sm->auto_add_sw_if_indices, i); - } - return 0; - } + first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0); + if (first_int_addr) + { + return nat44_ed_del_address (first_int_addr[0], twice_nat); } - return VNET_API_ERROR_NO_SUCH_ENTRY; + + return 0; } int |