nat: enable force session cleanup
[vpp.git] / src / plugins / nat / nat.c
index b0c30d6..c30324b 100755 (executable)
@@ -199,7 +199,10 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
 {
   snat_session_key_t key;
   clib_bihash_kv_8_8_t kv;
-  nat_ed_ses_key_t ed_key;
+  u8 proto;
+  u16 r_port, l_port;
+  ip4_address_t *l_addr, *r_addr;
+  u32 fib_index = 0;
   clib_bihash_kv_16_8_t ed_kv;
   snat_main_per_thread_data_t *tsm =
     vec_elt_at_index (sm->per_thread_data, thread_index);
@@ -208,21 +211,20 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
     {
       if (snat_is_unk_proto_session (s))
        {
-         ed_key.proto = s->in2out.port;
-         ed_key.r_port = 0;
-         ed_key.l_port = 0;
+         make_ed_kv (&s->in2out.addr, &s->ext_host_addr, s->in2out.port, 0,
+                     0, 0, ~0ULL, &ed_kv);
        }
       else
        {
-         ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
-         ed_key.l_port = s->in2out.port;
-         ed_key.r_port = s->ext_host_port;
+         proto = snat_proto_to_ip_proto (s->in2out.protocol);
+         l_port = s->in2out.port;
+         r_port = s->ext_host_port;
+         l_addr = &s->in2out.addr;
+         r_addr = &s->ext_host_addr;
+         proto = snat_proto_to_ip_proto (s->in2out.protocol);
+         make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+                     &ed_kv);
        }
-      ed_key.l_addr = s->in2out.addr;
-      ed_key.r_addr = s->ext_host_addr;
-      ed_key.fib_index = 0;
-      ed_kv.key[0] = ed_key.as_u64[0];
-      ed_kv.key[1] = ed_key.as_u64[1];
       if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
        nat_elog_warn ("in2out_ed key del failed");
       return;
@@ -234,36 +236,36 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
       if (is_affinity_sessions (s))
        nat_affinity_unlock (s->ext_host_addr, s->out2in.addr,
                             s->in2out.protocol, s->out2in.port);
-      ed_key.l_addr = s->out2in.addr;
-      ed_key.r_addr = s->ext_host_addr;
-      ed_key.fib_index = s->out2in.fib_index;
+      l_addr = &s->out2in.addr;
+      r_addr = &s->ext_host_addr;
+      fib_index = s->out2in.fib_index;
       if (snat_is_unk_proto_session (s))
        {
-         ed_key.proto = s->in2out.port;
-         ed_key.r_port = 0;
-         ed_key.l_port = 0;
+         proto = s->in2out.port;
+         r_port = 0;
+         l_port = 0;
        }
       else
        {
-         ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
-         ed_key.l_port = s->out2in.port;
-         ed_key.r_port = s->ext_host_port;
+         proto = snat_proto_to_ip_proto (s->in2out.protocol);
+         l_port = s->out2in.port;
+         r_port = s->ext_host_port;
        }
-      ed_kv.key[0] = ed_key.as_u64[0];
-      ed_kv.key[1] = ed_key.as_u64[1];
+      make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+                 &ed_kv);
       if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0))
        nat_elog_warn ("out2in_ed key del failed");
-      ed_key.l_addr = s->in2out.addr;
-      ed_key.fib_index = s->in2out.fib_index;
+      l_addr = &s->in2out.addr;
+      fib_index = s->in2out.fib_index;
       if (!snat_is_unk_proto_session (s))
-       ed_key.l_port = s->in2out.port;
+       l_port = s->in2out.port;
       if (is_twice_nat_session (s))
        {
-         ed_key.r_addr = s->ext_host_nat_addr;
-         ed_key.r_port = s->ext_host_nat_port;
+         r_addr = &s->ext_host_nat_addr;
+         r_port = s->ext_host_nat_port;
        }
-      ed_kv.key[0] = ed_key.as_u64[0];
-      ed_kv.key[1] = ed_key.as_u64[1];
+      make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+                 &ed_kv);
       if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
        nat_elog_warn ("in2out_ed key del failed");
 
@@ -327,12 +329,35 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
                                      &s->out2in);
 }
 
