nat: remove nat44-ed relation between SM and addr 85/34485/10
authorFilip Varga <fivarga@cisco.com>
Fri, 12 Nov 2021 16:22:11 +0000 (17:22 +0100)
committerOle Tr�an <otroan@employees.org>
Tue, 4 Jan 2022 12:06:00 +0000 (12:06 +0000)
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>
src/plugins/nat/nat44-ed/nat44_ed.c
src/plugins/nat/nat44-ed/nat44_ed.h
src/plugins/nat/nat44-ed/nat44_ed_api.c
src/plugins/nat/nat44-ed/nat44_ed_cli.c
src/plugins/nat/nat44-ed/nat44_ed_format.c
src/plugins/nat/nat44-ed/nat44_ed_in2out.c

index 7907d8f..d3ef3d5 100644 (file)
@@ -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
index d8cc0d3..9772f1e 100644 (file)
@@ -63,10 +63,6 @@ typedef enum nat44_config_flags_t_
 
 typedef struct
 {
-  /* nat44 plugin features */
-  u8 static_mapping_only;
-  u8 connection_tracking;
-
   u32 inside_vrf;
   u32 outside_vrf;
 
@@ -450,6 +446,7 @@ typedef struct
 
 typedef struct
 {
+  u8 is_resolved;
   ip4_address_t l_addr;
   ip4_address_t pool_addr;
   u16 l_port;
@@ -459,7 +456,21 @@ typedef struct
   ip_protocol_t proto;
   u32 flags;
   u8 *tag;
-} snat_static_map_resolve_t;
+} snat_static_mapping_resolve_t;
+
+typedef struct
+{
+  u8 is_resolved;
+  u8 is_twice_nat;
+  u32 sw_if_index;
+} snat_address_resolve_t;
+
+typedef struct
+{
+  u32 count;
+  u32 sw_if_index;
+  ip4_address_t addr;
+} snat_fib_entry_reg_t;
 
 typedef struct
 {
@@ -533,9 +544,8 @@ typedef struct snat_main_s
   /* Vector of twice NAT addresses for external hosts */
   snat_address_t *twice_nat_addresses;
 
-  /* sw_if_indices whose intfc addresses should be auto-added */
-  u32 *auto_add_sw_if_indices;
-  u32 *auto_add_sw_if_indices_twice_nat;
+  /* first interface address should be auto-added */
+  snat_address_resolve_t *addr_to_resolve;
 
   /* Address and port allocation function */
   nat_alloc_out_addr_and_port_function_t *alloc_addr_and_port;
@@ -555,8 +565,11 @@ typedef struct snat_main_s
   /* vector of outside fibs */
   nat_outside_fib_t *outside_fibs;
 
+  /* vector of fib entries */
+  snat_fib_entry_reg_t *fib_entry_reg;
+
   /* vector of interface address static mappings to resolve. */
-  snat_static_map_resolve_t *to_resolve;
+  snat_static_mapping_resolve_t *sm_to_resolve;
 
   /* Randomize port allocation order */
   u32 random_seed;
@@ -576,10 +589,6 @@ typedef struct snat_main_s
   /* If forwarding is enabled */
   u8 forwarding_enabled;
 
-  /* static mapping config */
-  u8 static_mapping_only;
-  u8 static_mapping_connection_tracking;
-
   /* Is translation memory size calculated or user defined */
   u8 translation_memory_size_set;
 
@@ -651,9 +660,6 @@ typedef struct snat_main_s
   fib_source_t fib_src_hi;
   fib_source_t fib_src_low;
 
-  /* pat - dynamic mapping enabled or conneciton tracking */
-  u8 pat;
-
   /* number of worker handoff frame queue elements */
   u32 frame_queue_nelts;
 
@@ -876,7 +882,7 @@ int nat44_ed_add_output_interface (u32 sw_if_index);
 int nat44_ed_del_output_interface (u32 sw_if_index);
 
 int nat44_ed_add_address (ip4_address_t *addr, u32 vrf_id, u8 twice_nat);
-int nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat);
+int nat44_ed_del_address (ip4_address_t addr, u8 twice_nat);
 int nat44_ed_add_interface_address (u32 sw_if_index, u8 twice_nat);
 int nat44_ed_del_interface_address (u32 sw_if_index, u8 twice_nat);
 
