nat: more long read after short write optimization
[vpp.git] / src / plugins / nat / nat.c
index 5566456..ed01bb4 100644 (file)
@@ -198,7 +198,6 @@ void
 nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
                       u8 is_ha)
 {
-  snat_session_key_t key;
   clib_bihash_kv_8_8_t kv;
   u8 proto;
   u16 r_port, l_port;
@@ -212,8 +211,8 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
     {
       if (snat_is_unk_proto_session (s))
        {
-         make_ed_kv (&s->in2out.addr, &s->ext_host_addr, s->in2out.port, 0,
-                     0, 0, ~0, ~0, &ed_kv);
+         init_ed_k (&ed_kv, s->in2out.addr, 0, s->ext_host_addr, 0, 0,
+                    s->in2out.port);
        }
       else
        {
@@ -221,9 +220,9 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
          r_port = s->ext_host_port;
          l_addr = &s->in2out.addr;
          r_addr = &s->ext_host_addr;
-         proto = nat_proto_to_ip_proto (s->in2out.protocol);
-         make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0,
-                     ~0, &ed_kv);
+         proto = nat_proto_to_ip_proto (s->nat_proto);
+         init_ed_k (&ed_kv, *l_addr, l_port, *r_addr, r_port, fib_index,
+                    proto);
        }
       if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
        nat_elog_warn ("in2out_ed key del failed");
@@ -235,7 +234,7 @@ 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);
+                            s->nat_proto, s->out2in.port);
       l_addr = &s->out2in.addr;
       r_addr = &s->ext_host_addr;
       fib_index = s->out2in.fib_index;
@@ -247,12 +246,11 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
        }
       else
        {
-         proto = nat_proto_to_ip_proto (s->in2out.protocol);
+         proto = nat_proto_to_ip_proto (s->nat_proto);
          l_port = s->out2in.port;
          r_port = s->ext_host_port;
        }
-      make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0, ~0,
-                 &ed_kv);
+      init_ed_k (&ed_kv, *l_addr, l_port, *r_addr, r_port, fib_index, proto);
       if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &ed_kv, 0))
        nat_elog_warn ("out2in_ed key del failed");
       l_addr = &s->in2out.addr;
@@ -264,8 +262,7 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
          r_addr = &s->ext_host_nat_addr;
          r_port = s->ext_host_nat_port;
        }
-      make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0, ~0,
-                 &ed_kv);
+      init_ed_k (&ed_kv, *l_addr, l_port, *r_addr, r_port, fib_index, proto);
       if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
        nat_elog_warn ("in2out_ed key del failed");
 
@@ -275,14 +272,14 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
                               &s->ext_host_nat_addr, s->ext_host_nat_port,
                               &s->out2in.addr, s->out2in.port,
                               &s->ext_host_addr, s->ext_host_port,
-                              s->in2out.protocol, is_twice_nat_session (s));
+                              s->nat_proto, is_twice_nat_session (s));
     }
   else
     {
-      kv.key = s->in2out.as_u64;
+      init_nat_i2o_k (&kv, s);
       if (clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0))
        nat_elog_warn ("in2out key del failed");
-      kv.key = s->out2in.as_u64;
+      init_nat_o2i_k (&kv, s);
       if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0))
        nat_elog_warn ("out2in key del failed");
 
@@ -290,7 +287,7 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
        nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index,
                                 &s->in2out.addr, s->in2out.port,
                                 &s->out2in.addr, s->out2in.port,
-                                s->in2out.protocol);
+                                s->nat_proto);
     }
 
   if (snat_is_unk_proto_session (s))
@@ -302,31 +299,31 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
       snat_ipfix_logging_nat44_ses_delete (thread_index,
                                           s->in2out.addr.as_u32,
                                           s->out2in.addr.as_u32,
-                                          s->in2out.protocol,
+                                          s->nat_proto,
                                           s->in2out.port,
                                           s->out2in.port,
                                           s->in2out.fib_index);
 
       nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
-                  s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
+                  s->ext_host_port, s->nat_proto, s->out2in.fib_index,
                   thread_index);
     }
 
   /* Twice NAT address and port for external host */
   if (is_twice_nat_session (s))
     {
-      key.protocol = s->in2out.protocol;
-      key.port = s->ext_host_nat_port;
-      key.addr.as_u32 = s->ext_host_nat_addr.as_u32;
       snat_free_outside_address_and_port (sm->twice_nat_addresses,
-                                         thread_index, &key);
+                                         thread_index,
+                                         &s->ext_host_nat_addr,
+                                         s->ext_host_nat_port, s->nat_proto);
     }
 
   if (snat_is_session_static (s))
     return;
 
   snat_free_outside_address_and_port (sm->addresses, thread_index,
-                                     &s->out2in);
+                                     &s->out2in.addr, s->out2in.port,
+                                     s->nat_proto);
 }
 
 int
@@ -352,7 +349,6 @@ void
 nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
                         u32 thread_index, u8 is_ha)
 {
-  snat_session_key_t key;
   u8 proto;
   u16 r_port, l_port;
   ip4_address_t *l_addr, *r_addr;
@@ -371,7 +367,7 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
        }
       else
        {
-         proto = nat_proto_to_ip_proto (s->in2out.protocol);
+         proto = nat_proto_to_ip_proto (s->nat_proto);
          l_port = s->in2out.port;
          r_port = s->ext_host_port;
        }
@@ -379,8 +375,7 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
       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, ~0, ~0,
-                 &ed_kv);
+      init_ed_k (&ed_kv, *l_addr, l_port, *r_addr, r_port, fib_index, proto);
 
       if (PREDICT_FALSE
          (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)))
@@ -391,7 +386,7 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
   /* session lookup tables */
   if (is_affinity_sessions (s))
     nat_affinity_unlock (s->ext_host_addr, s->out2in.addr,
-                        s->in2out.protocol, s->out2in.port);
+                        s->nat_proto, s->out2in.port);
   l_addr = &s->out2in.addr;
   r_addr = &s->ext_host_addr;
   fib_index = s->out2in.fib_index;
@@ -403,12 +398,11 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
     }
   else
     {
-      proto = nat_proto_to_ip_proto (s->in2out.protocol);
+      proto = nat_proto_to_ip_proto (s->nat_proto);
       l_port = s->out2in.port;
       r_port = s->ext_host_port;
     }
