NAT44: TCP connection close detection (VPP-1266)
[vpp.git] / src / plugins / nat / in2out.c
index 786b6c6..d3369b6 100755 (executable)
@@ -532,6 +532,11 @@ nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip,
       s = pool_elt_at_index (sm->per_thread_data[thread_index].sessions, value.value);
       if (is_fwd_bypass_session (s))
         {
+          if (ip->protocol == IP_PROTOCOL_TCP)
+            {
+              tcp_header_t *tcp = ip4_next_header(ip);
+              nat44_set_tcp_session_state (sm, s, tcp, thread_index);
+            }
           /* Per-user LRU list maintenance */
           clib_dlist_remove (tsm->list_pool, s->per_user_index);
           clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
@@ -1217,34 +1222,37 @@ snat_in2out_unknown_proto (snat_main_t *sm,
       else
         {
           /* Choose same out address as for TCP/UDP session to same destination */
-          if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
+          head_index = u->sessions_per_user_list_head_index;
+          head = pool_elt_at_index (tsm->list_pool, head_index);
+          elt_index = head->next;
+         if (PREDICT_FALSE (elt_index == ~0))
+           ses_index = ~0;
+         else
+           {
+             elt = pool_elt_at_index (tsm->list_pool, elt_index);
+             ses_index = elt->value;
+           }
+
+          while (ses_index != ~0)
             {
-              head_index = u->sessions_per_user_list_head_index;
-              head = pool_elt_at_index (tsm->list_pool, head_index);
-              elt_index = head->next;
+              s =  pool_elt_at_index (tsm->sessions, ses_index);
+              elt_index = elt->next;
               elt = pool_elt_at_index (tsm->list_pool, elt_index);
               ses_index = elt->value;
-              while (ses_index != ~0)
-                {
-                  s =  pool_elt_at_index (tsm->sessions, ses_index);
-                  elt_index = elt->next;
-                  elt = pool_elt_at_index (tsm->list_pool, elt_index);
-                  ses_index = elt->value;
 
-                  if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32)
-                    {
-                      new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
-                      address_index = s->outside_address_index;
+              if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32)
+                {
+                  new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
+                  address_index = s->outside_address_index;
 
-                      key.fib_index = sm->outside_fib_index;
-                      key.l_addr.as_u32 = new_addr;
-                      s_kv.key[0] = key.as_u64[0];
-                      s_kv.key[1] = key.as_u64[1];
-                      if (clib_bihash_search_16_8 (&sm->out2in_ed, &s_kv, &s_value))
-                        break;
+                  key.fib_index = sm->outside_fib_index;
+                  key.l_addr.as_u32 = new_addr;
+                  s_kv.key[0] = key.as_u64[0];
+                  s_kv.key[1] = key.as_u64[1];
+                  if (clib_bihash_search_16_8 (&sm->out2in_ed, &s_kv, &s_value))
+                    break;
 
-                      goto create_ses;
-                    }
+                  goto create_ses;
                 }
             }
           key.fib_index = sm->outside_fib_index;
@@ -1366,7 +1374,15 @@ snat_in2out_lb (snat_main_t *sm,
     {
       s = pool_elt_at_index (tsm->sessions, s_value.value);
       if (is_fwd_bypass_session (s))
-        return 0;
+        {
+          if (ip->protocol == IP_PROTOCOL_TCP)
+            nat44_set_tcp_session_state (sm, s, tcp, thread_index);
+          /* Per-user LRU list maintenance */
+          clib_dlist_remove (tsm->list_pool, s->per_user_index);
+          clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
+                              s->per_user_index);
+          return 0;
+        }
     }
   else
     {
@@ -1454,6 +1470,7 @@ snat_in2out_lb (snat_main_t *sm,
           ip->dst_address.as_u32 = s->ext_host_addr.as_u32;
         }
       tcp->checksum = ip_csum_fold(sum);
+      nat44_set_tcp_session_state (sm, s, tcp, thread_index);
     }
   else
     {
@@ -1712,6 +1729,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                                      ip4_header_t /* cheat */,
                                      length /* changed member */);
               tcp0->checksum = ip_csum_fold(sum0);
+              nat44_set_tcp_session_state (sm, s0, tcp0, thread_index);
             }
           else
             {
@@ -1904,6 +1922,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                                      ip4_header_t /* cheat */,
                                      length /* changed member */);
               tcp1->checksum = ip_csum_fold(sum1);
+              nat44_set_tcp_session_state (sm, s1, tcp1, thread_index);
             }
           else
             {
@@ -2133,6 +2152,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                                      ip4_header_t /* cheat */,
                                      length /* changed member */);
               tcp0->checksum = ip_csum_fold(sum0);
+              nat44_set_tcp_session_state (sm, s0, tcp0, thread_index);
             }
           else
             {
@@ -2665,6 +2685,7 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm,
                                          ip4_header_t /* cheat */,
                                          length /* changed member */);
                   tcp0->checksum = ip_csum_fold(sum0);
+                  nat44_set_tcp_session_state (sm, s0, tcp0, thread_index);
                 }
               else
                 {