+ continue;
+ }
+ if (ses->out2in.addr.as_u32 == addr.as_u32)
+ {
+ nat44_ed_free_session_data (sm, ses, tsm - sm->per_thread_data,
+ 0);
+ vec_add1 (ses_to_be_removed, ses - tsm->sessions);
+ }
+ }
+ vec_foreach (ses_index, ses_to_be_removed)
+ {
+ ses = pool_elt_at_index (tsm->sessions, ses_index[0]);
+ nat_ed_session_delete (sm, ses, tsm - sm->per_thread_data, 1);
+ }
+ vec_free (ses_to_be_removed);
+ }
+
+ if (!twice_nat)
+ {
+ nat44_ed_add_del_interface_fib_reg_entries (addr, 0);
+ }
+
+ if (a->fib_index != ~0)
+ {
+ fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low);
+ }
+
+ if (!twice_nat)
+ {
+ vec_del1 (sm->addresses, j);
+ }
+ else
+ {
+ vec_del1 (sm->twice_nat_addresses, j);
+ }
+
+ return 0;
+}
+
+u32
+get_thread_idx_by_port (u16 e_port)
+{
+ snat_main_t *sm = &snat_main;
+ u32 thread_idx = sm->num_workers;
+ if (sm->num_workers > 1)
+ {
+ thread_idx =
+ sm->first_worker_index +
+ sm->workers[(e_port - 1024) / sm->port_per_thread];
+ }
+ return thread_idx;
+}
+
+void
+nat_ed_static_mapping_del_sessions (snat_main_t * sm,
+ snat_main_per_thread_data_t * tsm,
+ ip4_address_t l_addr,
+ u16 l_port,
+ u8 protocol,
+ u32 fib_index, int addr_only,
+ ip4_address_t e_addr, u16 e_port)
+{
+ snat_session_t *s;
+ u32 *indexes_to_free = NULL;
+ pool_foreach (s, tsm->sessions) {
+ if (s->in2out.fib_index != fib_index ||
+ s->in2out.addr.as_u32 != l_addr.as_u32)
+ {
+ continue;
+ }
+ if (!addr_only)
+ {
+ if ((s->out2in.addr.as_u32 != e_addr.as_u32) ||
+ s->out2in.port != e_port || s->in2out.port != l_port ||
+ s->proto != protocol)
+ continue;
+ }
+
+ if (nat44_ed_is_lb_session (s))
+ continue;
+ if (!nat44_ed_is_session_static (s))
+ continue;
+ nat44_ed_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
+ vec_add1 (indexes_to_free, s - tsm->sessions);
+ if (!addr_only)
+ break;
+ }
+ u32 *ses_index;
+ vec_foreach (ses_index, indexes_to_free)
+ {
+ s = pool_elt_at_index (tsm->sessions, *ses_index);
+ nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1);
+ }
+ vec_free (indexes_to_free);
+}
+
+static_always_inline snat_static_mapping_t *
+nat44_ed_sm_lookup (snat_main_t *sm, clib_bihash_kv_16_8_t *kv)
+{
+ clib_bihash_kv_16_8_t v;
+ int rc = clib_bihash_search_16_8 (&sm->flow_hash, kv, &v);
+ if (!rc)
+ {
+ ASSERT (0 == ed_value_get_thread_index (&v));
+ return pool_elt_at_index (sm->static_mappings,
+ ed_value_get_session_index (&v));
+ }
+ return NULL;
+}
+
+snat_static_mapping_t *
+nat44_ed_sm_o2i_lookup (snat_main_t *sm, ip4_address_t addr, u16 port,
+ u32 fib_index, u8 proto)
+{
+ clib_bihash_kv_16_8_t kv;
+ nat44_ed_sm_init_o2i_k (&kv, addr.as_u32, port, fib_index, proto);
+ return nat44_ed_sm_lookup (sm, &kv);
+}
+
+snat_static_mapping_t *
+nat44_ed_sm_i2o_lookup (snat_main_t *sm, ip4_address_t addr, u16 port,
+ u32 fib_index, u8 proto)
+{
+ clib_bihash_kv_16_8_t kv;
+ nat44_ed_sm_init_i2o_k (&kv, addr.as_u32, port, fib_index, proto);
+ return nat44_ed_sm_lookup (sm, &kv);
+}
+
+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_idx)
+{
+ snat_static_mapping_resolve_t *rp;
+ snat_main_t *sm = &snat_main;
+ int i;
+
+ for (i = 0; i < vec_len (sm->sm_to_resolve); i++)
+ {
+ rp = sm->sm_to_resolve + i;
+
+ if (rp->sw_if_index == sw_if_index && rp->vrf_id == vrf_id)
+ {
+ if (is_sm_identity_nat (rp->flags) && is_sm_identity_nat (flags))
+ {
+ if (!(is_sm_addr_only (rp->flags) && is_sm_addr_only (flags)))