NAT44: add support for session timeout (VPP-1272)
[vpp.git] / src / plugins / nat / nat_inlines.h
index db5b295..adfb1d5 100644 (file)
@@ -140,6 +140,26 @@ user_session_increment (snat_main_t * sm, snat_user_t * u, u8 is_static)
     }
 }
 
+always_inline void
+nat44_delete_user_with_no_session (snat_main_t * sm, snat_user_t * u,
+                                  u32 thread_index)
+{
+  clib_bihash_kv_8_8_t kv;
+  snat_user_key_t u_key;
+  snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data,
+                                                      thread_index);
+
+  if (u->nstaticsessions == 0 && u->nsessions == 0)
+    {
+      u_key.addr.as_u32 = u->addr.as_u32;
+      u_key.fib_index = u->fib_index;
+      kv.key = u_key.as_u64;
+      pool_put_index (tsm->list_pool, u->sessions_per_user_list_head_index);
+      pool_put (tsm->users, u);
+      clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 0);
+    }
+}
+
 always_inline void
 nat44_delete_session (snat_main_t * sm, snat_session_t * ses,
                      u32 thread_index)
@@ -151,6 +171,11 @@ nat44_delete_session (snat_main_t * sm, snat_session_t * ses,
   snat_user_t *u;
 
   nat_log_debug ("session deleted %U", format_snat_session, tsm, ses);
+
+  clib_dlist_remove (tsm->list_pool, ses->per_user_index);
+  pool_put_index (tsm->list_pool, ses->per_user_index);
+  pool_put (tsm->sessions, ses);
+
   u_key.addr = ses->in2out.addr;
   u_key.fib_index = ses->in2out.fib_index;
   kv.key = u_key.as_u64;
@@ -161,10 +186,9 @@ nat44_delete_session (snat_main_t * sm, snat_session_t * ses,
        u->nstaticsessions--;
       else
        u->nsessions--;
+
+      nat44_delete_user_with_no_session (sm, u, thread_index);
     }
-  clib_dlist_remove (tsm->list_pool, ses->per_user_index);
-  pool_put_index (tsm->list_pool, ses->per_user_index);
-  pool_put (tsm->sessions, ses);
 }
 
 /** \brief Set TCP session state.
@@ -174,6 +198,11 @@ always_inline int
 nat44_set_tcp_session_state_i2o (snat_main_t * sm, snat_session_t * ses,
                                 tcp_header_t * tcp, u32 thread_index)
 {
+  if ((tcp->flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_SYN) &&
+      (ses->state & NAT44_SES_O2I_SYN))
+    ses->state = 0;
+  if (tcp->flags & TCP_FLAG_SYN)
+    ses->state |= NAT44_SES_I2O_SYN;
   if (tcp->flags & TCP_FLAG_FIN)
     {
       ses->i2o_fin_seq = clib_net_to_host_u32 (tcp->seq_number);
@@ -199,6 +228,11 @@ always_inline int
 nat44_set_tcp_session_state_o2i (snat_main_t * sm, snat_session_t * ses,
                                 tcp_header_t * tcp, u32 thread_index)
 {
+  if ((tcp->flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_SYN) &&
+      (ses->state & NAT44_SES_O2I_SYN))
+    ses->state = 0;
+  if (tcp->flags & TCP_FLAG_SYN)
+    ses->state |= NAT44_SES_O2I_SYN;
   if (tcp->flags & TCP_FLAG_FIN)
     {
       ses->o2i_fin_seq = clib_net_to_host_u32 (tcp->seq_number);
@@ -220,6 +254,29 @@ nat44_set_tcp_session_state_o2i (snat_main_t * sm, snat_session_t * ses,
   return 0;
 }
 
+always_inline u32
+nat44_session_get_timeout (snat_main_t * sm, snat_session_t * s)
+{
+  switch (s->in2out.protocol)
+    {
+    case SNAT_PROTOCOL_ICMP:
+      return sm->icmp_timeout;
+    case SNAT_PROTOCOL_UDP:
+      return sm->udp_timeout;
+    case SNAT_PROTOCOL_TCP:
+      {
+       if (s->state)
+         return sm->tcp_transitory_timeout;
+       else
+         return sm->tcp_established_timeout;
+      }
+    default:
+      return sm->udp_timeout;
+    }
+
+  return 0;
+}
+
 always_inline void
 nat44_session_update_counters (snat_session_t * s, f64 now, uword bytes)
 {
@@ -239,6 +296,38 @@ nat44_session_update_lru (snat_main_t * sm, snat_session_t * s,
                      s->per_user_list_head_index, s->per_user_index);
 }
 
+always_inline void
+make_ed_kv (clib_bihash_kv_16_8_t * kv, ip4_address_t * l_addr,
+           ip4_address_t * r_addr, u8 proto, u32 fib_index, u16 l_port,
+           u16 r_port)
+{
+  nat_ed_ses_key_t *key = (nat_ed_ses_key_t *) kv->key;
+
+  key->l_addr.as_u32 = l_addr->as_u32;
+  key->r_addr.as_u32 = r_addr->as_u32;
+  key->fib_index = fib_index;
+  key->proto = proto;
+  key->l_port = l_port;
+  key->r_port = r_port;
+
+  kv->value = ~0ULL;
+}
+
+always_inline void
+make_sm_kv (clib_bihash_kv_8_8_t * kv, ip4_address_t * addr, u8 proto,
+           u32 fib_index, u16 port)
+{
+  snat_session_key_t key;
+
+  key.addr.as_u32 = addr->as_u32;
+  key.port = port;
+  key.protocol = proto;
+  key.fib_index = fib_index;
+
+  kv->key = key.as_u64;
+  kv->value = ~0ULL;
+}
+
 #endif /* __included_nat_inlines_h__ */
 
 /*