-  make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0, ~0,
-             &ed_kv);
+  init_ed_k (&ed_kv, *l_addr, l_port, *r_addr, r_port, fib_index, proto);
 
   if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&sm->out2in_ed, &ed_kv, 0)))
     nat_elog_warn ("out2in_ed key del failed");
@@ -424,8 +418,7 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
       r_addr = &s->ext_host_nat_addr;
       r_port = s->ext_host_nat_port;
     }
-  make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0, ~0,
-             &ed_kv);
+  init_ed_k (&ed_kv, *l_addr, l_port, *r_addr, r_port, fib_index, proto);
 
   if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)))
     nat_elog_warn ("in2out_ed key del failed");
@@ -437,7 +430,7 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
                             &s->ext_host_nat_addr, s->ext_host_nat_port,
                             &s->out2in.addr, s->out2in.port,
                             &s->ext_host_addr, s->ext_host_port,
-                            s->in2out.protocol, is_twice_nat_session (s));
+                            s->nat_proto, is_twice_nat_session (s));
     }
 
   if (snat_is_unk_proto_session (s))
@@ -448,30 +441,30 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
       snat_ipfix_logging_nat44_ses_delete (thread_index,
                                           s->in2out.addr.as_u32,
                                           s->out2in.addr.as_u32,
-                                          s->in2out.protocol,
+                                          s->nat_proto,
                                           s->in2out.port,
                                           s->out2in.port,
                                           s->in2out.fib_index);
       nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
-                  s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
+                  s->ext_host_port, s->nat_proto, s->out2in.fib_index,
                   thread_index);
     }
 
   /* Twice NAT address and port for external host */
   if (is_twice_nat_session (s))
     {
-      key.protocol = s->in2out.protocol;
-      key.port = s->ext_host_nat_port;
-      key.addr.as_u32 = s->ext_host_nat_addr.as_u32;
       snat_free_outside_address_and_port (sm->twice_nat_addresses,
-                                         thread_index, &key);
+                                         thread_index,
+                                         &s->ext_host_nat_addr,
+                                         s->ext_host_nat_port, s->nat_proto);
     }
 
   if (snat_is_session_static (s))
     return;
 
   snat_free_outside_address_and_port (sm->addresses, thread_index,
-                                     &s->out2in);
+                                     &s->out2in.addr, s->out2in.port,
+                                     s->nat_proto);
 }
 
 
@@ -790,7 +783,7 @@ snat_static_mapping_del_sessions (snat_main_t * sm,
              if (!addr_only)
                {
                  if ((s->out2in.addr.as_u32 != e_addr.as_u32) ||
-                     (clib_net_to_host_u16 (s->out2in.port) != e_port))
+                     (s->out2in.port != e_port))
                    continue;
                }
 
@@ -831,9 +824,9 @@ snat_ed_static_mapping_del_sessions (snat_main_t * sm,
     if (!addr_only)
       {
         if ((s->out2in.addr.as_u32 != e_addr.as_u32) ||
-            (clib_net_to_host_u16 (s->out2in.port) != e_port) ||
-            clib_net_to_host_u16 (s->in2out.port) != l_port ||
-            s->in2out.protocol != protocol)
+            s->out2in.port != e_port ||
+            s->in2out.port != l_port ||
+            s->nat_proto != protocol)
           continue;
       }
 
@@ -865,7 +858,6 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
 {
   snat_main_t *sm = &snat_main;
   snat_static_mapping_t *m;
-  snat_session_key_t m_key;
   clib_bihash_kv_8_8_t kv, value;
   snat_address_t *a = 0;
   u32 fib_index = ~0;
@@ -958,11 +950,7 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
        }
     }
 
-  m_key.addr = e_addr;
-  m_key.port = addr_only ? 0 : e_port;
-  m_key.protocol = addr_only ? 0 : proto;
-  m_key.fib_index = 0;
-  kv.key = m_key.as_u64;
+  init_nat_k (&kv, e_addr, addr_only ? 0 : e_port, 0, addr_only ? 0 : proto);
   if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
     m = 0;
   else
@@ -986,12 +974,9 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
              local->fib_index =
                fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
                                                   nat_fib_src_low);
-             m_key.addr = m->local_addr;
-             m_key.port = m->local_port;
-             m_key.protocol = m->proto;
-             m_key.fib_index = local->fib_index;
-             kv.key = m_key.as_u64;
-             kv.value = m - sm->static_mappings;
+             init_nat_kv (&kv, m->local_addr, m->local_port,
+                          local->fib_index, m->proto,
+                          m - sm->static_mappings);
              clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
              return 0;
            }
@@ -1017,11 +1002,8 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
 
       if (!(out2in_only || identity_nat))
        {
-         m_key.addr = l_addr;
-         m_key.port = addr_only ? 0 : l_port;
-         m_key.protocol = addr_only ? 0 : proto;
-         m_key.fib_index = fib_index;
-         kv.key = m_key.as_u64;
+         init_nat_k (&kv, l_addr, addr_only ? 0 : l_port, fib_index,
+                     addr_only ? 0 : proto);
          if (!clib_bihash_search_8_8
              (&sm->static_mapping_by_local, &kv, &value))
            return VNET_API_ERROR_VALUE_EXIST;
@@ -1123,20 +1105,13 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
       else
        tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
 
-      m_key.addr = m->local_addr;
-      m_key.port = m->local_port;
-      m_key.protocol = m->proto;
-      m_key.fib_index = fib_index;
-      kv.key = m_key.as_u64;
-      kv.value = m - sm->static_mappings;
+      init_nat_kv (&kv, m->local_addr, m->local_port, fib_index, m->proto,
+                  m - sm->static_mappings);
       if (!out2in_only)
        clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
 
-      m_key.addr = m->external_addr;
-      m_key.port = m->external_port;
-      m_key.fib_index = 0;
-      kv.key = m_key.as_u64;
-      kv.value = m - sm->static_mappings;
+      init_nat_kv (&kv, m->external_addr, m->external_port, 0, m->proto,
+                  m - sm->static_mappings);
       clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1);
 
       /* Delete dynamic sessions matching local address (+ local port) */
