nat: move deterministic nat to det44 sub feature
[vpp.git] / src / plugins / nat / nat.c
index ed01bb4..ea1add6 100644 (file)
@@ -22,9 +22,7 @@
 #include <nat/nat.h>
 #include <nat/nat_dpo.h>
 #include <nat/nat_ipfix_logging.h>
-#include <nat/nat_det.h>
 #include <nat/nat64.h>
-#include <nat/nat66.h>
 #include <nat/nat_inlines.h>
 #include <nat/nat44/inlines.h>
 #include <nat/nat_affinity.h>
@@ -85,22 +83,6 @@ VNET_FEATURE_INIT (ip4_nat_classify, static) = {
   .node_name = "nat44-classify",
   .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
 };
-VNET_FEATURE_INIT (ip4_snat_det_in2out, static) = {
-  .arc_name = "ip4-unicast",
-  .node_name = "nat44-det-in2out",
-  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
-};
-VNET_FEATURE_INIT (ip4_snat_det_out2in, static) = {
-  .arc_name = "ip4-unicast",
-  .node_name = "nat44-det-out2in",
-  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature",
-                               "ip4-dhcp-client-detect"),
-};
-VNET_FEATURE_INIT (ip4_nat_det_classify, static) = {
-  .arc_name = "ip4-unicast",
-  .node_name = "nat44-det-classify",
-  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
-};
 VNET_FEATURE_INIT (ip4_nat44_ed_in2out, static) = {
   .arc_name = "ip4-unicast",
   .node_name = "nat44-ed-in2out",
@@ -338,7 +320,7 @@ nat44_set_session_limit (u32 session_limit, u32 vrf_id)
       vec_validate (sm->max_translations_per_fib, fib_index + 1);
 
       for (; len < vec_len (sm->max_translations_per_fib); len++)
-       sm->max_translations_per_fib[len] = sm->max_translations;
+       sm->max_translations_per_fib[len] = sm->max_translations_per_thread;
     }
 
   sm->max_translations_per_fib[fib_index] = session_limit;