+int
+nat44_set_session_limit (u32 session_limit, u32 vrf_id)
+{
+  snat_main_t *sm = &snat_main;
+  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
+  u32 len = vec_len (sm->max_translations_per_fib);
+
+  if (len <= fib_index)
+    {
+      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[fib_index] = session_limit;
+  return 0;
+}
+
+
 void
 nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
                         u32 thread_index, u8 is_ha)
 {
   snat_session_key_t key;
-  nat_ed_ses_key_t ed_key;
+  u8 proto;
+  u16 r_port, l_port;
+  ip4_address_t *l_addr, *r_addr;
+  u32 fib_index;
   clib_bihash_kv_16_8_t ed_kv;
   snat_main_per_thread_data_t *tsm =
     vec_elt_at_index (sm->per_thread_data, thread_index);
@@ -341,22 +366,22 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
     {
       if (snat_is_unk_proto_session (s))
        {
-         ed_key.proto = s->in2out.port;
-         ed_key.r_port = 0;
-         ed_key.l_port = 0;
+         proto = s->in2out.port;
+         r_port = 0;
+         l_port = 0;
        }
       else
        {
-         ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
-         ed_key.l_port = s->in2out.port;
-         ed_key.r_port = s->ext_host_port;
+         proto = snat_proto_to_ip_proto (s->in2out.protocol);
+         l_port = s->in2out.port;
+         r_port = s->ext_host_port;
        }
 
-      ed_key.l_addr = s->in2out.addr;
-      ed_key.r_addr = s->ext_host_addr;
-      ed_key.fib_index = 0;
-      ed_kv.key[0] = ed_key.as_u64[0];
-      ed_kv.key[1] = ed_key.as_u64[1];
+      l_addr = &s->in2out.addr;
+      r_addr = &s->ext_host_addr;
+      fib_index = 0;
+      make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+                 &ed_kv);
 
       if (PREDICT_FALSE
          (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)))
@@ -368,41 +393,40 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
   if (is_affinity_sessions (s))
     nat_affinity_unlock (s->ext_host_addr, s->out2in.addr,
                         s->in2out.protocol, s->out2in.port);
-  ed_key.l_addr = s->out2in.addr;
-  ed_key.r_addr = s->ext_host_addr;
-  ed_key.fib_index = s->out2in.fib_index;
+  l_addr = &s->out2in.addr;
+  r_addr = &s->ext_host_addr;
+  fib_index = s->out2in.fib_index;
   if (snat_is_unk_proto_session (s))
     {
-      ed_key.proto = s->in2out.port;
-      ed_key.r_port = 0;
-      ed_key.l_port = 0;
+      proto = s->in2out.port;
+      r_port = 0;
+      l_port = 0;
     }
   else
     {
-      ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
-      ed_key.l_port = s->out2in.port;
-      ed_key.r_port = s->ext_host_port;
+      proto = snat_proto_to_ip_proto (s->in2out.protocol);
+      l_port = s->out2in.port;
+      r_port = s->ext_host_port;
     }
-  ed_kv.key[0] = ed_key.as_u64[0];
-  ed_kv.key[1] = ed_key.as_u64[1];
+  make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+             &ed_kv);
 
   if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0)))
     nat_elog_warn ("out2in_ed key del failed");
 
-  ed_key.l_addr = s->in2out.addr;
-  ed_key.fib_index = s->in2out.fib_index;
+  l_addr = &s->in2out.addr;
+  fib_index = s->in2out.fib_index;
 
   if (!snat_is_unk_proto_session (s))
-    ed_key.l_port = s->in2out.port;
+    l_port = s->in2out.port;
 
   if (is_twice_nat_session (s))
     {
-      ed_key.r_addr = s->ext_host_nat_addr;
-      ed_key.r_port = s->ext_host_nat_port;
+      r_addr = &s->ext_host_nat_addr;
+      r_port = s->ext_host_nat_port;
     }
-
-  ed_kv.key[0] = ed_key.as_u64[0];
-  ed_kv.key[1] = ed_key.as_u64[1];
+  make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+             &ed_kv);
 
   if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)))
     nat_elog_warn ("in2out_ed key del failed");
@@ -2487,6 +2511,46 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses,
                                 snat_session_key_t * k,
                                 u16 port_per_thread, u32 snat_thread_index);
 