@@ -1165,9 +1140,7 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
                      if (snat_is_session_static (s))
                        continue;
 
-                     if (!addr_only
-                         && (clib_net_to_host_u16 (s->in2out.port) !=
-                             m->local_port))
+                     if (!addr_only && s->in2out.port != m->local_port)
                        continue;
 
                      nat_free_session_data (sm, s,
@@ -1248,11 +1221,7 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
       else
        tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
 
-      m_key.addr = m->local_addr;
-      m_key.port = m->local_port;
-      m_key.protocol = m->proto;
-      m_key.fib_index = fib_index;
-      kv.key = m_key.as_u64;
+      init_nat_k (&kv, m->local_addr, m->local_port, fib_index, m->proto);
       if (!out2in_only)
        clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0);
 
@@ -1281,10 +1250,7 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
       if (pool_elts (m->locals))
        return 0;
 
-      m_key.addr = m->external_addr;
-      m_key.port = m->external_port;
-      m_key.fib_index = 0;
-      kv.key = m_key.as_u64;
+      init_nat_k (&kv, m->external_addr, m->external_port, 0, m->proto);
       clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0);
 
       vec_free (m->tag);
@@ -1328,7 +1294,6 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
 {
   snat_main_t *sm = &snat_main;
   snat_static_mapping_t *m;
-  snat_session_key_t m_key;
   clib_bihash_kv_8_8_t kv, value;
   snat_address_t *a = 0;
   int i;
@@ -1340,11 +1305,7 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
   if (!sm->endpoint_dependent)
     return VNET_API_ERROR_FEATURE_DISABLED;
 
-  m_key.addr = e_addr;
-  m_key.port = e_port;
-  m_key.protocol = proto;
-  m_key.fib_index = 0;
-  kv.key = m_key.as_u64;
+  init_nat_k (&kv, e_addr, e_port, 0, proto);
   if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
     m = 0;
   else
@@ -1413,32 +1374,25 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
       else
        m->affinity_per_service_list_head_index = ~0;
 
-      m_key.addr = m->external_addr;
-      m_key.port = m->external_port;
-      m_key.protocol = m->proto;
-      m_key.fib_index = 0;
-      kv.key = m_key.as_u64;
-      kv.value = m - sm->static_mappings;
+      init_nat_kv (&kv, m->external_addr, m->external_port, 0, m->proto,
+                  m - sm->static_mappings);
       if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1))
        {
          nat_elog_err ("static_mapping_by_external key add failed");
          return VNET_API_ERROR_UNSPECIFIED;
        }
 
-      m_key.fib_index = m->fib_index;
       for (i = 0; i < vec_len (locals); i++)
        {
          locals[i].fib_index =
            fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
                                               locals[i].vrf_id,
                                               nat_fib_src_low);
-         m_key.addr = locals[i].addr;
-         m_key.fib_index = locals[i].fib_index;
          if (!out2in_only)
            {
-             m_key.port = locals[i].port;
-             kv.key = m_key.as_u64;
-             kv.value = m - sm->static_mappings;
+             init_nat_kv (&kv, locals[i].addr, locals[i].port,
+                          locals[i].fib_index, m->proto,
+                          m - sm->static_mappings);
              clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
            }
          locals[i].prefix = (i == 0) ? locals[i].probability :
@@ -1506,11 +1460,7 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
            }
        }
 
-      m_key.addr = m->external_addr;
-      m_key.port = m->external_port;
-      m_key.protocol = m->proto;
-      m_key.fib_index = 0;
-      kv.key = m_key.as_u64;
+      init_nat_k (&kv, m->external_addr, m->external_port, 0, m->proto);
       if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0))
        {
          nat_elog_err ("static_mapping_by_external key del failed");
@@ -1522,12 +1472,9 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
       ({
           fib_table_unlock (local->fib_index, FIB_PROTOCOL_IP4,
                             nat_fib_src_low);
-          m_key.addr = local->addr;
           if (!out2in_only)
             {
-              m_key.port = local->port;
-              m_key.fib_index = local->fib_index;
-              kv.key = m_key.as_u64;
+init_nat_k(&              kv, local->addr, local->port, local->fib_index, m->proto);
               if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0))
                 {
                   nat_elog_err ("static_mapping_by_local key del failed");
@@ -1552,7 +1499,7 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
               continue;
 
             if ((s->in2out.addr.as_u32 != local->addr.as_u32) ||
-                (clib_net_to_host_u16 (s->in2out.port) != local->port))
+                s->in2out.port != local->port)
               continue;
 
             nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
@@ -1580,7 +1527,6 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
 {
   snat_main_t *sm = &snat_main;
   snat_static_mapping_t *m = 0;
-  snat_session_key_t m_key;
   clib_bihash_kv_8_8_t kv, value;
   nat44_lb_addr_port_t *local, *prev_local, *match_local = 0;
   snat_main_per_thread_data_t *tsm;
@@ -1592,11 +1538,7 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
   if (!sm->endpoint_dependent)
     return VNET_API_ERROR_FEATURE_DISABLED;
 
-  m_key.addr = e_addr;
-  m_key.port = e_port;
-  m_key.protocol = proto;
-  m_key.fib_index = 0;
-  kv.key = m_key.as_u64;
+  init_nat_k (&kv, e_addr, e_port, 0, proto);
   if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
     m = pool_elt_at_index (sm->static_mappings, value.value);
 
@@ -1635,11 +1577,8 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
 
       if (!is_out2in_only_static_mapping (m))
        {
-         m_key.addr = l_addr;
-         m_key.port = l_port;
-         m_key.fib_index = local->fib_index;
-         kv.key = m_key.as_u64;
-         kv.value = m - sm->static_mappings;
+         init_nat_kv (&kv, l_addr, l_port, local->fib_index, proto,
+                      m - sm->static_mappings);
          if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1))
            nat_elog_err ("static_mapping_by_local key add failed");
        }
@@ -1657,10 +1596,7 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
 
       if (!is_out2in_only_static_mapping (m))
        {
-         m_key.addr = l_addr;
-         m_key.port = l_port;
-         m_key.fib_index = match_local->fib_index;
-         kv.key = m_key.as_u64;
+         init_nat_k (&kv, l_addr, l_port, match_local->fib_index, proto);
          if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0))
            nat_elog_err ("static_mapping_by_local key del failed");
        }