@@ -485,6 +467,13 @@ nat_user_get_or_create (snat_main_t * sm, ip4_address_t * addr, u32 fib_index,
   /* Ever heard of the "user" = src ip4 address before? */
   if (clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
     {
+      if (pool_elts (tsm->users) >= sm->max_users_per_thread)
+       {
+         vlib_increment_simple_counter (&sm->user_limit_reached,
+                                        thread_index, 0, 1);
+         nat_elog_warn ("maximum user limit reached");
+         return NULL;
+       }
       /* no, make a new one */
       pool_get (tsm->users, u);
       clib_memset (u, 0, sizeof (*u));
@@ -1791,6 +1780,40 @@ snat_del_address (snat_main_t * sm, ip4_address_t addr, u8 delete_sm,
   return 0;
 }
 
+static void
+nat_validate_counters (snat_main_t * sm, u32 sw_if_index)
+{
+#define _(x)                                                                  \
+  vlib_validate_simple_counter (&sm->counters.fastpath.in2out.x,              \
+                                sw_if_index);                                 \
+  vlib_zero_simple_counter (&sm->counters.fastpath.in2out.x, sw_if_index);    \
+  vlib_validate_simple_counter (&sm->counters.fastpath.out2in.x,              \
+                                sw_if_index);                                 \
+  vlib_zero_simple_counter (&sm->counters.fastpath.out2in.x, sw_if_index);    \
+  vlib_validate_simple_counter (&sm->counters.slowpath.in2out.x,              \
+                                sw_if_index);                                 \
+  vlib_zero_simple_counter (&sm->counters.slowpath.in2out.x, sw_if_index);    \
+  vlib_validate_simple_counter (&sm->counters.slowpath.out2in.x,              \
+                                sw_if_index);                                 \
+  vlib_zero_simple_counter (&sm->counters.slowpath.out2in.x, sw_if_index);    \
+  vlib_validate_simple_counter (&sm->counters.fastpath.in2out_ed.x,           \
+                                sw_if_index);                                 \
+  vlib_zero_simple_counter (&sm->counters.fastpath.in2out_ed.x, sw_if_index); \
+  vlib_validate_simple_counter (&sm->counters.fastpath.out2in_ed.x,           \
+                                sw_if_index);                                 \
+  vlib_zero_simple_counter (&sm->counters.fastpath.out2in_ed.x, sw_if_index); \
+  vlib_validate_simple_counter (&sm->counters.slowpath.in2out_ed.x,           \
+                                sw_if_index);                                 \
+  vlib_zero_simple_counter (&sm->counters.slowpath.in2out_ed.x, sw_if_index); \
+  vlib_validate_simple_counter (&sm->counters.slowpath.out2in_ed.x,           \
+                                sw_if_index);                                 \
+  vlib_zero_simple_counter (&sm->counters.slowpath.out2in_ed.x, sw_if_index);
+  foreach_nat_counter;
+#undef _
+  vlib_validate_simple_counter (&sm->counters.hairpinning, sw_if_index);
+  vlib_zero_simple_counter (&sm->counters.hairpinning, sw_if_index);
+}
+
 int
 snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
 {
@@ -1799,7 +1822,6 @@ snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
   const char *feature_name, *del_feature_name;
   snat_address_t *ap;
   snat_static_mapping_t *m;
-  snat_det_map_t *dm;
   nat_outside_fib_t *outside_fib;
   u32 fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
                                                       sw_if_index);
@@ -1819,12 +1841,10 @@ snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
     feature_name = is_inside ? "nat44-in2out-fast" : "nat44-out2in-fast";
   else
     {
-      if (sm->num_workers > 1 && !sm->deterministic)
+      if (sm->num_workers > 1)
        feature_name =
          is_inside ? "nat44-in2out-worker-handoff" :
          "nat44-out2in-worker-handoff";
-      else if (sm->deterministic)
-       feature_name = is_inside ? "nat44-det-in2out" : "nat44-det-out2in";
       else if (sm->endpoint_dependent)
        {
          feature_name = is_inside ? "nat-pre-in2out" : "nat-pre-out2in";
@@ -1833,11 +1853,11 @@ snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
        feature_name = is_inside ? "nat44-in2out" : "nat44-out2in";
     }
 
-  if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
+  if (sm->fq_in2out_index == ~0 && sm->num_workers > 1)
     sm->fq_in2out_index =
       vlib_frame_queue_main_init (sm->in2out_node_index, NAT_FQ_NELTS);
 
-  if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
+  if (sm->fq_out2in_index == ~0 && sm->num_workers > 1)
     sm->fq_out2in_index =
       vlib_frame_queue_main_init (sm->out2in_node_index, NAT_FQ_NELTS);
 
@@ -1882,18 +1902,12 @@ feature_set:
                 else
                   i->flags &= ~NAT_INTERFACE_FLAG_IS_OUTSIDE;
 
-                if (sm->num_workers > 1 && !sm->deterministic)
+                if (sm->num_workers > 1)
                   {
                     del_feature_name = "nat44-handoff-classify";
                     feature_name = !is_inside ?  "nat44-in2out-worker-handoff" :
                                                  "nat44-out2in-worker-handoff";
                   }
-                else if (sm->deterministic)
-                  {
-                    del_feature_name = "nat44-det-classify";
-                    feature_name = !is_inside ?  "nat44-det-in2out" :
-                                                 "nat44-det-out2in";
-                  }
                 else if (sm->endpoint_dependent)
                   {
                     del_feature_name = "nat44-ed-classify";
@@ -1919,7 +1933,7 @@ feature_set:
                       vnet_feature_enable_disable ("ip4-local",
                                                    "nat44-ed-hairpinning",
                                                    sw_if_index, 1, 0, 0);
-                    else if (!sm->deterministic)
+                    else
                       vnet_feature_enable_disable ("ip4-local",
                                                    "nat44-hairpinning",
                                                    sw_if_index, 1, 0, 0);
@@ -1939,7 +1953,7 @@ feature_set:
                       vnet_feature_enable_disable ("ip4-local",
                                                    "nat44-ed-hairpinning",
                                                    sw_if_index, 0, 0, 0);
-                    else if (!sm->deterministic)
+                    else
                       vnet_feature_enable_disable ("ip4-local",
                                                    "nat44-hairpinning",
                                                    sw_if_index, 0, 0, 0);
@@ -1952,18 +1966,12 @@ feature_set:
                 (nat_interface_is_outside(i) && !is_inside))
               return 0;
 
-            if (sm->num_workers > 1 && !sm->deterministic)
+            if (sm->num_workers > 1)
               {
                 del_feature_name = !is_inside ?  "nat44-in2out-worker-handoff" :
                                                  "nat44-out2in-worker-handoff";
                 feature_name = "nat44-handoff-classify";
               }
-            else if (sm->deterministic)
-              {
-                del_feature_name = !is_inside ?  "nat44-det-in2out" :
-                                                 "nat44-det-out2in";
-                feature_name = "nat44-det-classify";
-              }
             else if (sm->endpoint_dependent)
               {
                 del_feature_name = !is_inside ?  "nat-pre-in2out" :
@@ -1989,7 +1997,7 @@ feature_set:
                 if (sm->endpoint_dependent)
                   vnet_feature_enable_disable ("ip4-local", "nat44-ed-hairpinning",
                                                sw_if_index, 0, 0, 0);
-                else if (!sm->deterministic)
+                else
                   vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
                                                sw_if_index, 0, 0, 0);
               }
@@ -2007,6 +2015,8 @@ feature_set:
   pool_get (sm->interfaces, i);
   i->sw_if_index = sw_if_index;
   i->flags = 0;
+  nat_validate_counters (sm, sw_if_index);
+
   vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, 0,
                               0);
 
@@ -2019,7 +2029,7 @@ feature_set:
       if (sm->endpoint_dependent)
        vnet_feature_enable_disable ("ip4-local", "nat44-ed-hairpinning",
                                     sw_if_index, 1, 0, 0);
-      else if (!sm->deterministic)
+      else
        vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
                                     sw_if_index, 1, 0, 0);
     }