index 6b76967..4664fab 100644 (file)
@@ -47,15 +47,19 @@ vl_api_nat44_ed_plugin_enable_disable_t_handler (
 
   if (mp->enable)
     {
-      c.static_mapping_only = mp->flags & NAT44_API_IS_STATIC_MAPPING_ONLY;
-      c.connection_tracking = mp->flags & NAT44_API_IS_CONNECTION_TRACKING;
-
-      c.inside_vrf = ntohl (mp->inside_vrf);
-      c.outside_vrf = ntohl (mp->outside_vrf);
-
-      c.sessions = ntohl (mp->sessions);
+      if ((mp->flags & NAT44_API_IS_STATIC_MAPPING_ONLY) ||
+         (mp->flags & NAT44_API_IS_CONNECTION_TRACKING))
+       {
+         rv = VNET_API_ERROR_UNSUPPORTED;
+       }
+      else
+       {
+         c.sessions = ntohl (mp->sessions);
+         c.inside_vrf = ntohl (mp->inside_vrf);
+         c.outside_vrf = ntohl (mp->outside_vrf);
 
-      rv = nat44_plugin_enable (c);
+         rv = nat44_plugin_enable (c);
+       }
     }
   else
     {
@@ -275,12 +279,6 @@ static void
   int rv = 0;
   u32 *tmp;
 
-  if (sm->static_mapping_only)
-    {
-      rv = VNET_API_ERROR_FEATURE_DISABLED;
-      goto send_reply;
-    }
-
   is_add = mp->is_add;
   twice_nat = mp->flags & NAT_API_IS_TWICE_NAT;
 
@@ -308,7 +306,7 @@ static void
        }
       else
        {
-         rv = nat44_ed_del_address (this_addr, 0, twice_nat);
+         rv = nat44_ed_del_address (this_addr, twice_nat);
        }
 
       if (rv)
@@ -821,9 +819,8 @@ send_nat44_static_mapping_details (snat_static_mapping_t * m,
 }
 
 static void
-send_nat44_static_map_resolve_details (snat_static_map_resolve_t * m,
-                                      vl_api_registration_t * reg,
-                                      u32 context)
+send_nat44_static_map_resolve_details (snat_static_mapping_resolve_t *m,
+                                      vl_api_registration_t *reg, u32 context)
 {
   vl_api_nat44_static_mapping_details_t *rmp;
   snat_main_t *sm = &snat_main;
@@ -866,7 +863,7 @@ vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
   vl_api_registration_t *reg;
   snat_main_t *sm = &snat_main;
   snat_static_mapping_t *m;
-  snat_static_map_resolve_t *rp;
+  snat_static_mapping_resolve_t *rp;
   int j;
 
   reg = vl_api_client_index_to_registration (mp->client_index);
@@ -879,9 +876,9 @@ vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
        send_nat44_static_mapping_details (m, reg, mp->context);
   }
 
-  for (j = 0; j < vec_len (sm->to_resolve); j++)
+  for (j = 0; j < vec_len (sm->sm_to_resolve); j++)
     {
-      rp = sm->to_resolve + j;
+      rp = sm->sm_to_resolve + j;
       if (!is_sm_identity_nat (rp->flags))
        send_nat44_static_map_resolve_details (rp, reg, mp->context);
     }
@@ -973,8 +970,8 @@ send_nat44_identity_mapping_details (snat_static_mapping_t * m, int index,
 }
 
 static void
-send_nat44_identity_map_resolve_details (snat_static_map_resolve_t * m,
-                                        vl_api_registration_t * reg,
+send_nat44_identity_map_resolve_details (snat_static_mapping_resolve_t *m,
+                                        vl_api_registration_t *reg,
                                         u32 context)
 {
   vl_api_nat44_identity_mapping_details_t *rmp;
@@ -1006,7 +1003,7 @@ static void
   vl_api_registration_t *reg;
   snat_main_t *sm = &snat_main;
   snat_static_mapping_t *m;
-  snat_static_map_resolve_t *rp;
+  snat_static_mapping_resolve_t *rp;
   int j;
 
   reg = vl_api_client_index_to_registration (mp->client_index);
@@ -1024,9 +1021,9 @@ static void
        }
     }
 
-  for (j = 0; j < vec_len (sm->to_resolve); j++)
+  for (j = 0; j < vec_len (sm->sm_to_resolve); j++)
     {
-      rp = sm->to_resolve + j;
+      rp = sm->sm_to_resolve + j;
       if (is_sm_identity_nat (rp->flags))
        send_nat44_identity_map_resolve_details (rp, reg, mp->context);
     }
@@ -1042,12 +1039,6 @@ static void
   u8 twice_nat;
   int rv = 0;
 
-  if (sm->static_mapping_only)
-    {
-      rv = VNET_API_ERROR_FEATURE_DISABLED;
-      goto send_reply;
-    }
-
   VALIDATE_SW_IF_INDEX (mp);
 
   twice_nat = mp->flags & NAT_API_IS_TWICE_NAT;
@@ -1063,7 +1054,6 @@ static void
 
   BAD_SW_IF_INDEX_LABEL;
 
-send_reply:
   REPLY_MACRO (VL_API_NAT44_ADD_DEL_INTERFACE_ADDR_REPLY);
 }
 
