NAT44: nat44_del_session and nat44_user_session_details API update (VPP-1271)
[vpp.git] / src / plugins / nat / in2out.c
index 7d9d6c3..1659ed0 100755 (executable)
@@ -498,6 +498,7 @@ nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip,
   udp_header_t *udp;
   snat_session_t *s = 0;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
+  f64 now = vlib_time_now (sm->vlib_main);
 
   if (!sm->forwarding_enabled)
     return 0;
@@ -532,10 +533,19 @@ 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);
+              if (nat44_set_tcp_session_state_i2o (sm, s, tcp, thread_index))
+                return 1;
+            }
           /* 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);
+          /* Accounting */
+          s->last_heard = now;
+          s->total_pkts++;
           return 1;
         }
       else
@@ -1217,34 +1227,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;
@@ -1273,6 +1286,7 @@ create_ses:
 
       s->ext_host_addr.as_u32 = ip->dst_address.as_u32;
       s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO;
+      s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT;
       s->outside_address_index = address_index;
       s->out2in.addr.as_u32 = new_addr;
       s->out2in.fib_index = sm->outside_fib_index;
@@ -1365,7 +1379,18 @@ 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)
+            {
+              if (nat44_set_tcp_session_state_i2o (sm, s, tcp, thread_index))
+                return 0;
+            }
+          /* 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
     {
@@ -1402,6 +1427,7 @@ snat_in2out_lb (snat_main_t *sm,
       s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
       if (lb)
         s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING;
+      s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT;
       s->outside_address_index = ~0;
       s->in2out = l_key;
       s->out2in = e_key;
@@ -1432,6 +1458,9 @@ snat_in2out_lb (snat_main_t *sm,
                           s->ext_host_addr.as_u32, ip4_header_t, dst_address);
   ip->checksum = ip_csum_fold (sum);
 
+  if (vnet_buffer(b)->sw_if_index[VLIB_TX] == ~0)
+    vnet_buffer(b)->sw_if_index[VLIB_TX] = sm->outside_fib_index;
+
   if (PREDICT_TRUE(proto == SNAT_PROTOCOL_TCP))
     {
       old_port = tcp->src_port;
@@ -1452,6 +1481,8 @@ snat_in2out_lb (snat_main_t *sm,
           ip->dst_address.as_u32 = s->ext_host_addr.as_u32;
         }
       tcp->checksum = ip_csum_fold(sum);
+      if (nat44_set_tcp_session_state_i2o (sm, s, tcp, thread_index))
+        return s;
     }
   else
     {
@@ -1464,9 +1495,6 @@ snat_in2out_lb (snat_main_t *sm,
       udp->checksum = 0;
     }
 
-  if (vnet_buffer(b)->sw_if_index[VLIB_TX] == ~0)
-    vnet_buffer(b)->sw_if_index[VLIB_TX] = sm->outside_fib_index;
-
   /* Accounting */
   s->last_heard = now;
   s->total_pkts++;