@@ -2046,11 +2056,6 @@ fib:
 
     snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
   }));
-
-  pool_foreach (dm, sm->det_maps,
-  ({
-    snat_add_del_addr_to_fib(&dm->out_addr, dm->out_plen, sw_if_index, !is_del);
-  }));
   /* *INDENT-ON* */
 
   return 0;
@@ -2069,8 +2074,7 @@ snat_interface_add_del_output_feature (u32 sw_if_index,
                                                       sw_if_index);
 
 
-  if (sm->deterministic ||
-      (sm->static_mapping_only && !(sm->static_mapping_connection_tracking)))
+  if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
     return VNET_API_ERROR_UNSUPPORTED;
 
   /* *INDENT-OFF* */
@@ -2228,6 +2232,7 @@ fq:
   pool_get (sm->output_feature_interfaces, i);
   i->sw_if_index = sw_if_index;
   i->flags = 0;
+  nat_validate_counters (sm, sw_if_index);
   if (is_inside)
     i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
   else
@@ -2508,11 +2513,6 @@ snat_init (vlib_main_t * vm)
   node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in-slowpath");
   sm->ed_out2in_slowpath_node_index = node->index;
 
-  node = vlib_get_node_by_name (vm, (u8 *) "nat44-det-in2out");
-  sm->det_in2out_node_index = node->index;
-  node = vlib_get_node_by_name (vm, (u8 *) "nat44-det-out2in");
-  sm->det_out2in_node_index = node->index;
-
   node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpinning");
   sm->hairpinning_node_index = node->index;
   node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpin-dst");
@@ -2578,6 +2578,40 @@ snat_init (vlib_main_t * vm)
   sm->total_sessions.stat_segment_name = "/nat44/total-sessions";
   vlib_validate_simple_counter (&sm->total_sessions, 0);
   vlib_zero_simple_counter (&sm->total_sessions, 0);