+void
+test_ed_make_split ()
+{
+  ip4_address_t l_addr;
+  l_addr.as_u8[0] = 1;
+  l_addr.as_u8[1] = 1;
+  l_addr.as_u8[2] = 1;
+  l_addr.as_u8[3] = 1;
+  ip4_address_t r_addr;
+  r_addr.as_u8[0] = 2;
+  r_addr.as_u8[1] = 2;
+  r_addr.as_u8[2] = 2;
+  r_addr.as_u8[3] = 2;
+  u16 l_port = 40001;
+  u16 r_port = 40301;
+  u8 proto = 9;
+  u32 fib_index = 9000001;
+  u64 value = ~0ULL;
+  clib_bihash_kv_16_8_t kv;
+  make_ed_kv (&l_addr, &r_addr, proto, fib_index, l_port, r_port, value, &kv);
+  ip4_address_t l_addr2;
+  ip4_address_t r_addr2;
+  clib_memset (&l_addr2, 0, sizeof (l_addr2));
+  clib_memset (&r_addr2, 0, sizeof (r_addr2));
+  u16 l_port2 = 0;
+  u16 r_port2 = 0;
+  u8 proto2 = 0;
+  u32 fib_index2 = 0;
+  split_ed_kv (&kv, &l_addr2, &r_addr2, &proto2, &fib_index2, &l_port2,
+              &r_port2);
+  u64 value2 = kv.value;
+  ASSERT (l_addr.as_u32 == l_addr2.as_u32);
+  ASSERT (r_addr.as_u32 == r_addr2.as_u32);
+  ASSERT (l_port == l_port2);
+  ASSERT (r_port == r_port2);
+  ASSERT (proto == proto2);
+  ASSERT (fib_index == fib_index2);
+  ASSERT (value == value2);
+}
+
 static clib_error_t *
 snat_init (vlib_main_t * vm)
 {
@@ -2656,6 +2720,7 @@ snat_init (vlib_main_t * vm)
                                         FIB_SOURCE_PRIORITY_LOW,
                                         FIB_SOURCE_BH_SIMPLE);
 
+  test_ed_make_split ();
   return error;
 }
 
@@ -3159,16 +3224,18 @@ u8 *
 format_ed_session_kvp (u8 * s, va_list * args)
 {
   clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *);
-  nat_ed_ses_key_t k;
 
-  k.as_u64[0] = v->key[0];
-  k.as_u64[1] = v->key[1];
+  u8 proto;
+  u16 r_port, l_port;
+  ip4_address_t l_addr, r_addr;
+  u32 fib_index;
 
+  split_ed_kv (v, &l_addr, &r_addr, &proto, &fib_index, &l_port, &r_port);
   s =
     format (s, "local %U:%d remote %U:%d proto %U fib %d session-index %llu",
-           format_ip4_address, &k.l_addr, clib_net_to_host_u16 (k.l_port),
-           format_ip4_address, &k.r_addr, clib_net_to_host_u16 (k.r_port),
-           format_ip_protocol, k.proto, k.fib_index, v->value);
+           format_ip4_address, &l_addr, clib_net_to_host_u16 (l_port),
+           format_ip4_address, &r_addr, clib_net_to_host_u16 (r_port),
+           format_ip_protocol, proto, fib_index, v->value);
 
   return s;
 }
@@ -3340,8 +3407,9 @@ nat44_ed_get_worker_in2out_cb (ip4_header_t * ip, u32 rx_fib_index,
          break;
        }
 
-      make_ed_kv (&kv16, &ip->src_address, &ip->dst_address,
-                 ip->protocol, fib_index, udp->src_port, udp->dst_port);
+      make_ed_kv (&ip->src_address, &ip->dst_address,
+                 ip->protocol, fib_index, udp->src_port, udp->dst_port,
+                 ~0ULL, &kv16);
 
       /* *INDENT-OFF* */
       vec_foreach (tsm, sm->per_thread_data)
@@ -3410,8 +3478,9 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip,
     {
       udp = ip4_next_header (ip);
 
-      make_ed_kv (&kv16, &ip->dst_address, &ip->src_address,
-                 ip->protocol, rx_fib_index, udp->dst_port, udp->src_port);
+      make_ed_kv (&ip->dst_address, &ip->src_address,
+                 ip->protocol, rx_fib_index, udp->dst_port, udp->src_port,
+                 ~0ULL, &kv16);
 
       /* *INDENT-OFF* */
       vec_foreach (tsm, sm->per_thread_data)
@@ -3431,15 +3500,8 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip,
     }
   else if (proto == SNAT_PROTOCOL_ICMP)
     {
-      nat_ed_ses_key_t key;
-
-      if (!get_icmp_o2i_ed_key (b, ip, &key))
+      if (!get_icmp_o2i_ed_key (b, ip, rx_fib_index, ~0ULL, 0, 0, 0, &kv16))
        {
-
-         key.fib_index = rx_fib_index;
-         kv16.key[0] = key.as_u64[0];
-         kv16.key[1] = key.as_u64[1];
-
           /* *INDENT-OFF* */
           vec_foreach (tsm, sm->per_thread_data)
             {
@@ -3796,14 +3858,14 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port,
   key.fib_index = fib_index;
   s->in2out = key;
 
-  make_ed_kv (&kv, in_addr, &s->ext_host_nat_addr,
+  make_ed_kv (in_addr, &s->ext_host_nat_addr,
              snat_proto_to_ip_proto (proto), fib_index, in_port,
-             s->ext_host_nat_port);
+             s->ext_host_nat_port, s - tsm->sessions, &kv);
   if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1))
     nat_elog_warn ("in2out key add failed");
 
-  make_ed_kv (&kv, out_addr, eh_addr, snat_proto_to_ip_proto (proto),
-             s->out2in.fib_index, out_port, eh_port);
+  make_ed_kv (out_addr, eh_addr, snat_proto_to_ip_proto (proto),
+             s->out2in.fib_index, out_port, eh_port, s - tsm->sessions, &kv);
   if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 1))
     nat_elog_warn ("out2in key add failed");
 }