@@ -1684,7 +1620,7 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
           continue;
 
         if ((s->in2out.addr.as_u32 != match_local->addr.as_u32) ||
-            (clib_net_to_host_u16 (s->in2out.port) != match_local->port))
+            s->in2out.port != match_local->port)
           continue;
 
         nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
@@ -2441,14 +2377,13 @@ nat_ip4_add_del_addr_only_sm_cb (ip4_main_t * im,
                                 u32 if_address_index, u32 is_delete);
 
 static int
-nat_alloc_addr_and_port_default (snat_address_t * addresses,
-                                u32 fib_index,
-                                u32 thread_index,
-                                snat_session_key_t * k,
+nat_alloc_addr_and_port_default (snat_address_t * addresses, u32 fib_index,
+                                u32 thread_index, nat_protocol_t proto,
+                                ip4_address_t * addr, u16 * port,
                                 u16 port_per_thread, u32 snat_thread_index);
 
 void
-test_ed_make_split ()
+test_key_calc_split ()
 {
   ip4_address_t l_addr;
   l_addr.as_u8[0] = 1;
@@ -2467,8 +2402,8 @@ test_ed_make_split ()
   u32 thread_index = 3000000001;
   u32 session_index = 3000000221;
   clib_bihash_kv_16_8_t kv;
-  make_ed_kv (&l_addr, &r_addr, proto, fib_index, l_port, r_port,
-             thread_index, session_index, &kv);
+  init_ed_kv (&kv, l_addr, l_port, r_addr, r_port, fib_index, proto,
+             thread_index, session_index);
   ip4_address_t l_addr2;
   ip4_address_t r_addr2;
   clib_memset (&l_addr2, 0, sizeof (l_addr2));
@@ -2487,6 +2422,16 @@ test_ed_make_split ()
   ASSERT (fib_index == fib_index2);
   ASSERT (thread_index == ed_value_get_thread_index (&kv));
   ASSERT (session_index == ed_value_get_session_index (&kv));
+
+  fib_index = 7001;
+  proto = 5;
+  nat_protocol_t proto3 = ~0;
+  u64 key = calc_nat_key (l_addr, l_port, fib_index, proto);
+  split_nat_key (key, &l_addr2, &l_port2, &fib_index2, &proto3);
+  ASSERT (l_addr.as_u32 == l_addr2.as_u32);
+  ASSERT (l_port == l_port2);
+  ASSERT (proto == proto3);
+  ASSERT (fib_index == fib_index2);
 }
 
 static clib_error_t *
@@ -2656,7 +2601,7 @@ snat_init (vlib_main_t * vm)
                                         FIB_SOURCE_PRIORITY_LOW,
                                         FIB_SOURCE_BH_SIMPLE);
 
-  test_ed_make_split ();
+  test_key_calc_split ();
   return error;
 }
 