+  sm->user_limit_reached.name = "user-limit-reached";
+  sm->user_limit_reached.stat_segment_name = "/nat44/user-limit-reached";
+  vlib_validate_simple_counter (&sm->user_limit_reached, 0);
+  vlib_zero_simple_counter (&sm->user_limit_reached, 0);
+
+#define _(x)                                            \
+  sm->counters.fastpath.in2out.x.name = #x;             \
+  sm->counters.fastpath.in2out.x.stat_segment_name =    \
+      "/nat44/in2out/fastpath/" #x;                     \
+  sm->counters.slowpath.in2out.x.name = #x;             \
+  sm->counters.slowpath.in2out.x.stat_segment_name =    \
+      "/nat44/in2out/slowpath/" #x;                     \
+  sm->counters.fastpath.out2in.x.name = #x;             \
+  sm->counters.fastpath.out2in.x.stat_segment_name =    \
+      "/nat44/out2in/fastpath/" #x;                     \
+  sm->counters.slowpath.out2in.x.name = #x;             \
+  sm->counters.slowpath.out2in.x.stat_segment_name =    \
+      "/nat44/out2in/slowpath/" #x;                     \
+  sm->counters.fastpath.in2out_ed.x.name = #x;          \
+  sm->counters.fastpath.in2out_ed.x.stat_segment_name = \
+      "/nat44/ed/in2out/fastpath/" #x;                  \
+  sm->counters.slowpath.in2out_ed.x.name = #x;          \
+  sm->counters.slowpath.in2out_ed.x.stat_segment_name = \
+      "/nat44/ed/in2out/slowpath/" #x;                  \
+  sm->counters.fastpath.out2in_ed.x.name = #x;          \
+  sm->counters.fastpath.out2in_ed.x.stat_segment_name = \
+      "/nat44/ed/out2in/fastpath/" #x;                  \
+  sm->counters.slowpath.out2in_ed.x.name = #x;          \
+  sm->counters.slowpath.out2in_ed.x.stat_segment_name = \
+      "/nat44/ed/out2in/slowpath/" #x;
+  foreach_nat_counter;
+#undef _
+  sm->counters.hairpinning.name = "hairpinning";
+  sm->counters.hairpinning.stat_segment_name = "/nat44/hairpinning";
 
   /* Init IPFIX logging */
   snat_ipfix_logging_init (vm);
@@ -2587,8 +2621,6 @@ snat_init (vlib_main_t * vm)
   if (error)
     return error;
 
-  nat66_init (vm);
-
   ip4_table_bind_callback_t cbt4 = {
     .function = snat_ip4_table_bind,
   };
@@ -2840,14 +2872,6 @@ end:
   return 0;
 }
 