@@ -3814,7 +3876,6 @@ nat_ha_sdel_ed_cb (ip4_address_t * out_addr, u16 out_port,
                   u32 fib_index, u32 ti)
 {
   snat_main_t *sm = &snat_main;
-  nat_ed_ses_key_t key;
   clib_bihash_kv_16_8_t kv, value;
   u32 thread_index;
   snat_session_t *s;
@@ -3829,14 +3890,8 @@ nat_ha_sdel_ed_cb (ip4_address_t * out_addr, u16 out_port,
     thread_index = sm->num_workers;
   tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
 
-  key.l_addr.as_u32 = out_addr->as_u32;
-  key.l_port = out_port;
-  key.r_addr.as_u32 = eh_addr->as_u32;
-  key.r_port = eh_port;
-  key.proto = proto;
-  key.fib_index = fib_index;
-  kv.key[0] = key.as_u64[0];
-  kv.key[1] = key.as_u64[1];
+  make_ed_kv (out_addr, eh_addr, proto, fib_index, out_port, eh_port, ~0ULL,
+             &kv);
   if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
     return;
 
@@ -3852,21 +3907,14 @@ nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port,
                   u32 thread_index)
 {
   snat_main_t *sm = &snat_main;
-  nat_ed_ses_key_t key;
   clib_bihash_kv_16_8_t kv, value;
   snat_session_t *s;
   snat_main_per_thread_data_t *tsm;
 
   tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
 
-  key.l_addr.as_u32 = out_addr->as_u32;
-  key.l_port = out_port;
-  key.r_addr.as_u32 = eh_addr->as_u32;
-  key.r_port = eh_port;
-  key.proto = proto;
-  key.fib_index = fib_index;
-  kv.key[0] = key.as_u64[0];
-  kv.key[1] = key.as_u64[1];
+  make_ed_kv (out_addr, eh_addr, proto, fib_index, out_port, eh_port, ~0ULL,
+             &kv);
   if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
     return;
 
@@ -3875,6 +3923,76 @@ nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port,
   s->total_bytes = total_bytes;
 }
 
+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->global_lru_pool, sm->max_translations);
+
+  dlist_elt_t *head;
+  pool_get (tsm->global_lru_pool, head);
+  tsm->global_lru_head_index = head - tsm->global_lru_pool;
+  clib_dlist_init (tsm->global_lru_pool, tsm->global_lru_head_index);
+
+  if (sm->endpoint_dependent)
+    {
+      clib_bihash_init_16_8 (&tsm->in2out_ed, "in2out-ed",
+                            sm->translation_buckets,
+                            sm->translation_memory_size);
+      clib_bihash_set_kvp_format_fn_16_8 (&tsm->in2out_ed,
+                                         format_ed_session_kvp);
+      clib_bihash_init_16_8 (&tsm->out2in_ed, "out2in-ed",
+                            sm->translation_buckets,
+                            sm->translation_memory_size);
+      clib_bihash_set_kvp_format_fn_16_8 (&tsm->out2in_ed,
+                                         format_ed_session_kvp);
+    }
+  else
+    {
+      clib_bihash_init_8_8 (&tsm->in2out, "in2out",
+                           sm->translation_buckets,
+                           sm->translation_memory_size);
+      clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out, format_session_kvp);
+      clib_bihash_init_8_8 (&tsm->out2in, "out2in",
+                           sm->translation_buckets,
+                           sm->translation_memory_size);
+      clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in, format_session_kvp);
+    }
+
+  // TODO: resolve static mappings (put only to !ED)
+  pool_alloc (tsm->list_pool, sm->max_translations);
+  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);
+}
+
+void
+nat44_db_free (snat_main_per_thread_data_t * tsm)
+{
+  snat_main_t *sm = &snat_main;
+
+  pool_free (tsm->sessions);
+  pool_free (tsm->global_lru_pool);
+
+  if (sm->endpoint_dependent)
+    {
+      clib_bihash_free_16_8 (&tsm->in2out_ed);
+      clib_bihash_free_16_8 (&tsm->out2in_ed);
+    }
+  else
+    {
+      clib_bihash_free_8_8 (&tsm->in2out);
+      clib_bihash_free_8_8 (&tsm->out2in);
+    }
+
+  // TODO: resolve static mappings (put only to !ED)
+  pool_free (tsm->users);
+  pool_free (tsm->list_pool);
+  clib_bihash_free_8_8 (&tsm->user_hash);
+}
+
 static clib_error_t *
 snat_config (vlib_main_t * vm, unformat_input_t * input)
 {
@@ -3997,9 +4115,10 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
 
   sm->translation_buckets = translation_buckets;
   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);