@@ -1092,21 +1082,18 @@ static void
 vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t
                                            * mp)
 {
-  vl_api_registration_t *reg;
   snat_main_t *sm = &snat_main;
-  u32 *i;
+  vl_api_registration_t *reg;
+  snat_address_resolve_t *ap;
 
   reg = vl_api_client_index_to_registration (mp->client_index);
   if (!reg)
     return;
 
-  vec_foreach (i, sm->auto_add_sw_if_indices)
-    {
-      send_nat44_interface_addr_details (*i, reg, mp->context, 0);
-    }
-  vec_foreach (i, sm->auto_add_sw_if_indices_twice_nat)
+  vec_foreach (ap, sm->addr_to_resolve)
     {
-      send_nat44_interface_addr_details (*i, reg, mp->context, 1);
+      send_nat44_interface_addr_details (ap->sw_if_index, reg, mp->context,
+                                        ap->is_twice_nat);
     }
 }
 
@@ -1446,20 +1433,18 @@ vl_api_nat44_plugin_enable_disable_t_handler (
 
   if (mp->enable)
     {
-      if (mp->users || mp->user_sessions)
+      if ((mp->flags & NAT44_API_IS_STATIC_MAPPING_ONLY) ||
+         (mp->flags & NAT44_API_IS_CONNECTION_TRACKING) || mp->users ||
+         mp->user_sessions)
        {
          rv = VNET_API_ERROR_UNSUPPORTED;
        }
       else
        {
-         c.static_mapping_only = mp->flags & NAT44_API_IS_STATIC_MAPPING_ONLY;
-         c.connection_tracking = mp->flags & NAT44_API_IS_CONNECTION_TRACKING;
-
+         c.sessions = ntohl (mp->sessions);
          c.inside_vrf = ntohl (mp->inside_vrf);
          c.outside_vrf = ntohl (mp->outside_vrf);
 
-         c.sessions = ntohl (mp->sessions);
-
          rv = nat44_plugin_enable (c);
        }
     }
@@ -1496,9 +1481,8 @@ vl_api_nat_show_config_t_handler (vl_api_nat_show_config_t *mp)
                       rmp->max_translations_per_user = 0;
                       rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
                       rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
-                      rmp->static_mapping_only = sm->static_mapping_only;
-                      rmp->static_mapping_connection_tracking =
-                        sm->static_mapping_connection_tracking;
+                      rmp->static_mapping_only = 0;
+                      rmp->static_mapping_connection_tracking = 0;
                       rmp->endpoint_dependent = 1;
                       rmp->out2in_dpo = 0;
                     }));
@@ -1518,9 +1502,8 @@ vl_api_nat_show_config_2_t_handler (vl_api_nat_show_config_2_t *mp)
       rmp->max_translations_per_user = 0;
       rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
       rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
-      rmp->static_mapping_only = sm->static_mapping_only;
-      rmp->static_mapping_connection_tracking =
-       sm->static_mapping_connection_tracking;
+      rmp->static_mapping_only = 0;
+      rmp->static_mapping_connection_tracking = 0;
       rmp->endpoint_dependent = 1;
       rmp->out2in_dpo = 0;
       rmp->max_translations_per_thread =
@@ -1560,10 +1543,6 @@ vl_api_nat44_show_running_config_t_handler (
       // consider how to split functionality between subplugins
       rmp->ipfix_logging_enabled = nat_ipfix_logging_enabled ();
       rmp->flags |= NAT44_IS_ENDPOINT_DEPENDENT;
-      if (rc->static_mapping_only)
-       rmp->flags |= NAT44_IS_STATIC_MAPPING_ONLY;
-      if (rc->connection_tracking)
-       rmp->flags |= NAT44_IS_CONNECTION_TRACKING;
     }));
 }
 