-static_always_inline u16
-snat_random_port (u16 min, u16 max)
-{
-  snat_main_t *sm = &snat_main;
-  return min + random_u32 (&sm->random_seed) /
-    (random_u32_max () / (max - min + 1) + 1);
-}
-
 int
 snat_alloc_outside_address_and_port (snat_address_t * addresses,
                                     u32 fib_index,
@@ -2893,7 +2917,7 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses,
                     { \
                       portnum = (port_per_thread * \
                         snat_thread_index) + \
-                        snat_random_port(1, port_per_thread) + 1024; \
+                        snat_random_port(0, port_per_thread - 1) + 1024; \
                       if (a->busy_##n##_port_refcounts[portnum]) \
                         continue; \
                      --a->busy_##n##_port_refcounts[portnum]; \
@@ -2930,7 +2954,7 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses,
             { \
               portnum = (port_per_thread * \
                 snat_thread_index) + \
-                snat_random_port(1, port_per_thread) + 1024; \
+                snat_random_port(0, port_per_thread - 1) + 1024; \
              if (a->busy_##n##_port_refcounts[portnum]) \
                 continue; \
              ++a->busy_##n##_port_refcounts[portnum]; \
@@ -3780,13 +3804,25 @@ nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port,
   s->total_bytes = total_bytes;
 }
 
+static u32
+nat_calc_bihash_buckets (u32 n_elts)
+{
+  return 1 << (max_log2 (n_elts >> 1) + 1);
+}
+
+static u32
+nat_calc_bihash_memory (u32 n_buckets, uword kv_size)
+{
+  return n_buckets * (8 + kv_size * 4);
+}
+
 void
 nat44_db_init (snat_main_per_thread_data_t * tsm)
 {
   snat_main_t *sm = &snat_main;
 
-  pool_alloc (tsm->sessions, sm->max_translations);
-  pool_alloc (tsm->lru_pool, sm->max_translations);
+  pool_alloc (tsm->sessions, sm->max_translations_per_thread);
+  pool_alloc (tsm->lru_pool, sm->max_translations_per_thread);
 
   dlist_elt_t *head;
 
@@ -3831,7 +3867,7 @@ nat44_db_init (snat_main_per_thread_data_t * tsm)
     }
 
   // TODO: resolve static mappings (put only to !ED)
-  pool_alloc (tsm->list_pool, sm->max_translations);
+  pool_alloc (tsm->list_pool, sm->max_translations_per_thread);
   clib_bihash_init_8_8 (&tsm->user_hash, "users", sm->user_buckets,
                        sm->user_memory_size);
   clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash, format_user_kvp);
@@ -3898,7 +3934,6 @@ 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;
   snat_main_per_thread_data_t *tsm;
 
   u32 static_mapping_buckets = 1024;
@@ -3910,10 +3945,10 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
   u32 nat64_st_buckets = 2048;
   uword nat64_st_memory_size = 256 << 20;
 
-  u32 user_buckets = 128;
-  uword user_memory_size = 64 << 20;
-  u32 translation_buckets = 1024;
-  uword translation_memory_size = 128 << 20;
+  u32 max_users_per_thread = 0;
+  u32 user_memory_size = 0;
+  u32 max_translations_per_thread = 0;
+  u32 translation_memory_size = 0;
 
   u32 max_translations_per_user = ~0;
 
@@ -3928,14 +3963,14 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
   u32 tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
   u32 tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
 
-  sm->deterministic = 0;
   sm->out2in_dpo = 0;
   sm->endpoint_dependent = 0;
 
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     {
       if (unformat
-         (input, "translation hash buckets %d", &translation_buckets))
+         (input, "max translations per thread %d",
+          &max_translations_per_thread))
        ;
       else if (unformat (input, "udp timeout %d", &udp_timeout))
        ;
@@ -3947,7 +3982,9 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
                         &tcp_established_timeout));
       else if (unformat (input, "translation hash memory %d",
                         &translation_memory_size));
-      else if (unformat (input, "user hash buckets %d", &user_buckets))
+      else
+       if (unformat
+           (input, "max users per thread %d", &max_users_per_thread))
        ;
       else if (unformat (input, "user hash memory %d", &user_memory_size))
        ;
@@ -3966,8 +4003,6 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
          if (unformat (input, "connection tracking"))
            static_mapping_connection_tracking = 1;
        }
-      else if (unformat (input, "deterministic"))
-       sm->deterministic = 1;
       else if (unformat (input, "nat64 bib hash buckets %d",
                         &nat64_bib_buckets))
        ;
@@ -3989,17 +4024,24 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
                                  format_unformat_error, input);
     }
 
-  if (sm->deterministic && sm->endpoint_dependent)
-    return clib_error_return (0,
-                             "deterministic and endpoint-dependent modes are mutually exclusive");
-
-  if (static_mapping_only && (sm->deterministic || sm->endpoint_dependent))
+  if (static_mapping_only && (sm->endpoint_dependent))
     return clib_error_return (0,
                              "static mapping only mode available only for simple nat");
 
-  if (sm->out2in_dpo && (sm->deterministic || sm->endpoint_dependent))
+  if (sm->out2in_dpo && (sm->endpoint_dependent))
     return clib_error_return (0,
                              "out2in dpo mode available only for simple nat");
+  if (sm->endpoint_dependent && max_users_per_thread > 0)
+    {
+      return clib_error_return (0,
+                               "setting 'max users' in endpoint-dependent mode is not supported");
+    }
+
+  if (sm->endpoint_dependent && max_translations_per_user != ~0)
+    {
+      return clib_error_return (0,
+                               "setting 'max translations per user' in endpoint-dependent mode is not supported");
+    }
 
   /* optionally configurable timeouts for testing purposes */
   sm->udp_timeout = udp_timeout;