+
   sm->max_translations_per_user = max_translations_per_user == ~0 ?
     sm->max_translations : max_translations_per_user;
 
@@ -4072,52 +4191,9 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
           /* *INDENT-OFF* */
           vec_foreach (tsm, sm->per_thread_data)
             {
-              pool_alloc (tsm->sessions, sm->max_translations);
-              pool_alloc (tsm->list_pool, sm->max_translations);
-              pool_alloc (tsm->global_lru_pool, sm->max_translations);
-
-              dlist_elt_t *head;
-              pool_get (tsm->global_lru_pool, head);
-              tsm->global_lru_head_index = head - tsm->global_lru_pool;
-              clib_dlist_init (tsm->global_lru_pool,
-                               tsm->global_lru_head_index);
-
-              if (sm->endpoint_dependent)
-                {
-                  clib_bihash_init_16_8 (&tsm->in2out_ed, "in2out-ed",
-                                         translation_buckets,
-                                         translation_memory_size);
-                  clib_bihash_set_kvp_format_fn_16_8 (&tsm->in2out_ed,
-                                                      format_ed_session_kvp);
-
-                  clib_bihash_init_16_8 (&tsm->out2in_ed, "out2in-ed",
-                                         translation_buckets,
-                                         translation_memory_size);
-                  clib_bihash_set_kvp_format_fn_16_8 (&tsm->out2in_ed,
-                                                      format_ed_session_kvp);
-                }
-              else
-                {
-                  clib_bihash_init_8_8 (&tsm->in2out, "in2out",
-                                        translation_buckets,
-                                        translation_memory_size);
-                  clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out,
-                                                     format_session_kvp);
-
-                  clib_bihash_init_8_8 (&tsm->out2in, "out2in",
-                                        translation_buckets,
-                                        translation_memory_size);
-                  clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in,
-                                                     format_session_kvp);
-                }
-
-              clib_bihash_init_8_8 (&tsm->user_hash, "users", user_buckets,
-                                    user_memory_size);
-              clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash,
-                                                 format_user_kvp);
+              nat44_db_init (tsm);
             }
           /* *INDENT-ON* */
-
        }
       else
        {
@@ -4411,7 +4487,6 @@ nat44_del_ed_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
 {
   ip4_header_t ip;
   clib_bihash_16_8_t *t;
-  nat_ed_ses_key_t key;
   clib_bihash_kv_16_8_t kv, value;
   u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
   snat_session_t *s;
@@ -4429,16 +4504,12 @@ nat44_del_ed_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
 
   t = is_in ? &tsm->in2out_ed : &tsm->out2in_ed;
-  key.l_addr.as_u32 = addr->as_u32;
-  key.r_addr.as_u32 = eh_addr->as_u32;
-  key.l_port = clib_host_to_net_u16 (port);
-  key.r_port = clib_host_to_net_u16 (eh_port);
-  key.proto = proto;
-  key.fib_index = fib_index;
-  kv.key[0] = key.as_u64[0];
-  kv.key[1] = key.as_u64[1];
+  make_ed_kv (addr, eh_addr, proto, fib_index, clib_host_to_net_u16 (port),
+             clib_host_to_net_u16 (eh_port), ~0ULL, &kv);
   if (clib_bihash_search_16_8 (t, &kv, &value))
-    return VNET_API_ERROR_NO_SUCH_ENTRY;
+    {
+      return VNET_API_ERROR_NO_SUCH_ENTRY;
+    }
 
   if (pool_is_free_index (tsm->sessions, value.value))
     return VNET_API_ERROR_UNSPECIFIED;