@@ -2664,16 +2609,18 @@ VLIB_INIT_FUNCTION (snat_init);
 
 void
 snat_free_outside_address_and_port (snat_address_t * addresses,
-                                   u32 thread_index, snat_session_key_t * k)
+                                   u32 thread_index,
+                                   ip4_address_t * addr,
+                                   u16 port, nat_protocol_t protocol)
 {
   snat_address_t *a;
   u32 address_index;
-  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
+  u16 port_host_byte_order = clib_net_to_host_u16 (port);
 
   for (address_index = 0; address_index < vec_len (addresses);
        address_index++)
     {
-      if (addresses[address_index].addr.as_u32 == k->addr.as_u32)
+      if (addresses[address_index].addr.as_u32 == addr->as_u32)
        break;
     }
 
@@ -2681,7 +2628,7 @@ snat_free_outside_address_and_port (snat_address_t * addresses,
 
   a = addresses + address_index;
 
-  switch (k->protocol)
+  switch (protocol)
     {
 #define _(N, i, n, s) \
     case NAT_PROTOCOL_##N: \
@@ -2700,20 +2647,21 @@ snat_free_outside_address_and_port (snat_address_t * addresses,
 
 static int
 nat_set_outside_address_and_port (snat_address_t * addresses,
-                                 u32 thread_index, snat_session_key_t * k)
+                                 u32 thread_index, ip4_address_t addr,
+                                 u16 port, nat_protocol_t protocol)
 {
   snat_address_t *a = 0;
   u32 address_index;
-  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
+  u16 port_host_byte_order = clib_net_to_host_u16 (port);
 
   for (address_index = 0; address_index < vec_len (addresses);
        address_index++)
     {
-      if (addresses[address_index].addr.as_u32 != k->addr.as_u32)
+      if (addresses[address_index].addr.as_u32 != addr.as_u32)
        continue;
 
       a = addresses + address_index;
-      switch (k->protocol)
+      switch (protocol)
        {
 #define _(N, j, n, s) \
         case NAT_PROTOCOL_##N: \
@@ -2736,8 +2684,13 @@ nat_set_outside_address_and_port (snat_address_t * addresses,
 
 int
 snat_static_mapping_match (snat_main_t * sm,
-                          snat_session_key_t match,
-                          snat_session_key_t * mapping,
+                          ip4_address_t match_addr,
+                          u16 match_port,
+                          u32 match_fib_index,
+                          nat_protocol_t match_protocol,
+                          ip4_address_t * mapping_addr,
+                          u16 * mapping_port,
+                          u32 * mapping_fib_index,
                           u8 by_external,
                           u8 * is_addr_only,
                           twice_nat_type_t * twice_nat,
@@ -2746,33 +2699,36 @@ snat_static_mapping_match (snat_main_t * sm,
 {
   clib_bihash_kv_8_8_t kv, value;
   snat_static_mapping_t *m;
-  snat_session_key_t m_key;
   clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
   u32 rand, lo = 0, hi, mid, *tmp = 0, i;
   u8 backend_index;
   nat44_lb_addr_port_t *local;
 
-  m_key.fib_index = match.fib_index;
   if (by_external)
     {
       mapping_hash = &sm->static_mapping_by_external;
-      m_key.fib_index = 0;
-    }
-
-  m_key.addr = match.addr;
-  m_key.port = clib_net_to_host_u16 (match.port);
-  m_key.protocol = match.protocol;
-
-  kv.key = m_key.as_u64;
+      init_nat_k (&kv, match_addr, match_port, 0, match_protocol);
+      if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
+       {
+         /* Try address only mapping */
+         init_nat_k (&kv, match_addr, 0, 0, 0);
+         if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
+           return 1;
+       }
 
-  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
+    }
+  else
     {
-      /* Try address only mapping */
-      m_key.port = 0;
-      m_key.protocol = 0;
-      kv.key = m_key.as_u64;
+      init_nat_k (&kv, match_addr, match_port, match_fib_index,
+                 match_protocol);
       if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
-       return 1;
+       {
+         /* Try address only mapping */
+         init_nat_k (&kv, match_addr, 0, match_fib_index, 0);
+         if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
+           return 1;
+       }
+
     }
 
   m = pool_elt_at_index (sm->static_mappings, value.value);
@@ -2784,15 +2740,15 @@ snat_static_mapping_match (snat_main_t * sm,
          if (PREDICT_FALSE (lb != 0))
            *lb = m->affinity ? AFFINITY_LB_NAT : LB_NAT;
          if (m->affinity && !nat_affinity_find_and_lock (ext_host_addr[0],
-                                                         match.addr,
-                                                         match.protocol,
-                                                         match.port,
+                                                         match_addr,
+                                                         match_protocol,
+                                                         match_port,
                                                          &backend_index))
            {
              local = pool_elt_at_index (m->locals, backend_index);
-             mapping->addr = local->addr;
-             mapping->port = clib_host_to_net_u16 (local->port);
-             mapping->fib_index = local->fib_index;
+             *mapping_addr = local->addr;
+             *mapping_port = local->port;
+             *mapping_fib_index = local->fib_index;
              goto end;
            }
          // pick locals matching this worker
@@ -2838,13 +2794,13 @@ snat_static_mapping_match (snat_main_t * sm,
          local = pool_elt_at_index (m->locals, tmp[lo]);
          if (!(local->prefix >= rand))
            return 1;
-         mapping->addr = local->addr;
-         mapping->port = clib_host_to_net_u16 (local->port);
-         mapping->fib_index = local->fib_index;
+         *mapping_addr = local->addr;
+         *mapping_port = local->port;
+         *mapping_fib_index = local->fib_index;
          if (m->affinity)
            {
-             if (nat_affinity_create_and_lock (ext_host_addr[0], match.addr,
-                                               match.protocol, match.port,
+             if (nat_affinity_create_and_lock (ext_host_addr[0], match_addr,
+                                               match_protocol, match_port,
                                                tmp[lo], m->affinity,
                                                m->affinity_per_service_list_head_index))
                nat_elog_info ("create affinity record failed");
@@ -2855,21 +2811,20 @@ snat_static_mapping_match (snat_main_t * sm,
        {
          if (PREDICT_FALSE (lb != 0))
            *lb = NO_LB_NAT;
-         mapping->fib_index = m->fib_index;
-         mapping->addr = m->local_addr;
+         *mapping_fib_index = m->fib_index;
+         *mapping_addr = m->local_addr;
          /* Address only mapping doesn't change port */
-         mapping->port = is_addr_only_static_mapping (m) ? match.port
-           : clib_host_to_net_u16 (m->local_port);
+         *mapping_port = is_addr_only_static_mapping (m) ? match_port
+           : m->local_port;
        }
-      mapping->protocol = m->proto;
     }
   else
     {
-      mapping->addr = m->external_addr;
+      *mapping_addr = m->external_addr;
       /* Address only mapping doesn't change port */
-      mapping->port = is_addr_only_static_mapping (m) ? match.port
-       : clib_host_to_net_u16 (m->external_port);
-      mapping->fib_index = sm->outside_fib_index;
+      *mapping_port = is_addr_only_static_mapping (m) ? match_port
+       : m->external_port;
+      *mapping_fib_index = sm->outside_fib_index;
     }
 
 end:
@@ -2897,21 +2852,26 @@ int
 snat_alloc_outside_address_and_port (snat_address_t * addresses,
                                     u32 fib_index,
                                     u32 thread_index,
-                                    snat_session_key_t * k,
+                                    nat_protocol_t proto,
+                                    ip4_address_t * addr,
+                                    u16 * port,
                                     u16 port_per_thread,
                                     u32 snat_thread_index)
 {
   snat_main_t *sm = &snat_main;
 
-  return sm->alloc_addr_and_port (addresses, fib_index, thread_index, k,
-                                 port_per_thread, snat_thread_index);
+  return sm->alloc_addr_and_port (addresses, fib_index, thread_index, proto,
+                                 addr, port, port_per_thread,
+                                 snat_thread_index);
 }
 
 static int
 nat_alloc_addr_and_port_default (snat_address_t * addresses,
                                 u32 fib_index,
                                 u32 thread_index,
-                                snat_session_key_t * k,
+                                nat_protocol_t proto,
+                                ip4_address_t * addr,
+                                u16 * port,
                                 u16 port_per_thread, u32 snat_thread_index)
 {
   int i;
@@ -2921,7 +2881,7 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses,
   for (i = 0; i < vec_len (addresses); i++)
     {
       a = addresses + i;
-      switch (k->protocol)
+      switch (proto)
        {
 #define _(N, j, n, s) \
         case NAT_PROTOCOL_##N: \
@@ -2939,8 +2899,8 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses,
                      --a->busy_##n##_port_refcounts[portnum]; \
                       a->busy_##n##_ports_per_thread[thread_index]++; \
                       a->busy_##n##_ports++; \
-                      k->addr = a->addr; \
-                      k->port = clib_host_to_net_u16(portnum); \
+                      *addr = a->addr; \
+                      *port = clib_host_to_net_u16(portnum); \
                       return 0; \
                     } \
                 } \
@@ -2962,7 +2922,7 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses,
   if (ga)
     {
       a = ga;
-      switch (k->protocol)
+      switch (proto)
        {
 #define _(N, j, n, s) \
         case NAT_PROTOCOL_##N: \
@@ -2976,8 +2936,8 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses,
              ++a->busy_##n##_port_refcounts[portnum]; \
               a->busy_##n##_ports_per_thread[thread_index]++; \
               a->busy_##n##_ports++; \
-              k->addr = a->addr; \
-              k->port = clib_host_to_net_u16(portnum); \
+              *addr = a->addr; \
+              *port = clib_host_to_net_u16(portnum); \
               return 0; \
             }
          break;
@@ -2995,10 +2955,9 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses,
 }
 
 static int
-nat_alloc_addr_and_port_mape (snat_address_t * addresses,
-                             u32 fib_index,
-                             u32 thread_index,
-                             snat_session_key_t * k,
+nat_alloc_addr_and_port_mape (snat_address_t * addresses, u32 fib_index,
+                             u32 thread_index, nat_protocol_t proto,
+                             ip4_address_t * addr, u16 * port,
                              u16 port_per_thread, u32 snat_thread_index)
 {
   snat_main_t *sm = &snat_main;
@@ -3010,7 +2969,7 @@ nat_alloc_addr_and_port_mape (snat_address_t * addresses,
   if (!vec_len (addresses))
     goto exhausted;
 
-  switch (k->protocol)
+  switch (proto)
     {
 #define _(N, i, n, s) \
     case NAT_PROTOCOL_##N: \
@@ -3025,8 +2984,8 @@ nat_alloc_addr_and_port_mape (snat_address_t * addresses,
                 continue; \
              ++a->busy_##n##_port_refcounts[portnum]; \
               a->busy_##n##_ports++; \
-              k->addr = a->addr; \
-              k->port = clib_host_to_net_u16 (portnum); \
+              *addr = a->addr; \
+              *port = clib_host_to_net_u16 (portnum); \
               return 0; \
             } \
         } \
@@ -3045,10 +3004,9 @@ exhausted:
 }
 
 static int
-nat_alloc_addr_and_port_range (snat_address_t * addresses,
-                              u32 fib_index,
-                              u32 thread_index,
-                              snat_session_key_t * k,
+nat_alloc_addr_and_port_range (snat_address_t * addresses, u32 fib_index,
+                              u32 thread_index, nat_protocol_t proto,
+                              ip4_address_t * addr, u16 * port,
                               u16 port_per_thread, u32 snat_thread_index)
 {
   snat_main_t *sm = &snat_main;
@@ -3060,7 +3018,7 @@ nat_alloc_addr_and_port_range (snat_address_t * addresses,
   if (!vec_len (addresses))
     goto exhausted;
 
-  switch (k->protocol)
+  switch (proto)
     {
 #define _(N, i, n, s) \
     case NAT_PROTOCOL_##N: \
@@ -3073,8 +3031,8 @@ nat_alloc_addr_and_port_range (snat_address_t * addresses,
                 continue; \
              ++a->busy_##n##_port_refcounts[portnum]; \
               a->busy_##n##_ports++; \
-              k->addr = a->addr; \
-              k->port = clib_host_to_net_u16 (portnum); \
+              *addr = a->addr; \
+              *port = clib_host_to_net_u16 (portnum); \
               return 0; \
             } \
         } \
@@ -3119,11 +3077,8 @@ u8 *
 format_session_kvp (u8 * s, va_list * args)
 {
   clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
-  snat_session_key_t k;
 
-  k.as_u64 = v->key;
-
-  s = format (s, "%U session-index %llu", format_snat_key, &k, v->value);
+  s = format (s, "%U session-index %llu", format_snat_key, v->key, v->value);
 
   return s;
 }
@@ -3132,12 +3087,9 @@ u8 *
 format_static_mapping_kvp (u8 * s, va_list * args)
 {
   clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
-  snat_session_key_t k;
-
-  k.as_u64 = v->key;
 
   s = format (s, "%U static-mapping-index %llu",
-             format_static_mapping_key, &k, v->value);
+             format_snat_key, v->key, v->value);
 
   return s;
 }
@@ -3205,7 +3157,6 @@ snat_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip0,
   snat_main_t *sm = &snat_main;
   udp_header_t *udp;
   u16 port;
-  snat_session_key_t m_key;
   clib_bihash_kv_8_8_t kv, value;
   snat_static_mapping_t *m;
   u32 proto;
@@ -3214,11 +3165,7 @@ snat_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip0,
   /* first try static mappings without port */
   if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
     {
-      m_key.addr = ip0->dst_address;
-      m_key.port = 0;
-      m_key.protocol = 0;
-      m_key.fib_index = rx_fib_index0;
-      kv.key = m_key.as_u64;
+      init_nat_k (&kv, ip0->dst_address, 0, rx_fib_index0, 0);
       if (!clib_bihash_search_8_8
          (&sm->static_mapping_by_external, &kv, &value))
        {
@@ -3271,11 +3218,7 @@ snat_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip0,
   /* try static mappings with port */
   if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
     {
-      m_key.addr = ip0->dst_address;
-      m_key.port = clib_net_to_host_u16 (port);
-      m_key.protocol = proto;
-      m_key.fib_index = rx_fib_index0;
-      kv.key = m_key.as_u64;
+      init_nat_k (&kv, ip0->dst_address, port, rx_fib_index0, proto);
       if (!clib_bihash_search_8_8
          (&sm->static_mapping_by_external, &kv, &value))
        {
@@ -3345,9 +3288,8 @@ nat44_ed_get_worker_in2out_cb (ip4_header_t * ip, u32 rx_fib_index,
          break;
        }
 
-      make_ed_kv (&ip->src_address, &ip->dst_address,
-                 ip->protocol, fib_index, udp->src_port, udp->dst_port,
-                 ~0, ~0, &kv16);
+      init_ed_k (&kv16, ip->src_address, udp->src_port, ip->dst_address,
+                udp->dst_port, fib_index, ip->protocol);
 
       if (PREDICT_TRUE (!clib_bihash_search_16_8 (&sm->out2in_ed,
                                                  &kv16, &value16)))
@@ -3415,9 +3357,8 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip,
     {
       udp = ip4_next_header (ip);
 
-      make_ed_kv (&ip->dst_address, &ip->src_address,
-                 ip->protocol, rx_fib_index, udp->dst_port, udp->src_port,
-                 ~0, ~0, &kv16);
+      init_ed_k (&kv16, ip->dst_address, udp->dst_port, ip->src_address,
+                udp->src_port, rx_fib_index, ip->protocol);
 
       if (PREDICT_TRUE (!clib_bihash_search_16_8 (&sm->out2in_ed,
                                                  &kv16, &value16)))
@@ -3462,7 +3403,7 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip,
   /* first try static mappings without port */
   if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
     {
-      make_sm_kv (&kv, &ip->dst_address, 0, 0, 0);
+      init_nat_k (&kv, ip->dst_address, 0, 0, 0);
       if (!clib_bihash_search_8_8
          (&sm->static_mapping_by_external, &kv, &value))
        {
@@ -3517,8 +3458,7 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip,
   /* try static mappings with port */
   if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
     {
-      make_sm_kv (&kv, &ip->dst_address, proto, 0,
-                 clib_net_to_host_u16 (port));
+      init_nat_k (&kv, ip->dst_address, proto, 0, port);
       if (!clib_bihash_search_8_8
          (&sm->static_mapping_by_external, &kv, &value))
        {
@@ -3562,7 +3502,6 @@ nat_ha_sadd_cb (ip4_address_t * in_addr, u16 in_port,
 {
   snat_main_t *sm = &snat_main;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
-  snat_session_key_t key;
   snat_user_t *u;
   snat_session_t *s;
   clib_bihash_kv_8_8_t kv;
@@ -3578,14 +3517,10 @@ nat_ha_sadd_cb (ip4_address_t * in_addr, u16 in_port,
                },
   };
 
-  key.addr.as_u32 = out_addr->as_u32;
-  key.port = out_port;
-  key.protocol = proto;
-
   if (!(flags & SNAT_SESSION_FLAG_STATIC_MAPPING))
     {
       if (nat_set_outside_address_and_port
-         (sm->addresses, thread_index, &key))
+         (sm->addresses, thread_index, *out_addr, out_port, proto))
        return;
     }
 
@@ -3599,9 +3534,12 @@ nat_ha_sadd_cb (ip4_address_t * in_addr, u16 in_port,
 
   if (sm->endpoint_dependent)
     {
-      nat_ed_lru_insert (tsm, s, now, proto);
+      nat_ed_lru_insert (tsm, s, now, nat_proto_to_ip_proto (proto));
     }
 
+  s->out2in.addr.as_u32 = out_addr->as_u32;
+  s->out2in.port = out_port;
+  s->nat_proto = proto;
   s->last_heard = now;
   s->flags = flags;
   s->ext_host_addr.as_u32 = eh_addr->as_u32;
@@ -3610,10 +3548,10 @@ nat_ha_sadd_cb (ip4_address_t * in_addr, u16 in_port,
   switch (vec_len (sm->outside_fibs))
     {
     case 0:
-      key.fib_index = sm->outside_fib_index;
+      s->out2in.fib_index = sm->outside_fib_index;
       break;
     case 1:
-      key.fib_index = sm->outside_fibs[0].fib_index;
+      s->out2in.fib_index = sm->outside_fibs[0].fib_index;
       break;
     default:
       /* *INDENT-OFF* */
@@ -3624,7 +3562,7 @@ nat_ha_sadd_cb (ip4_address_t * in_addr, u16 in_port,
             {
               if (fib_entry_get_resolving_interface (fei) != ~0)
                 {
-                  key.fib_index = outside_fib->fib_index;
+                  s->out2in.fib_index = outside_fib->fib_index;
                   break;
                 }
             }
@@ -3632,17 +3570,14 @@ nat_ha_sadd_cb (ip4_address_t * in_addr, u16 in_port,
       /* *INDENT-ON* */
       break;
     }
-  s->out2in = key;
-  kv.key = key.as_u64;
-  kv.value = s - tsm->sessions;
+  init_nat_o2i_kv (&kv, s, s - tsm->sessions);
   if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 1))
     nat_elog_warn ("out2in key add failed");
 
-  key.addr.as_u32 = in_addr->as_u32;
-  key.port = in_port;
-  key.fib_index = fib_index;
-  s->in2out = key;
-  kv.key = key.as_u64;
+  s->in2out.addr.as_u32 = in_addr->as_u32;
+  s->in2out.port = in_port;
+  s->in2out.fib_index = fib_index;
+  init_nat_i2o_kv (&kv, s, s - tsm->sessions);
   if (clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 1))
     nat_elog_warn ("in2out key add failed");
 }
@@ -3653,7 +3588,6 @@ nat_ha_sdel_cb (ip4_address_t * out_addr, u16 out_port,
                u32 ti)
 {
   snat_main_t *sm = &snat_main;
-  snat_session_key_t key;
   clib_bihash_kv_8_8_t kv, value;
   u32 thread_index;
   snat_session_t *s;
@@ -3668,11 +3602,7 @@ nat_ha_sdel_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.addr.as_u32 = out_addr->as_u32;
-  key.port = out_port;
-  key.protocol = proto;
-  key.fib_index = fib_index;
-  kv.key = key.as_u64;
+  init_nat_k (&kv, *out_addr, out_port, fib_index, proto);
   if (clib_bihash_search_8_8 (&tsm->out2in, &kv, &value))
     return;
 
@@ -3687,18 +3617,13 @@ nat_ha_sref_cb (ip4_address_t * out_addr, u16 out_port,
                u32 total_pkts, u64 total_bytes, u32 thread_index)
 {
   snat_main_t *sm = &snat_main;
-  snat_session_key_t key;
   clib_bihash_kv_8_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.addr.as_u32 = out_addr->as_u32;
-  key.port = out_port;
-  key.protocol = proto;
-  key.fib_index = fib_index;
-  kv.key = key.as_u64;
+  init_nat_k (&kv, *out_addr, out_port, fib_index, proto);
   if (clib_bihash_search_8_8 (&tsm->out2in, &kv, &value))
     return;
 
@@ -3716,7 +3641,6 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port,
 {
   snat_main_t *sm = &snat_main;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
-  snat_session_key_t key;
   snat_session_t *s;
   clib_bihash_kv_16_8_t kv;
   vlib_main_t *vm = vlib_get_main ();
@@ -3731,23 +3655,18 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port,
                },
   };
 
-  key.addr.as_u32 = out_addr->as_u32;
-  key.port = out_port;
-  key.protocol = proto;
 
   if (!(flags & SNAT_SESSION_FLAG_STATIC_MAPPING))
     {
       if (nat_set_outside_address_and_port
-         (sm->addresses, thread_index, &key))
+         (sm->addresses, thread_index, *out_addr, out_port, proto))
        return;
     }
 
-  key.addr.as_u32 = ehn_addr->as_u32;
-  key.port = ehn_port;
   if (flags & SNAT_SESSION_FLAG_TWICE_NAT)
     {
       if (nat_set_outside_address_and_port
-         (sm->twice_nat_addresses, thread_index, &key))
+         (sm->addresses, thread_index, *ehn_addr, ehn_port, proto))
        return;
     }
 
@@ -3767,10 +3686,10 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port,
   switch (vec_len (sm->outside_fibs))
     {
     case 0:
-      key.fib_index = sm->outside_fib_index;
+      s->out2in.fib_index = sm->outside_fib_index;
       break;
     case 1:
-      key.fib_index = sm->outside_fibs[0].fib_index;
+      s->out2in.fib_index = sm->outside_fibs[0].fib_index;
       break;
     default:
       /* *INDENT-OFF* */
@@ -3781,7 +3700,7 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port,
             {
               if (fib_entry_get_resolving_interface (fei) != ~0)
                 {
-                  key.fib_index = outside_fib->fib_index;
+                  s->out2in.fib_index = outside_fib->fib_index;
                   break;
                 }
             }
@@ -3789,25 +3708,23 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port,
       /* *INDENT-ON* */
       break;
     }
-  key.addr.as_u32 = out_addr->as_u32;
-  key.port = out_port;
-  s->out2in = key;
-  kv.value = s - tsm->sessions;
-
-  key.addr.as_u32 = in_addr->as_u32;
-  key.port = in_port;
-  key.fib_index = fib_index;
-  s->in2out = key;
-
-  make_ed_kv (in_addr, &s->ext_host_nat_addr,
-             nat_proto_to_ip_proto (proto), fib_index, in_port,
-             s->ext_host_nat_port, thread_index, s - tsm->sessions, &kv);
+  s->nat_proto = proto;
+  s->out2in.addr.as_u32 = out_addr->as_u32;
+  s->out2in.port = out_port;
+
+  s->in2out.addr.as_u32 = in_addr->as_u32;
+  s->in2out.port = in_port;
+  s->in2out.fib_index = fib_index;
+
+  init_ed_kv (&kv, *in_addr, in_port, s->ext_host_nat_addr,
+             s->ext_host_nat_port, fib_index, nat_proto_to_ip_proto (proto),
+             thread_index, s - tsm->sessions);
   if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1))
     nat_elog_warn ("in2out key add failed");
 
-  make_ed_kv (out_addr, eh_addr, nat_proto_to_ip_proto (proto),
-             s->out2in.fib_index, out_port, eh_port, thread_index,
-             s - tsm->sessions, &kv);
+  init_ed_kv (&kv, *out_addr, out_port, *eh_addr, eh_port,
+             s->out2in.fib_index, nat_proto_to_ip_proto (proto),
+             thread_index, s - tsm->sessions);
   if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &kv, 1))
     nat_elog_warn ("out2in key add failed");
 }
@@ -3832,8 +3749,7 @@ 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);
 
-  make_ed_kv (out_addr, eh_addr, proto, fib_index, out_port, eh_port, ~0, ~0,
-             &kv);
+  init_ed_k (&kv, *out_addr, out_port, *eh_addr, eh_port, fib_index, proto);
   if (clib_bihash_search_16_8 (&sm->out2in_ed, &kv, &value))
     return;
 
@@ -3855,8 +3771,7 @@ nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port,
 
   tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
 
-  make_ed_kv (out_addr, eh_addr, proto, fib_index, out_port, eh_port, ~0, ~0,
-             &kv);
+  init_ed_k (&kv, *out_addr, out_port, *eh_addr, eh_port, fib_index, proto);
   if (clib_bihash_search_16_8 (&sm->out2in_ed, &kv, &value))
     return;
 
@@ -4210,7 +4125,6 @@ nat_ip4_add_del_addr_only_sm_cb (ip4_main_t * im,
   snat_main_t *sm = &snat_main;
   snat_static_map_resolve_t *rp;
   snat_static_mapping_t *m;
-  snat_session_key_t m_key;
   clib_bihash_kv_8_8_t kv, value;
   int i, rv;
   ip4_address_t l_addr;
@@ -4227,11 +4141,8 @@ nat_ip4_add_del_addr_only_sm_cb (ip4_main_t * im,
   return;
 
 match:
-  m_key.addr.as_u32 = address->as_u32;
-  m_key.port = rp->addr_only ? 0 : rp->e_port;
-  m_key.protocol = rp->addr_only ? 0 : rp->proto;
-  m_key.fib_index = sm->outside_fib_index;
-  kv.key = m_key.as_u64;
+  init_nat_k (&kv, *address, rp->addr_only ? 0 : rp->e_port,
+             sm->outside_fib_index, rp->addr_only ? 0 : rp->proto);
   if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
     m = 0;
   else
@@ -4425,7 +4336,6 @@ nat44_del_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
   clib_bihash_kv_8_8_t kv, value;
   ip4_header_t ip;
   u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
-  snat_session_key_t key;
   snat_session_t *s;
   clib_bihash_8_8_t *t;
 
@@ -4440,11 +4350,7 @@ nat44_del_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
   else
     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
 
-  key.addr.as_u32 = addr->as_u32;
-  key.port = clib_host_to_net_u16 (port);
-  key.protocol = proto;
-  key.fib_index = fib_index;
-  kv.key = key.as_u64;
+  init_nat_k (&kv, *addr, port, fib_index, proto);
   t = is_in ? &tsm->in2out : &tsm->out2in;
   if (!clib_bihash_search_8_8 (t, &kv, &value))
     {
@@ -4484,8 +4390,7 @@ 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 : &sm->out2in_ed;
-  make_ed_kv (addr, eh_addr, proto, fib_index, clib_host_to_net_u16 (port),
-             clib_host_to_net_u16 (eh_port), ~0, ~0, &kv);
+  init_ed_k (&kv, *addr, port, *eh_addr, eh_port, fib_index, proto);
   if (clib_bihash_search_16_8 (t, &kv, &value))
     {
       return VNET_API_ERROR_NO_SUCH_ENTRY;