@@ -4007,26 +4049,45 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
   sm->tcp_established_timeout = tcp_established_timeout;
   sm->icmp_timeout = icmp_timeout;
 
-  sm->user_buckets = user_buckets;
-  sm->user_memory_size = user_memory_size;
+  if (0 == max_users_per_thread)
+    {
+      max_users_per_thread = 1024;
+    }
+  sm->max_users_per_thread = max_users_per_thread;
+  sm->user_buckets = nat_calc_bihash_buckets (sm->max_users_per_thread);
 
-  sm->translation_buckets = translation_buckets;
+  if (0 == max_translations_per_thread)
+    {
+      // default value based on legacy setting of load factor 10 * default
+      // translation buckets 1024
+      max_translations_per_thread = 10 * 1024;
+    }
+  sm->max_translations_per_thread = max_translations_per_thread;
+  sm->translation_buckets =
+    nat_calc_bihash_buckets (sm->max_translations_per_thread);
+  if (0 == translation_memory_size)
+    {
+      translation_memory_size =
+       nat_calc_bihash_memory (sm->translation_buckets,
+                               sizeof (clib_bihash_16_8_t));
+    }
   sm->translation_memory_size = translation_memory_size;
-  /* do not exceed load factor 10 */
-  sm->max_translations = 10 * translation_buckets;
-  vec_add1 (sm->max_translations_per_fib, sm->max_translations);
+  if (0 == user_memory_size)
+    {
+      user_memory_size =
+       nat_calc_bihash_memory (sm->max_users_per_thread,
+                               sizeof (clib_bihash_8_8_t));
+    }
+  sm->user_memory_size = user_memory_size;
+  vec_add1 (sm->max_translations_per_fib, sm->max_translations_per_thread);
 
   sm->max_translations_per_user = max_translations_per_user == ~0 ?
-    sm->max_translations : max_translations_per_user;
+    sm->max_translations_per_thread : max_translations_per_user;
 
   sm->outside_vrf_id = outside_vrf_id;
   sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
                                                             outside_vrf_id,
                                                             nat_fib_src_hi);
-  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,
-                                                            nat_fib_src_hi);
   sm->inside_vrf_id = inside_vrf_id;
   sm->inside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
                                                            inside_vrf_id,
@@ -4037,77 +4098,67 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
   nat64_set_hash (nat64_bib_buckets, nat64_bib_memory_size, nat64_st_buckets,
                  nat64_st_memory_size);
 