index 9743ce6..cfd3627 100644 (file)
@@ -38,23 +38,15 @@ nat44_ed_enable_disable_command_fn (vlib_main_t *vm, unformat_input_t *input,
   clib_error_t *error = 0;
 
   nat44_config_t c = { 0 };
-  u8 enable_set = 0, enable = 0, mode_set = 0;
+  u8 enable_set = 0, enable = 0;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
 
   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 (unformat (line_input, "inside-vrf %u", &c.inside_vrf));
+      if (unformat (line_input, "inside-vrf %u", &c.inside_vrf))
+       ;
       else if (unformat (line_input, "outside-vrf %u", &c.outside_vrf));
       else if (unformat (line_input, "sessions %u", &c.sessions));
       else if (!enable_set)
@@ -350,7 +342,6 @@ add_address_command_fn (vlib_main_t * vm,
                        unformat_input_t * input, vlib_cli_command_t * cmd)
 {
   unformat_input_t _line_input, *line_input = &_line_input;
-  snat_main_t *sm = &snat_main;
   ip4_address_t start_addr, end_addr, this_addr;
   u32 start_host_order, end_host_order;
   u32 vrf_id = ~0;
@@ -386,12 +377,6 @@ add_address_command_fn (vlib_main_t * vm,
        }
     }
 
-  if (sm->static_mapping_only)
-    {
-      error = clib_error_return (0, "static mapping only mode");
-      goto done;
-    }
-
   start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
   end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
 
@@ -418,7 +403,7 @@ add_address_command_fn (vlib_main_t * vm,
        }
       else
        {
-         rv = nat44_ed_del_address (this_addr, 0, twice_nat);
+         rv = nat44_ed_del_address (this_addr, twice_nat);
        }
 
       switch (rv)
@@ -1279,14 +1264,14 @@ nat44_show_static_mappings_command_fn (vlib_main_t * vm,
 {
   snat_main_t *sm = &snat_main;
   snat_static_mapping_t *m;
-  snat_static_map_resolve_t *rp;
+  snat_static_mapping_resolve_t *rp;
 
   vlib_cli_output (vm, "NAT44 static mappings:");
   pool_foreach (m, sm->static_mappings)
    {
     vlib_cli_output (vm, " %U", format_snat_static_mapping, m);
   }
-  vec_foreach (rp, sm->to_resolve)
+  vec_foreach (rp, sm->sm_to_resolve)
     vlib_cli_output (vm, " %U", format_snat_static_map_to_resolve, rp);
 
   return 0;
@@ -1358,21 +1343,14 @@ nat44_show_interface_address_command_fn (vlib_main_t * vm,
 {
   snat_main_t *sm = &snat_main;
   vnet_main_t *vnm = vnet_get_main ();
-  u32 *sw_if_index;
+  snat_address_resolve_t *ap;
 
   vlib_cli_output (vm, "NAT44 pool address interfaces:");
-  vec_foreach (sw_if_index, sm->auto_add_sw_if_indices)
+  vec_foreach (ap, sm->addr_to_resolve)
     {
-      vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm,
-                       *sw_if_index);
+      vlib_cli_output (vm, " %U%s", format_vnet_sw_if_index_name, vnm,
+                      ap->sw_if_index, ap->is_twice_nat ? " twice-nat" : "");
     }
-  vlib_cli_output (vm, "NAT44 twice-nat pool address interfaces:");
-  vec_foreach (sw_if_index, sm->auto_add_sw_if_indices_twice_nat)
-    {
-      vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm,
-                       *sw_if_index);
-    }
-
   return 0;
 }
 
@@ -1737,16 +1715,13 @@ done:
  *  vpp# nat44 enable
  * To disable nat44-ed, use:
  *  vpp# nat44 disable
- * To enable nat44-ed static mapping with connection tracking, use:
- *  vpp# nat44-ed enable static-mapping connection-tracking
  * To set inside-vrf outside-vrf, use:
  *  vpp# nat44 enable inside-vrf <id> outside-vrf <id>
  * @cliexend
 ?*/
 VLIB_CLI_COMMAND (nat44_ed_enable_disable_command, static) = {
   .path = "nat44",
-  .short_help = "nat44 <enable [sessions <max-number>] [static-mapping-only "
-               "connection-tracking] [inside-vrf <vrf-id>] "
+  .short_help = "nat44 <enable [sessions <max-number>] [inside-vrf <vrf-id>] "
                "[outside-vrf <vrf-id>]>|disable",
   .function = nat44_ed_enable_disable_command_fn,
 };
index 81e743f..a6f6302 100644 (file)
@@ -188,7 +188,8 @@ format_snat_static_mapping (u8 * s, va_list * args)
 u8 *
 format_snat_static_map_to_resolve (u8 * s, va_list * args)
 {
-  snat_static_map_resolve_t *m = va_arg (*args, snat_static_map_resolve_t *);
+  snat_static_mapping_resolve_t *m =
+    va_arg (*args, snat_static_mapping_resolve_t *);
   vnet_main_t *vnm = vnet_get_main ();
 
   if (is_sm_addr_only (m->flags))
index e93198a..23e0957 100644 (file)
@@ -278,7 +278,7 @@ nat_ed_alloc_addr_and_port (snat_main_t *sm, u32 rx_fib_index,
        }
       else
        {
-         // frist try nat pool addresses to sw interface addreses mappings
+         // first try nat pool addresses to sw interface addreses mappings
          for (i = s_addr_offset; i < vec_len (sm->addresses); ++i)
            {
              a = sm->addresses + i;