X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat.c;h=8e4d9df929cea5adf69faa50ae191d0d69eb762b;hb=35dfedc55fe40c781278ca04789b5ecc4c56e9c2;hp=959abd7ebbf1ff68efbf09f82165d593b922a126;hpb=16f0546cadb1248f9dce99788ecc50cc2668c7e4;p=vpp.git diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c old mode 100644 new mode 100755 index 959abd7ebbf..8e4d9df929c --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -152,6 +152,21 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index) snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data, thread_index); + if (is_fwd_bypass_session (s)) + { + ed_key.l_addr = s->in2out.addr; + ed_key.r_addr = s->ext_host_addr; + ed_key.l_port = s->in2out.port; + ed_key.r_port = s->ext_host_port; + ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol); + ed_key.fib_index = 0; + ed_kv.key[0] = ed_key.as_u64[0]; + ed_kv.key[1] = ed_key.as_u64[1]; + if (clib_bihash_add_del_16_8 (&sm->in2out_ed, &ed_kv, 0)) + clib_warning ("in2out_ed key del failed"); + return; + } + /* Endpoint dependent session lookup tables */ if (is_ed_session (s)) { @@ -350,6 +365,7 @@ nat44_classify_node_fn_inline (vlib_main_t * vm, u32 n_left_from, * from, * to_next; nat44_classify_next_t next_index; snat_main_t *sm = &snat_main; + snat_static_mapping_t *m; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -401,7 +417,9 @@ nat44_classify_node_fn_inline (vlib_main_t * vm, kv0.key = m_key0.as_u64; if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv0, &value0)) { - next0 = NAT44_CLASSIFY_NEXT_OUT2IN; + m = pool_elt_at_index (sm->static_mappings, value0.value); + if (m->local_addr.as_u32 != m->external_addr.as_u32) + next0 = NAT44_CLASSIFY_NEXT_OUT2IN; goto enqueue0; } udp_header_t * udp0 = ip4_next_header (ip0); @@ -409,7 +427,11 @@ nat44_classify_node_fn_inline (vlib_main_t * vm, m_key0.protocol = ip_proto_to_snat_proto (ip0->protocol); kv0.key = m_key0.as_u64; if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv0, &value0)) - next0 = NAT44_CLASSIFY_NEXT_OUT2IN; + { + m = pool_elt_at_index (sm->static_mappings, value0.value); + if (m->local_addr.as_u32 != m->external_addr.as_u32) + next0 = NAT44_CLASSIFY_NEXT_OUT2IN; + } } enqueue0: @@ -522,7 +544,7 @@ snat_add_del_addr_to_fib (ip4_address_t * addr, u8 p_len, u32 sw_if_index, if (is_add) fib_table_entry_update_one_path(fib_index, &prefix, - FIB_SOURCE_PLUGIN_HI, + FIB_SOURCE_PLUGIN_LOW, (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_EXCLUSIVE), @@ -536,7 +558,7 @@ snat_add_del_addr_to_fib (ip4_address_t * addr, u8 p_len, u32 sw_if_index, else fib_table_entry_delete(fib_index, &prefix, - FIB_SOURCE_PLUGIN_HI); + FIB_SOURCE_PLUGIN_LOW); } void snat_add_address (snat_main_t *sm, ip4_address_t *addr, u32 vrf_id, @@ -562,7 +584,7 @@ void snat_add_address (snat_main_t *sm, ip4_address_t *addr, u32 vrf_id, if (vrf_id != ~0) ap->fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id, - FIB_SOURCE_PLUGIN_HI); + FIB_SOURCE_PLUGIN_LOW); else ap->fib_index = ~0; #define _(N, i, n, s) \ @@ -654,7 +676,11 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm, * @param addr_only If 0 address port and pair mapping, otherwise address only. * @param sw_if_index External port instead of specific IP address. * @param is_add If 0 delete static mapping, otherwise add. - * @param twice_nat If 1 translate external host address and port. + * @param twice_nat If value is TWICE_NAT then translate external host address + * and port. + * If value is TWICE_NAT_SELF then translate external host + * address and port whenever external host address equals + * local address of internal host. * @param out2in_only If 1 rule match only out2in direction * @param tag - opaque string tag * @@ -663,7 +689,8 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm, int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, u32 vrf_id, int addr_only, u32 sw_if_index, snat_protocol_t proto, int is_add, - u8 twice_nat, u8 out2in_only, u8 * tag) + twice_nat_type_t twice_nat, u8 out2in_only, + u8 * tag) { snat_main_t * sm = &snat_main; snat_static_mapping_t *m; @@ -682,30 +709,73 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, u32 ses_index; u64 user_index; snat_session_t * s; + snat_static_map_resolve_t *rp, *rp_match = 0; /* If the external address is a specific interface address */ if (sw_if_index != ~0) { ip4_address_t * first_int_addr; + for (i = 0; i < vec_len (sm->to_resolve); i++) + { + rp = sm->to_resolve + i; + if (rp->sw_if_index != sw_if_index && + rp->l_addr.as_u32 != l_addr.as_u32 && + rp->vrf_id != vrf_id && rp->addr_only != addr_only) + continue; + + if (!addr_only) + { + if (rp->l_port != l_port && rp->e_port != e_port && rp->proto != proto) + continue; + } + + rp_match = rp; + break; + } + /* Might be already set... */ first_int_addr = ip4_interface_first_address (sm->ip4_main, sw_if_index, 0 /* just want the address*/); - /* DHCP resolution required? */ - if (first_int_addr == 0) + if (is_add) { + if (rp_match) + return VNET_API_ERROR_VALUE_EXIST; + snat_add_static_mapping_when_resolved (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto, addr_only, is_add, tag); - return 0; + + /* DHCP resolution required? */ + if (first_int_addr == 0) + { + return 0; + } + else + { + e_addr.as_u32 = first_int_addr->as_u32; + /* Identity mapping? */ + if (l_addr.as_u32 == 0) + l_addr.as_u32 = e_addr.as_u32; + } } - else + else { - e_addr.as_u32 = first_int_addr->as_u32; - /* Identity mapping? */ - if (l_addr.as_u32 == 0) - l_addr.as_u32 = e_addr.as_u32; + if (!rp_match) + return VNET_API_ERROR_NO_SUCH_ENTRY; + + vec_del1 (sm->to_resolve, i); + + if (first_int_addr) + { + e_addr.as_u32 = first_int_addr->as_u32; + /* Identity mapping? */ + if (l_addr.as_u32 == 0) + l_addr.as_u32 = e_addr.as_u32; + } + else + return 0; } } @@ -742,6 +812,17 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, vrf_id = sm->inside_vrf_id; } + if (!out2in_only) + { + m_key.addr = l_addr; + m_key.port = addr_only ? 0 : l_port; + m_key.protocol = addr_only ? 0 : proto; + m_key.fib_index = fib_index; + kv.key = m_key.as_u64; + if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value)) + return VNET_API_ERROR_VALUE_EXIST; + } + /* Find external address in allocated addresses and reserve port for address and port pair mapping when dynamic translations enabled */ if (!(addr_only || sm->static_mapping_only || out2in_only)) @@ -776,7 +857,26 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, } /* External address must be allocated */ if (!a && (l_addr.as_u32 != e_addr.as_u32)) - return VNET_API_ERROR_NO_SUCH_ENTRY; + { + if (sw_if_index != ~0) + { + for (i = 0; i < vec_len (sm->to_resolve); i++) + { + rp = sm->to_resolve + i; + if (rp->addr_only) + continue; + if (rp->sw_if_index != sw_if_index && + rp->l_addr.as_u32 != l_addr.as_u32 && + rp->vrf_id != vrf_id && rp->l_port != l_port && + rp->e_port != e_port && rp->proto != proto) + continue; + + vec_del1 (sm->to_resolve, i); + break; + } + } + return VNET_API_ERROR_NO_SUCH_ENTRY; + } } pool_get (sm->static_mappings, m); @@ -888,7 +988,12 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, else { if (!m) - return VNET_API_ERROR_NO_SUCH_ENTRY; + { + if (sw_if_index != ~0) + return 0; + else + return VNET_API_ERROR_NO_SUCH_ENTRY; + } /* Free external address port */ if (!(addr_only || sm->static_mapping_only || out2in_only)) @@ -986,6 +1091,9 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, continue; } + if (is_lb_session (s)) + continue; + nat_free_session_data (sm, s, tsm - sm->per_thread_data); clib_dlist_remove (tsm->list_pool, s->per_user_index); pool_put_index (tsm->list_pool, s->per_user_index); @@ -995,7 +1103,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, if (!addr_only) break; } - if (addr_only) + if (addr_only && (u->nstaticsessions == 0)) { pool_put (tsm->users, u); clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 0); @@ -1033,10 +1141,38 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, return 0; } +static int lb_local_exists (nat44_lb_addr_port_t * local, + ip4_address_t * e_addr, u16 e_port) +{ + snat_main_t *sm = &snat_main; + snat_static_mapping_t *m; + nat44_lb_addr_port_t *ap; + + /* *INDENT-OFF* */ + pool_foreach (m, sm->static_mappings, + ({ + if (vec_len(m->locals)) + { + if (m->external_port == e_port && m->external_addr.as_u32 == e_addr->as_u32) + continue; + + vec_foreach (ap, m->locals) + { + if (ap->port == local->port && ap->addr.as_u32 == local->addr.as_u32) + return 1; + } + } + })); + /* *INDENT-ON* */ + + return 0; +} + int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, snat_protocol_t proto, u32 vrf_id, nat44_lb_addr_port_t *locals, u8 is_add, - u8 twice_nat, u8 out2in_only, u8 *tag) + twice_nat_type_t twice_nat, u8 out2in_only, + u8 *tag) { snat_main_t * sm = &snat_main; snat_static_mapping_t *m; @@ -1073,7 +1209,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id, - FIB_SOURCE_PLUGIN_HI); + FIB_SOURCE_PLUGIN_LOW); /* Find external address in allocated addresses and reserve port for address and port pair mapping when dynamic translations enabled */ @@ -1186,7 +1322,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, if (!m) return VNET_API_ERROR_NO_SUCH_ENTRY; - fib_table_unlock (m->fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_HI); + fib_table_unlock (m->fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_LOW); /* Free external address port */ if (!(sm->static_mapping_only || out2in_only)) @@ -1253,12 +1389,15 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, } } - m_key.port = clib_host_to_net_u16 (local->port); - kv.key = m_key.as_u64; - if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 0)) + if (!lb_local_exists(local, &e_addr, e_port)) { - clib_warning ("in2out key del failed"); - return VNET_API_ERROR_UNSPECIFIED; + m_key.port = clib_host_to_net_u16 (local->port); + kv.key = m_key.as_u64; + if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 0)) + { + clib_warning ("in2out key del failed"); + return VNET_API_ERROR_UNSPECIFIED; + } } /* Delete sessions */ u_key.addr = local->addr; @@ -1280,6 +1419,9 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, elt = pool_elt_at_index (tsm->list_pool, elt->next); ses_index = elt->value; + if (!(is_lb_session (s))) + continue; + if ((s->in2out.addr.as_u32 != local->addr.as_u32) && (clib_net_to_host_u16 (s->in2out.port) != local->port)) continue; @@ -1354,7 +1496,7 @@ snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm, if (a->fib_index != ~0) fib_table_unlock(a->fib_index, FIB_PROTOCOL_IP4, - FIB_SOURCE_PLUGIN_HI); + FIB_SOURCE_PLUGIN_LOW); /* Delete sessions using address */ if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports) @@ -1428,6 +1570,12 @@ int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del) if (sm->out2in_dpo && !is_inside) return VNET_API_ERROR_UNSUPPORTED; + pool_foreach (i, sm->output_feature_interfaces, + ({ + if (i->sw_if_index == sw_if_index) + return VNET_API_ERROR_VALUE_EXIST; + })); + if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking)) feature_name = is_inside ? "nat44-in2out-fast" : "nat44-out2in-fast"; else @@ -1481,12 +1629,18 @@ int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del) sw_if_index, 0, 0, 0); vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, 0, 0); + if (!is_inside) + vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning", + sw_if_index, 1, 0, 0); } else { vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 0, 0, 0); pool_put (sm->interfaces, i); + if (is_inside) + vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning", + sw_if_index, 0, 0, 0); } } else @@ -1517,6 +1671,9 @@ int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del) sw_if_index, 0, 0, 0); vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, 0, 0); + if (!is_inside) + vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning", + sw_if_index, 0, 0, 0); goto set_flags; } @@ -1532,21 +1689,21 @@ int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del) i->flags = 0; vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, 0, 0); + if (is_inside && !sm->out2in_dpo) + vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning", + sw_if_index, 1, 0, 0); + set_flags: if (is_inside) - i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE; + { + i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE; + return 0; + } else i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE; /* Add/delete external addresses to FIB */ fib: - if (is_inside && !sm->out2in_dpo) - { - vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning", - sw_if_index, !is_del, 0, 0); - return 0; - } - vec_foreach (ap, sm->addresses) snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del); @@ -1579,6 +1736,12 @@ int snat_interface_add_del_output_feature (u32 sw_if_index, (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))) return VNET_API_ERROR_UNSUPPORTED; + pool_foreach (i, sm->interfaces, + ({ + if (i->sw_if_index == sw_if_index) + return VNET_API_ERROR_VALUE_EXIST; + })); + if (is_inside) { vnet_feature_enable_disable ("ip4-unicast", "nat44-hairpin-dst", @@ -1646,7 +1809,7 @@ fib: pool_foreach (m, sm->static_mappings, ({ - if (!(m->addr_only)) + if (!(m->addr_only) || (m->local_addr.as_u32 == m->external_addr.as_u32)) continue; snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del); @@ -1690,6 +1853,15 @@ snat_ip4_add_del_interface_address_cb (ip4_main_t * im, u32 if_address_index, u32 is_delete); +static void +nat_ip4_add_del_addr_only_sm_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 int nat_alloc_addr_and_port_default (snat_address_t * addresses, u32 fib_index, @@ -1768,6 +1940,11 @@ static clib_error_t * snat_init (vlib_main_t * vm) vec_add1 (im->add_del_interface_address_callbacks, cb4); + cb4.function = nat_ip4_add_del_addr_only_sm_cb; + cb4.function_opaque = 0; + + vec_add1 (im->add_del_interface_address_callbacks, cb4); + nat_dpo_module_init (); /* Init IPFIX logging */ @@ -1829,6 +2006,7 @@ void snat_free_outside_address_and_port (snat_address_t * addresses, * address. * @param is_addr_only If matched mapping is address only * @param twice_nat If matched mapping is twice NAT. + * @param lb If matched mapping is load-balanced. * * @returns 0 if match found otherwise 1. */ @@ -1837,7 +2015,8 @@ int snat_static_mapping_match (snat_main_t * sm, snat_session_key_t * mapping, u8 by_external, u8 *is_addr_only, - u8 *twice_nat) + twice_nat_type_t *twice_nat, + u8 *lb) { clib_bihash_kv_8_8_t kv, value; snat_static_mapping_t *m; @@ -1908,6 +2087,9 @@ int snat_static_mapping_match (snat_main_t * sm, if (PREDICT_FALSE(twice_nat != 0)) *twice_nat = m->twice_nat; + if (PREDICT_FALSE(lb != 0)) + *lb = vec_len (m->locals) > 0; + return 0; } @@ -2296,12 +2478,14 @@ static clib_error_t * snat_config (vlib_main_t * vm, unformat_input_t * input) { snat_main_t * sm = &snat_main; + nat66_main_t * nm = &nat66_main; u32 translation_buckets = 1024; u32 translation_memory_size = 128<<20; u32 user_buckets = 128; u32 user_memory_size = 64<<20; u32 max_translations_per_user = 100; u32 outside_vrf_id = 0; + u32 outside_ip6_vrf_id = 0; u32 inside_vrf_id = 0; u32 static_mapping_buckets = 1024; u32 static_mapping_memory_size = 64<<20; @@ -2334,6 +2518,9 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) 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)) ; @@ -2377,6 +2564,10 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, outside_vrf_id, FIB_SOURCE_PLUGIN_HI); + nm->outside_vrf_id = outside_ip6_vrf_id; + nm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, + outside_ip6_vrf_id, + FIB_SOURCE_PLUGIN_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, @@ -2569,10 +2760,13 @@ u8 * format_snat_static_mapping (u8 * s, va_list * args) nat44_lb_addr_port_t *local; if (m->addr_only) - s = format (s, "local %U external %U vrf %d %s", + s = format (s, "local %U external %U vrf %d %s %s", format_ip4_address, &m->local_addr, format_ip4_address, &m->external_addr, - m->vrf_id, m->twice_nat ? "twice-nat" : ""); + m->vrf_id, + m->twice_nat == TWICE_NAT ? "twice-nat" : + m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "", + m->out2in_only ? "out2in-only" : ""); else { if (vec_len (m->locals)) @@ -2581,7 +2775,8 @@ u8 * format_snat_static_mapping (u8 * s, va_list * args) format_snat_protocol, m->proto, m->vrf_id, format_ip4_address, &m->external_addr, m->external_port, - m->twice_nat ? "twice-nat" : "", + m->twice_nat == TWICE_NAT ? "twice-nat" : + m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "", m->out2in_only ? "out2in-only" : ""); vec_foreach (local, m->locals) s = format (s, "\n local %U:%d probability %d\%", @@ -2593,7 +2788,9 @@ u8 * format_snat_static_mapping (u8 * s, va_list * args) format_snat_protocol, m->proto, format_ip4_address, &m->local_addr, m->local_port, format_ip4_address, &m->external_addr, m->external_port, - m->vrf_id, m->twice_nat ? "twice-nat" : "", + m->vrf_id, + m->twice_nat == TWICE_NAT ? "twice-nat" : + m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "", m->out2in_only ? "out2in-only" : ""); } return s; @@ -2648,6 +2845,77 @@ u8 * format_det_map_ses (u8 * s, va_list * args) return s; } +static void +nat_ip4_add_del_addr_only_sm_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_main_t *sm = &snat_main; + snat_static_map_resolve_t *rp; + snat_static_mapping_t *m; + snat_session_key_t m_key; + clib_bihash_kv_8_8_t kv, value; + int i, rv; + ip4_address_t l_addr; + + for (i = 0; i < vec_len (sm->to_resolve); i++) + { + rp = sm->to_resolve + i; + if (rp->addr_only == 0) + continue; + if (rp->sw_if_index == sw_if_index) + goto match; + } + + return; + +match: + m_key.addr.as_u32 = address->as_u32; + m_key.port = rp->addr_only ? 0 : rp->e_port; + m_key.protocol = rp->addr_only ? 0 : rp->proto; + m_key.fib_index = sm->outside_fib_index; + kv.key = m_key.as_u64; + if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value)) + m = 0; + else + m = pool_elt_at_index (sm->static_mappings, value.value); + + if (!is_delete) + { + /* Don't trip over lease renewal, static config */ + if (m) + return; + } + else + { + if (!m) + return; + } + + /* Indetity mapping? */ + if (rp->l_addr.as_u32 == 0) + l_addr.as_u32 = address[0].as_u32; + else + l_addr.as_u32 = rp->l_addr.as_u32; + /* Add the static mapping */ + rv = snat_add_static_mapping (l_addr, + address[0], + rp->l_port, + rp->e_port, + rp->vrf_id, + rp->addr_only, + ~0 /* sw_if_index */, + rp->proto, + !is_delete, + 0, 0, rp->tag); + if (rv) + clib_warning ("snat_add_static_mapping returned %d", rv); +} + static void snat_ip4_add_del_interface_address_cb (ip4_main_t * im, uword opaque, @@ -2659,7 +2927,6 @@ snat_ip4_add_del_interface_address_cb (ip4_main_t * im, { snat_main_t *sm = &snat_main; snat_static_map_resolve_t *rp; - u32 *indices_to_delete = 0; ip4_address_t l_addr; int i, j; int rv; @@ -2695,6 +2962,8 @@ match: for (j = 0; j < vec_len (sm->to_resolve); j++) { rp = sm->to_resolve + j; + if (rp->addr_only) + continue; /* On this interface? */ if (rp->sw_if_index == sw_if_index) { @@ -2717,18 +2986,8 @@ match: if (rv) clib_warning ("snat_add_static_mapping returned %d", rv); - vec_free (rp->tag); - vec_add1 (indices_to_delete, j); } } - /* If we resolved any of the outstanding static mappings */ - if (vec_len(indices_to_delete)) - { - /* Delete them */ - for (j = vec_len(indices_to_delete)-1; j >= 0; j--) - vec_delete(sm->to_resolve, 1, j); - vec_free(indices_to_delete); - } return; } else @@ -2820,7 +3079,7 @@ nat44_del_session (snat_main_t *sm, ip4_address_t *addr, u16 port, snat_user_t *u; ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32; - if (sm->num_workers) + if (sm->num_workers > 1) tsm = vec_elt_at_index (sm->per_thread_data, sm->worker_in2out_cb (&ip, fib_index));