-  if (sm->deterministic)
+  if (sm->endpoint_dependent)
     {
-      sm->in2out_node_index = snat_det_in2out_node.index;
-      sm->in2out_output_node_index = ~0;
-      sm->out2in_node_index = snat_det_out2in_node.index;
-      sm->icmp_match_in2out_cb = icmp_match_in2out_det;
-      sm->icmp_match_out2in_cb = icmp_match_out2in_det;
+      sm->worker_in2out_cb = nat44_ed_get_worker_in2out_cb;
+      sm->worker_out2in_cb = nat44_ed_get_worker_out2in_cb;
+
+      sm->in2out_node_index = nat44_ed_in2out_node.index;
+      sm->in2out_output_node_index = nat44_ed_in2out_output_node.index;
+      sm->out2in_node_index = nat44_ed_out2in_node.index;
+
+      sm->icmp_match_in2out_cb = icmp_match_in2out_ed;
+      sm->icmp_match_out2in_cb = icmp_match_out2in_ed;
+      nat_affinity_init (vm);
+      nat_ha_init (vm, nat_ha_sadd_ed_cb, nat_ha_sdel_ed_cb,
+                  nat_ha_sref_ed_cb);
+      clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed",
+                            clib_max (1, sm->num_workers) *
+                            sm->translation_buckets,
+                            clib_max (1, sm->num_workers) *
+                            sm->translation_memory_size);
+      clib_bihash_set_kvp_format_fn_16_8 (&sm->out2in_ed,
+                                         format_ed_session_kvp);
     }
   else
     {
-      if (sm->endpoint_dependent)
-       {
-         sm->worker_in2out_cb = nat44_ed_get_worker_in2out_cb;
-         sm->worker_out2in_cb = nat44_ed_get_worker_out2in_cb;
-
-         sm->in2out_node_index = nat44_ed_in2out_node.index;
-         sm->in2out_output_node_index = nat44_ed_in2out_output_node.index;
-         sm->out2in_node_index = nat44_ed_out2in_node.index;
-
-         sm->icmp_match_in2out_cb = icmp_match_in2out_ed;
-         sm->icmp_match_out2in_cb = icmp_match_out2in_ed;
-         nat_affinity_init (vm);
-         nat_ha_init (vm, nat_ha_sadd_ed_cb, nat_ha_sdel_ed_cb,
-                      nat_ha_sref_ed_cb);
-         clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed",
-                                translation_buckets,
-                                translation_memory_size);
-         clib_bihash_set_kvp_format_fn_16_8 (&sm->out2in_ed,
-                                             format_ed_session_kvp);
-       }
-      else
-       {
-         sm->worker_in2out_cb = snat_get_worker_in2out_cb;
-         sm->worker_out2in_cb = snat_get_worker_out2in_cb;
+      sm->worker_in2out_cb = snat_get_worker_in2out_cb;
+      sm->worker_out2in_cb = snat_get_worker_out2in_cb;
 
-         sm->in2out_node_index = snat_in2out_node.index;
-         sm->in2out_output_node_index = snat_in2out_output_node.index;
-         sm->out2in_node_index = snat_out2in_node.index;
+      sm->in2out_node_index = snat_in2out_node.index;
+      sm->in2out_output_node_index = snat_in2out_output_node.index;
+      sm->out2in_node_index = snat_out2in_node.index;
 
-         sm->icmp_match_in2out_cb = icmp_match_in2out_slow;
-         sm->icmp_match_out2in_cb = icmp_match_out2in_slow;
-         nat_ha_init (vm, nat_ha_sadd_cb, nat_ha_sdel_cb, nat_ha_sref_cb);
-       }
-      if (!static_mapping_only ||
-         (static_mapping_only && static_mapping_connection_tracking))
-       {
+      sm->icmp_match_in2out_cb = icmp_match_in2out_slow;
+      sm->icmp_match_out2in_cb = icmp_match_out2in_slow;
+      nat_ha_init (vm, nat_ha_sadd_cb, nat_ha_sdel_cb, nat_ha_sref_cb);
+    }
+  if (!static_mapping_only ||
+      (static_mapping_only && static_mapping_connection_tracking))
+    {
           /* *INDENT-OFF* */
           vec_foreach (tsm, sm->per_thread_data)
             {
               nat44_db_init (tsm);
             }
           /* *INDENT-ON* */
-       }
-      else
-       {
-         sm->icmp_match_in2out_cb = icmp_match_in2out_fast;
-         sm->icmp_match_out2in_cb = icmp_match_out2in_fast;
-       }
-      clib_bihash_init_8_8 (&sm->static_mapping_by_local,
-                           "static_mapping_by_local", static_mapping_buckets,
-                           static_mapping_memory_size);
-      clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
-                                        format_static_mapping_kvp);
-
-      clib_bihash_init_8_8 (&sm->static_mapping_by_external,
-                           "static_mapping_by_external",
-                           static_mapping_buckets,
-                           static_mapping_memory_size);
-      clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
-                                        format_static_mapping_kvp);
     }
+  else
+    {
+      sm->icmp_match_in2out_cb = icmp_match_in2out_fast;
+      sm->icmp_match_out2in_cb = icmp_match_out2in_fast;
+    }
+  clib_bihash_init_8_8 (&sm->static_mapping_by_local,
+                       "static_mapping_by_local", static_mapping_buckets,
+                       static_mapping_memory_size);
+  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
+                                    format_static_mapping_kvp);
+
+  clib_bihash_init_8_8 (&sm->static_mapping_by_external,
+                       "static_mapping_by_external",
+                       static_mapping_buckets, static_mapping_memory_size);
+  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
+                                    format_static_mapping_kvp);
 
   return 0;
 }