nat: ignore user hash in ED NAT 74/26574/11
authorKlement Sekera <ksekera@cisco.com>
Wed, 15 Apr 2020 13:37:18 +0000 (15:37 +0200)
committerOle Trøan <otroan@employees.org>
Fri, 24 Apr 2020 15:22:24 +0000 (15:22 +0000)
With port overloading, port is no longer a scarce resource and there
is no need to limit connections per internal IP. This saves one hash
insert in slow path.

Type: improvement

Change-Id: I8a7a9713ac855fa99fa1617ec684f757cf6e09ae
Signed-off-by: Klement Sekera <ksekera@cisco.com>
src/plugins/nat/in2out_ed.c
src/plugins/nat/nat.c
src/plugins/nat/nat.h
src/plugins/nat/nat44/inlines.h
src/plugins/nat/nat_api.c
src/plugins/nat/nat_inlines.h
src/plugins/nat/out2in_ed.c
src/plugins/nat/test/test_nat.py

index ca1d0cd..95f80a4 100644 (file)
@@ -152,7 +152,7 @@ nat44_i2o_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg)
       snat_free_outside_address_and_port (sm->addresses, ctx->thread_index,
                                          &s->out2in);
     delete:
-      nat44_delete_session (sm, s, ctx->thread_index);
+      nat44_ed_delete_session (sm, s, ctx->thread_index, 1);
       return 1;
     }
 
@@ -281,9 +281,8 @@ slow_path_ed (snat_main_t * sm,
              vlib_node_runtime_t * node, u32 next, u32 thread_index, f64 now)
 {
   snat_session_t *s = NULL;
-  snat_user_t *u = NULL;
   snat_session_key_t key0, key1;
-  lb_nat_type_t lb = 0, is_sm = 0;
+  lb_nat_type_t lb = 0;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
   nat_ed_ses_key_t *key = (nat_ed_ses_key_t *) kv->key;
   u32 proto = ip_proto_to_snat_proto (key->proto);
@@ -333,16 +332,7 @@ slow_path_ed (snat_main_t * sm,
   if (snat_static_mapping_match
       (sm, key0, &key1, 0, 0, 0, &lb, 0, &identity_nat))
     {
-      u =
-       nat_user_get_or_create (sm, &key->l_addr, rx_fib_index, thread_index);
-      if (!u)
-       {
-         nat_elog_warn ("create NAT user failed");
-         b->error = node->errors[NAT_IN2OUT_ED_ERROR_CANNOT_CREATE_USER];
-         goto drop;
-       }
-
-      s = nat_ed_session_alloc (sm, u, thread_index, now);
+      s = nat_ed_session_alloc (sm, thread_index, now);
       if (!s)
        {
          nat_elog_warn ("create NAT session failed");
@@ -396,20 +386,9 @@ slow_path_ed (snat_main_t * sm,
          *sessionp = s;
          return next;
        }
-      is_sm = 1;
-      u =
-       nat_user_get_or_create (sm, &key->l_addr, rx_fib_index, thread_index);
-      if (!u)
-       {
-         nat_elog_warn ("create NAT user failed");
-         b->error = node->errors[NAT_IN2OUT_ED_ERROR_CANNOT_CREATE_USER];
-         goto drop;
-       }
-
-      s = nat_ed_session_alloc (sm, u, thread_index, now);
+      s = nat_ed_session_alloc (sm, thread_index, now);
       if (!s)
        {
-         nat44_delete_user_with_no_session (sm, u, thread_index);
          nat_elog_warn ("create NAT session failed");
          b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_USER_SESS_EXCEEDED];
          goto drop;
@@ -453,7 +432,6 @@ slow_path_ed (snat_main_t * sm,
       out2in_ed_inserted = true;
     }
 
-  user_session_increment (sm, u, is_sm);
   if (lb)
     s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING;
   s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT;
@@ -506,10 +484,6 @@ drop:
       nat_free_session_data (sm, s, thread_index, 0);
       nat44_ed_delete_session (sm, s, thread_index, 1);
     }
-  if (u)
-    {
-      nat44_delete_user_with_no_session (sm, u, thread_index);
-    }
   return NAT_NEXT_DROP;
 }
 
@@ -630,7 +604,7 @@ nat44_ed_not_translate_output_feature (snat_main_t * sm, ip4_header_t * ip,
       if (nat44_is_ses_closed (s))
        {
          nat_free_session_data (sm, s, thread_index, 0);
-         nat44_delete_session (sm, s, thread_index);
+         nat44_ed_delete_session (sm, s, thread_index, 1);
        }
       else
        s->flags |= SNAT_SESSION_FLAG_OUTPUT_FEATURE;
@@ -782,10 +756,7 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm,
   snat_static_mapping_t *m;
   u32 old_addr, new_addr = 0;
   ip_csum_t sum;
-  snat_user_t *u;
-  dlist_elt_t *head, *elt;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
-  u32 elt_index, head_index, ses_index;
   snat_session_t *s;
   u32 outside_fib_index = sm->outside_fib_index;
   int i;
@@ -845,15 +816,6 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm,
          return 0;
        }
 
-      u = nat_user_get_or_create (sm, &ip->src_address, rx_fib_index,
-                                 thread_index);
-      if (!u)
-       {
-         b->error = node->errors[NAT_IN2OUT_ED_ERROR_CANNOT_CREATE_USER];
-         nat_elog_warn ("create NAT user failed");
-         return 0;
-       }
-
       make_sm_kv (&kv, &ip->src_address, 0, rx_fib_index, 0);
 
       /* Try to find static mapping first */
@@ -864,41 +826,23 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm,
          is_sm = 1;
          goto create_ses;
        }
-      /* Fallback to 3-tuple key */
       else
        {
-         /* Choose same out address as for TCP/UDP session to same destination */
-         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)
-           {
-             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;
-
-                 make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address,
-                             ip->protocol, outside_fib_index, 0, 0);
-                 if (clib_bihash_search_16_8
-                     (&tsm->out2in_ed, &s_kv, &s_value))
-                   goto create_ses;
-
-                 break;
-               }
-           }
+         /* *INDENT-OFF* */
+         pool_foreach (s, tsm->sessions, {
+           if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32)
+             {
+               new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
+
+               make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address, ip->protocol,
+                           outside_fib_index, 0, 0);
+               if (clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
+                 goto create_ses;
+
+               break;
+             }
+         });
+         /* *INDENT-ON* */
 
          for (i = 0; i < vec_len (sm->addresses); i++)
            {
@@ -915,11 +859,10 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm,
        }
 
     create_ses:
-      s = nat_ed_session_alloc (sm, u, thread_index, now);
+      s = nat_ed_session_alloc (sm, thread_index, now);
       if (!s)
        {
          b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_USER_SESS_EXCEEDED];
-         nat44_delete_user_with_no_session (sm, u, thread_index);
          nat_elog_warn ("create NAT session failed");
          return 0;
        }
@@ -934,7 +877,6 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm,
       s->in2out.port = s->out2in.port = ip->protocol;
       if (is_sm)
        s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
-      user_session_increment (sm, u, is_sm);
 
       /* Add to lookup tables */
       make_ed_kv (&s_kv, &s->in2out.addr, &ip->dst_address, ip->protocol,
@@ -1111,7 +1053,7 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t * vm,
          if (now >= sess_timeout_time)
            {
              nat_free_session_data (sm, s0, thread_index, 0);
-             nat44_delete_session (sm, s0, thread_index);
+             nat44_ed_delete_session (sm, s0, thread_index, 1);
              // session is closed, go slow path
              next0 = def_slow;
              goto trace0;
@@ -1372,7 +1314,7 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm,
              if (s0->tcp_close_timestamp && now >= s0->tcp_close_timestamp)
                {
                  nat_free_session_data (sm, s0, thread_index, 0);
-                 nat44_delete_session (sm, s0, thread_index);
+                 nat44_ed_delete_session (sm, s0, thread_index, 1);
                  s0 = NULL;
                }
            }
index d27887e..b0c30d6 100755 (executable)
@@ -623,64 +623,21 @@ nat_global_lru_free_one (snat_main_t * sm, int thread_index, f64 now)
 }
 
 snat_session_t *
-nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index,
-                     f64 now)
+nat_ed_session_alloc (snat_main_t * sm, u32 thread_index, f64 now)
 {
-  snat_session_t *s = NULL;
+  snat_session_t *s;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
 
-  dlist_elt_t *oldest_elt;
-  u64 sess_timeout_time;
-  u32 oldest_index;
-
-  // no sessions
-  if (PREDICT_FALSE (!(u->nsessions) && !(u->nstaticsessions)))
-    goto alloc_new;
-
-  // no free sessions
-  if (PREDICT_FALSE
-      ((u->nsessions + u->nstaticsessions) >= sm->max_translations_per_user))
-    {
-      nat_elog_addr (SNAT_LOG_WARNING, "[warn] max translations per user",
-                    clib_net_to_host_u32 (u->addr.as_u32));
-      snat_ipfix_logging_max_entries_per_user (thread_index,
-                                              sm->max_translations_per_user,
-                                              u->addr.as_u32);
-      return 0;
-    }
+  nat_global_lru_free_one (sm, thread_index, now);
 
-  /* first try to reuse an expired session from this ip */
-  oldest_index =
-    clib_dlist_remove_head (tsm->list_pool,
-                           u->sessions_per_user_list_head_index);
-  oldest_elt = pool_elt_at_index (tsm->list_pool, oldest_index);
-  s = pool_elt_at_index (tsm->sessions, oldest_elt->value);
+  pool_get (tsm->sessions, s);
+  clib_memset (s, 0, sizeof (*s));
 
-  sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
-  if (now >= sess_timeout_time ||
-      (s->tcp_close_timestamp && now >= s->tcp_close_timestamp))
-    {
-      // reuse old session
-      clib_dlist_addtail (tsm->list_pool,
-                         u->sessions_per_user_list_head_index, oldest_index);
-      s = nat44_session_reuse_old (sm, u, s, thread_index, now);
-      s->last_lru_update = now;
-    }
-  else
-    {
-      clib_dlist_addhead (tsm->list_pool,
-                         u->sessions_per_user_list_head_index, oldest_index);
-      s = NULL;
-    }
+  nat44_global_lru_insert (tsm, s, now);
 
-alloc_new:
-  if (!s)
-    {
-      nat_global_lru_free_one (sm, thread_index, now);
-      s = nat44_session_alloc_new (tsm, u, now);
-      vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
-                              pool_elts (tsm->sessions));
-    }
+  s->ha_last_refreshed = now;
+  vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
+                          pool_elts (tsm->sessions));
   return s;
 }
 
@@ -839,6 +796,105 @@ get_thread_idx_by_port (u16 e_port)
   return thread_idx;
 }
 
+void
+snat_static_mapping_del_sessions (snat_main_t * sm,
+                                 snat_main_per_thread_data_t * tsm,
+                                 snat_user_key_t u_key, int addr_only,
+                                 ip4_address_t e_addr, u16 e_port)
+{
+  clib_bihash_kv_8_8_t kv, value;
+  kv.key = u_key.as_u64;
+  u64 user_index;
+  dlist_elt_t *head, *elt;
+  snat_user_t *u;
+  snat_session_t *s;
+  u32 elt_index, head_index, ses_index;
+  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
+    {
+      user_index = value.value;
+      u = pool_elt_at_index (tsm->users, user_index);
+      if (u->nstaticsessions)
+       {
+         head_index = u->sessions_per_user_list_head_index;
+         head = pool_elt_at_index (tsm->list_pool, head_index);
+         elt_index = head->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 = pool_elt_at_index (tsm->list_pool, elt->next);
+             ses_index = elt->value;
+
+             if (!addr_only)
+               {
+                 if ((s->out2in.addr.as_u32 != e_addr.as_u32) ||
+                     (clib_net_to_host_u16 (s->out2in.port) != e_port))
+                   continue;
+               }
+
+             if (is_lb_session (s))
+               continue;
+
+             if (!snat_is_session_static (s))
+               continue;
+
+             nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
+             nat44_delete_session (sm, s, tsm - sm->per_thread_data);
+
+             if (!addr_only)
+               break;
+           }
+       }
+    }
+}
+
+void
+snat_ed_static_mapping_del_sessions (snat_main_t * sm,
+                                    snat_main_per_thread_data_t * tsm,
+                                    ip4_address_t l_addr,
+                                    u16 l_port,
+                                    u8 protocol,
+                                    u32 fib_index, int addr_only,
+                                    ip4_address_t e_addr, u16 e_port)
+{
+  snat_session_t *s;
+  u32 *indexes_to_free = NULL;
+  /* *INDENT-OFF* */
+  pool_foreach (s, tsm->sessions, {
+    if (s->in2out.fib_index != fib_index ||
+        s->in2out.addr.as_u32 != l_addr.as_u32)
+      {
+        continue;
+      }
+    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)
+          continue;
+      }
+
+    if (is_lb_session (s))
+      continue;
+    if (!snat_is_session_static (s))
+      continue;
+    nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
+    vec_add1 (indexes_to_free, s - tsm->sessions);
+    if (!addr_only)
+      break;
+  });
+  /* *INDENT-ON* */
+  u32 *ses_index;
+  vec_foreach (ses_index, indexes_to_free)
+  {
+    s = pool_elt_at_index (tsm->sessions, *ses_index);
+    nat44_ed_delete_session (sm, s, tsm - sm->per_thread_data, 1);
+  }
+  vec_free (indexes_to_free);
+}
+
 int
 snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
                         u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
@@ -1243,48 +1299,20 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
       if (!(sm->static_mapping_only) ||
          (sm->static_mapping_only && sm->static_mapping_connection_tracking))
        {
-         u_key.addr = m->local_addr;
-         u_key.fib_index = fib_index;
-         kv.key = u_key.as_u64;
-         if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
+         if (sm->endpoint_dependent)
            {
-             user_index = value.value;
-             u = pool_elt_at_index (tsm->users, user_index);
-             if (u->nstaticsessions)
-               {
-                 head_index = u->sessions_per_user_list_head_index;
-                 head = pool_elt_at_index (tsm->list_pool, head_index);
-                 elt_index = head->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 = pool_elt_at_index (tsm->list_pool, elt->next);
-                     ses_index = elt->value;
-
-                     if (!addr_only)
-                       {
-                         if ((s->out2in.addr.as_u32 != e_addr.as_u32) ||
-                             (clib_net_to_host_u16 (s->out2in.port) !=
-                              e_port))
-                           continue;
-                       }
-
-                     if (is_lb_session (s))
-                       continue;
-
-                     if (!snat_is_session_static (s))
-                       continue;
-
-                     nat_free_session_data (sm, s,
-                                            tsm - sm->per_thread_data, 0);
-                     nat44_delete_session (sm, s, tsm - sm->per_thread_data);
-
-                     if (!addr_only && !sm->endpoint_dependent)
-                       break;
-                   }
-               }
+             snat_ed_static_mapping_del_sessions (sm, tsm, m->local_addr,
+                                                  m->local_port, m->proto,
+                                                  fib_index, addr_only,
+                                                  e_addr, e_port);
+           }
+         else
+           {
+             u_key.addr = m->local_addr;
+             u_key.fib_index = fib_index;
+             kv.key = u_key.as_u64;
+             snat_static_mapping_del_sessions (sm, tsm, u_key, addr_only,
+                                               e_addr, e_port);
            }
        }
 
@@ -1344,12 +1372,8 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
   snat_address_t *a = 0;
   int i;
   nat44_lb_addr_port_t *local;
-  u32 elt_index, head_index, ses_index;
   snat_main_per_thread_data_t *tsm;
-  snat_user_key_t u_key;
-  snat_user_t *u;
   snat_session_t *s;
-  dlist_elt_t *head, *elt;
   uword *bitmap = 0;
 
   if (!sm->endpoint_dependent)
@@ -1562,37 +1586,17 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
             tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
 
           /* Delete sessions */
-          u_key.addr = local->addr;
-          u_key.fib_index = local->fib_index;
-          kv.key = u_key.as_u64;
-          if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
-            {
-              u = pool_elt_at_index (tsm->users, value.value);
-              if (u->nstaticsessions)
-                {
-                  head_index = u->sessions_per_user_list_head_index;
-                  head = pool_elt_at_index (tsm->list_pool, head_index);
-                  elt_index = head->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 = pool_elt_at_index (tsm->list_pool, elt->next);
-                      ses_index = elt->value;
-
-                      if (!(is_lb_session (s)))
-                        continue;
-
-                      if ((s->in2out.addr.as_u32 != local->addr.as_u32) ||
-                          (clib_net_to_host_u16 (s->in2out.port) != local->port))
-                        continue;
-
-                      nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
-                      nat44_delete_session (sm, s, tsm - sm->per_thread_data);
-                    }
-                }
-            }
+          pool_foreach (s, tsm->sessions, {
+            if (!(is_lb_session (s)))
+              continue;
+
+            if ((s->in2out.addr.as_u32 != local->addr.as_u32) ||
+                (clib_net_to_host_u16 (s->in2out.port) != local->port))
+              continue;
+
+            nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
+            nat44_ed_delete_session (sm, s, tsm - sm->per_thread_data, 1);
+          });
       }));
       /* *INDENT-ON* */
       if (m->affinity)
@@ -1619,11 +1623,8 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
   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;
-  snat_user_key_t u_key;
-  snat_user_t *u;
   snat_session_t *s;
-  dlist_elt_t *head, *elt;
-  u32 elt_index, head_index, ses_index, *locals = 0;
+  u32 *locals = 0;
   uword *bitmap = 0;
   int i;
 
@@ -1716,38 +1717,19 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
        tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
 
       /* Delete sessions */
-      u_key.addr = match_local->addr;
-      u_key.fib_index = match_local->fib_index;
-      kv.key = u_key.as_u64;
-      if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
-       {
-         u = pool_elt_at_index (tsm->users, value.value);
-         if (u->nstaticsessions)
-           {
-             head_index = u->sessions_per_user_list_head_index;
-             head = pool_elt_at_index (tsm->list_pool, head_index);
-             elt_index = head->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 = pool_elt_at_index (tsm->list_pool, elt->next);
-                 ses_index = elt->value;
-
-                 if (!(is_lb_session (s)))
-                   continue;
+      /* *INDENT-OFF* */
+      pool_foreach (s, tsm->sessions, {
+        if (!(is_lb_session (s)))
+          continue;
 
-                 if ((s->in2out.addr.as_u32 != match_local->addr.as_u32) ||
-                     (clib_net_to_host_u16 (s->in2out.port) !=
-                      match_local->port))
-                   continue;
+        if ((s->in2out.addr.as_u32 != match_local->addr.as_u32) ||
+            (clib_net_to_host_u16 (s->in2out.port) != match_local->port))
+          continue;
 
-                 nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
-                 nat44_delete_session (sm, s, tsm - sm->per_thread_data);
-               }
-           }
-       }
+        nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
+        nat44_ed_delete_session (sm, s, tsm - sm->per_thread_data, 1);
+      });
+      /* *INDENT-ON* */
 
       pool_put (m->locals, match_local);
     }
@@ -1858,11 +1840,19 @@ snat_del_address (snat_main_t * sm, ip4_address_t addr, u8 delete_sm,
               }
           }));
 
-          vec_foreach (ses_index, ses_to_be_removed)
-            {
-              ses = pool_elt_at_index (tsm->sessions, ses_index[0]);
-              nat44_delete_session (sm, ses, tsm - sm->per_thread_data);
-            }
+         if (sm->endpoint_dependent){
+             vec_foreach (ses_index, ses_to_be_removed)
+               {
+                 ses = pool_elt_at_index (tsm->sessions, ses_index[0]);
+                 nat44_ed_delete_session (sm, ses, tsm - sm->per_thread_data, 1);
+               }
+         }else{
+             vec_foreach (ses_index, ses_to_be_removed)
+               {
+                 ses = pool_elt_at_index (tsm->sessions, ses_index[0]);
+                 nat44_delete_session (sm, ses, tsm - sm->per_thread_data);
+               }
+         }
 
           vec_free (ses_to_be_removed);
         }
@@ -3722,7 +3712,6 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port,
 {
   snat_main_t *sm = &snat_main;
   snat_session_key_t key;
-  snat_user_t *u;
   snat_session_t *s;
   clib_bihash_kv_16_8_t kv;
   f64 now = vlib_time_now (sm->vlib_main);
@@ -3759,11 +3748,7 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port,
        return;
     }
 
-  u = nat_user_get_or_create (sm, in_addr, fib_index, thread_index);
-  if (!u)
-    return;
-
-  s = nat_ed_session_alloc (sm, u, thread_index, now);
+  s = nat_ed_session_alloc (sm, thread_index, now);
   if (!s)
     return;
 
@@ -3776,7 +3761,6 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port,
       s->ext_host_nat_addr.as_u32 = ehn_addr->as_u32;
       s->ext_host_nat_port = ehn_port;
     }
-  user_session_increment (sm, u, snat_is_session_static (s));
   switch (vec_len (sm->outside_fibs))
     {
     case 0:
@@ -4460,7 +4444,7 @@ nat44_del_ed_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
     return VNET_API_ERROR_UNSPECIFIED;
   s = pool_elt_at_index (tsm->sessions, value.value);
   nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
-  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
+  nat44_ed_delete_session (sm, s, tsm - sm->per_thread_data, 1);
   return 0;
 }
 
index 0fc174d..98c18c0 100644 (file)
@@ -1317,13 +1317,12 @@ snat_session_t *nat_session_alloc_or_recycle (snat_main_t * sm,
 /**
  * @brief Allocate NAT endpoint-dependent session
  *
- * @param u            NAT user
  * @param thread_index thread index
  *
  * @return session data structure on success otherwise zero value
  */
-snat_session_t *nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u,
-                                     u32 thread_index, f64 now);
+snat_session_t *nat_ed_session_alloc (snat_main_t * sm, u32 thread_index,
+                                     f64 now);
 
 /**
  * @brief Set address and port assignment algorithm for MAP-E CE
index 541770a..3c88e15 100644 (file)
@@ -53,6 +53,19 @@ nat44_session_reuse_old (snat_main_t * sm, snat_user_t * u,
   return s;
 }
 
+static_always_inline void
+nat44_global_lru_insert (snat_main_per_thread_data_t * tsm,
+                        snat_session_t * s, f64 now)
+{
+  dlist_elt_t *lru_list_elt;
+  pool_get (tsm->global_lru_pool, lru_list_elt);
+  s->global_lru_index = lru_list_elt - tsm->global_lru_pool;
+  clib_dlist_addtail (tsm->global_lru_pool, tsm->global_lru_head_index,
+                     s->global_lru_index);
+  lru_list_elt->value = s - tsm->sessions;
+  s->last_lru_update = now;
+}
+
 static_always_inline snat_session_t *
 nat44_session_alloc_new (snat_main_per_thread_data_t * tsm, snat_user_t * u,
                         f64 now)
@@ -75,14 +88,7 @@ nat44_session_alloc_new (snat_main_per_thread_data_t * tsm, snat_user_t * u,
                      s->per_user_list_head_index,
                      per_user_translation_list_elt - tsm->list_pool);
 
-  dlist_elt_t *lru_list_elt;
-  pool_get (tsm->global_lru_pool, lru_list_elt);
-  s->global_lru_index = lru_list_elt - tsm->global_lru_pool;
-  clib_dlist_addtail (tsm->global_lru_pool, tsm->global_lru_head_index,
-                     s->global_lru_index);
-  lru_list_elt->value = s - tsm->sessions;
-  s->last_lru_update = now;
-
+  nat44_global_lru_insert (tsm, s, now);
   s->ha_last_refreshed = now;
   return s;
 }
index 863f2cb..a54a479 100644 (file)
@@ -1678,26 +1678,40 @@ vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
                        sm->worker_in2out_cb (&ip, ukey.fib_index, 0));
   else
     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
-  if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
-    return;
-  u = pool_elt_at_index (tsm->users, value.value);
-  if (!u->nsessions && !u->nstaticsessions)
-    return;
-
-  head_index = u->sessions_per_user_list_head_index;
-  head = pool_elt_at_index (tsm->list_pool, head_index);
-  elt_index = head->next;
-  elt = pool_elt_at_index (tsm->list_pool, elt_index);
-  session_index = elt->value;
-  while (session_index != ~0)
+  if (!sm->endpoint_dependent)
     {
-      s = pool_elt_at_index (tsm->sessions, session_index);
-
-      send_nat44_user_session_details (s, reg, mp->context);
-
-      elt_index = elt->next;
+      if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
+       return;
+      u = pool_elt_at_index (tsm->users, value.value);
+      if (!u->nsessions && !u->nstaticsessions)
+       return;
+
+      head_index = u->sessions_per_user_list_head_index;
+      head = pool_elt_at_index (tsm->list_pool, head_index);
+      elt_index = head->next;
       elt = pool_elt_at_index (tsm->list_pool, elt_index);
       session_index = elt->value;
+      while (session_index != ~0)
+       {
+         s = pool_elt_at_index (tsm->sessions, session_index);
+
+         send_nat44_user_session_details (s, reg, mp->context);
+
+         elt_index = elt->next;
+         elt = pool_elt_at_index (tsm->list_pool, elt_index);
+         session_index = elt->value;
+       }
+    }
+  else
+    {
+      /* *INDENT-OFF* */
+      pool_foreach (s, tsm->sessions, {
+        if (s->in2out.addr.as_u32 == ukey.addr.as_u32)
+          {
+            send_nat44_user_session_details (s, reg, mp->context);
+          }
+      });
+      /* *INDENT-ON* */
     }
 }
 
@@ -2012,12 +2026,21 @@ static void
               vec_add1 (ses_to_be_removed, s - tsm->sessions);
             }
         }));
-        vec_foreach (ses_index, ses_to_be_removed)
-        {
-          s = pool_elt_at_index(tsm->sessions, ses_index[0]);
-          nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
-          nat44_delete_session (sm, s, tsm - sm->per_thread_data);
-        }
+       if(sm->endpoint_dependent){
+           vec_foreach (ses_index, ses_to_be_removed)
+             {
+               s = pool_elt_at_index(tsm->sessions, ses_index[0]);
+               nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
+               nat44_ed_delete_session (sm, s, tsm - sm->per_thread_data, 1);
+             }
+       }else{
+           vec_foreach (ses_index, ses_to_be_removed)
+             {
+               s = pool_elt_at_index(tsm->sessions, ses_index[0]);
+               nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
+               nat44_delete_session (sm, s, tsm - sm->per_thread_data);
+             }
+       }
         vec_free (ses_to_be_removed);
       }
       /* *INDENT-ON* */
index 01b4359..daf501d 100644 (file)
@@ -286,9 +286,8 @@ nat44_delete_user_with_no_session (snat_main_t * sm, snat_user_t * u,
 }
 
 always_inline void
-nat44_delete_session_internal (snat_main_t * sm, snat_session_t * ses,
-                              u32 thread_index, int global_lru_delete
-                              /* delete from global LRU list */ )
+nat44_delete_session (snat_main_t * sm, snat_session_t * ses,
+                     u32 thread_index)
 {
   snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data,
                                                       thread_index);
@@ -302,10 +301,7 @@ nat44_delete_session_internal (snat_main_t * sm, snat_session_t * ses,
 
   clib_dlist_remove (tsm->list_pool, ses->per_user_index);
   pool_put_index (tsm->list_pool, ses->per_user_index);
-  if (global_lru_delete)
-    {
-      clib_dlist_remove (tsm->global_lru_pool, ses->global_lru_index);
-    }
+  clib_dlist_remove (tsm->global_lru_pool, ses->global_lru_index);
   pool_put_index (tsm->global_lru_pool, ses->global_lru_index);
   pool_put (tsm->sessions, ses);
   vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
@@ -324,20 +320,23 @@ nat44_delete_session_internal (snat_main_t * sm, snat_session_t * ses,
     }
 }
 
-always_inline void
-nat44_delete_session (snat_main_t * sm, snat_session_t * ses,
-                     u32 thread_index)
-{
-  return nat44_delete_session_internal (sm, ses, thread_index, 1);
-}
-
 always_inline void
 nat44_ed_delete_session (snat_main_t * sm, snat_session_t * ses,
                         u32 thread_index, int global_lru_delete
                         /* delete from global LRU list */ )
 {
-  return nat44_delete_session_internal (sm, ses, thread_index,
-                                       global_lru_delete);
+  snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data,
+                                                      thread_index);
+
+  if (global_lru_delete)
+    {
+      clib_dlist_remove (tsm->global_lru_pool, ses->global_lru_index);
+    }
+  pool_put_index (tsm->global_lru_pool, ses->global_lru_index);
+  pool_put (tsm->sessions, ses);
+  vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
+                          pool_elts (tsm->sessions));
+
 }
 
 /** \brief Set TCP session state.
@@ -455,10 +454,13 @@ nat44_session_update_lru (snat_main_t * sm, snat_session_t * s,
   /* don't update too often - timeout is in a magnitude of seconds anyway */
   if (s->last_heard > s->last_lru_update + 1)
     {
-      clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
-                        s->per_user_index);
-      clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
-                         s->per_user_list_head_index, s->per_user_index);
+      if (!sm->endpoint_dependent)
+       {
+         clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
+                            s->per_user_index);
+         clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
+                             s->per_user_list_head_index, s->per_user_index);
+       }
 
       clib_dlist_remove (sm->per_thread_data[thread_index].global_lru_pool,
                         s->global_lru_index);
index e5adef4..560dc0d 100644 (file)
@@ -176,7 +176,7 @@ nat44_o2i_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg)
       snat_free_outside_address_and_port (sm->addresses, ctx->thread_index,
                                          &s->out2in);
     delete:
-      nat44_delete_session (sm, s, ctx->thread_index);
+      nat44_ed_delete_session (sm, s, ctx->thread_index, 1);
       return 1;
     }
 
@@ -195,7 +195,6 @@ create_session_for_static_mapping_ed (snat_main_t * sm,
                                      lb_nat_type_t lb_nat, f64 now)
 {
   snat_session_t *s;
-  snat_user_t *u;
   ip4_header_t *ip;
   udp_header_t *udp;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
@@ -210,19 +209,10 @@ create_session_for_static_mapping_ed (snat_main_t * sm,
       return 0;
     }
 
-  u = nat_user_get_or_create (sm, &l_key.addr, l_key.fib_index, thread_index);
-  if (!u)
-    {
-      b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
-      nat_elog_warn ("create NAT user failed");
-      return 0;
-    }
-
-  s = nat_ed_session_alloc (sm, u, thread_index, now);
+  s = nat_ed_session_alloc (sm, thread_index, now);
   if (!s)
     {
       b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_USER_SESS_EXCEEDED];
-      nat44_delete_user_with_no_session (sm, u, thread_index);
       nat_elog_warn ("create NAT session failed");
       return 0;
     }
@@ -241,7 +231,6 @@ create_session_for_static_mapping_ed (snat_main_t * sm,
   s->out2in = e_key;
   s->in2out = l_key;
   s->in2out.protocol = s->out2in.protocol;
-  user_session_increment (sm, u, 1);
 
   /* Add to lookup tables */
   make_ed_kv (&kv, &e_key.addr, &s->ext_host_addr, ip->protocol,
@@ -264,7 +253,7 @@ create_session_for_static_mapping_ed (snat_main_t * sm,
                                               tsm->snat_thread_index))
        {
          b->error = node->errors[NAT_OUT2IN_ED_ERROR_OUT_OF_PORTS];
-         nat44_delete_session (sm, s, thread_index);
+         nat44_ed_delete_session (sm, s, thread_index, 1);
          if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 0))
            nat_elog_notice ("out2in-ed key del failed");
          return 0;
@@ -331,7 +320,6 @@ create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip,
   nat_ed_ses_key_t key;
   clib_bihash_kv_16_8_t kv, value;
   udp_header_t *udp;
-  snat_user_t *u;
   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);
@@ -372,18 +360,9 @@ create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip,
       if (PREDICT_FALSE (nat44_maximum_sessions_exceeded (sm, thread_index)))
        return;
 
-      u = nat_user_get_or_create (sm, &ip->dst_address, sm->inside_fib_index,
-                                 thread_index);
-      if (!u)
-       {
-         nat_elog_warn ("create NAT user failed");
-         return;
-       }
-
-      s = nat_ed_session_alloc (sm, u, thread_index, now);
+      s = nat_ed_session_alloc (sm, thread_index, now);
       if (!s)
        {
-         nat44_delete_user_with_no_session (sm, u, thread_index);
          nat_elog_warn ("create NAT session failed");
          return;
        }
@@ -403,7 +382,6 @@ create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip,
        }
       s->out2in.fib_index = 0;
       s->in2out = s->out2in;
-      user_session_increment (sm, u, 0);
 
       kv.value = s - tsm->sessions;
       if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1))
@@ -579,7 +557,6 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm,
   ip_csum_t sum;
   snat_session_t *s;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
-  snat_user_t *u;
 
   old_addr = ip->dst_address.as_u32;
 
@@ -612,21 +589,11 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm,
 
       new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32;
 
-      u = nat_user_get_or_create (sm, &m->local_addr, m->fib_index,
-                                 thread_index);
-      if (!u)
-       {
-         b->error = node->errors[NAT_OUT2IN_ED_ERROR_CANNOT_CREATE_USER];
-         nat_elog_warn ("create NAT user failed");
-         return 0;
-       }
-
       /* Create a new session */
-      s = nat_ed_session_alloc (sm, u, thread_index, now);
+      s = nat_ed_session_alloc (sm, thread_index, now);
       if (!s)
        {
          b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_USER_SESS_EXCEEDED];
-         nat44_delete_user_with_no_session (sm, u, thread_index);
          nat_elog_warn ("create NAT session failed");
          return 0;
        }
@@ -640,7 +607,6 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm,
       s->in2out.addr.as_u32 = new_addr;
       s->in2out.fib_index = m->fib_index;
       s->in2out.port = s->out2in.port = ip->protocol;
-      user_session_increment (sm, u, 1);
 
       /* Add to lookup tables */
       s_kv.value = s - tsm->sessions;
@@ -791,7 +757,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
            {
              // session is closed, go slow path
              nat_free_session_data (sm, s0, thread_index, 0);
-             nat44_delete_session (sm, s0, thread_index);
+             nat44_ed_delete_session (sm, s0, thread_index, 1);
              next0 = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
              goto trace0;
            }
@@ -1053,7 +1019,7 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm,
              if (s0->tcp_close_timestamp && now >= s0->tcp_close_timestamp)
                {
                  nat_free_session_data (sm, s0, thread_index, 0);
-                 nat44_delete_session (sm, s0, thread_index);
+                 nat44_ed_delete_session (sm, s0, thread_index, 1);
                  s0 = NULL;
                }
            }
index 31eb7cb..214daf8 100644 (file)
@@ -4510,8 +4510,6 @@ class TestNAT44EndpointDependent(MethodHolder):
             '/err/nat44-ed-out2in/good out2in packets processed')
         self.assertEqual(err - totaln, 3)
 
-        users = self.statistics.get_counter('/nat44/total-users')
-        self.assertEqual(users[0][0], 1)
         sessions = self.statistics.get_counter('/nat44/total-sessions')
         self.assertEqual(sessions[0][0], 3)
 
@@ -4607,8 +4605,6 @@ class TestNAT44EndpointDependent(MethodHolder):
                 '/err/nat44-ed-out2in/good out2in packets processed')
             self.assertEqual(err - totaln, 3)
 
-            users = self.statistics.get_counter('/nat44/total-users')
-            self.assertEqual(users[0][0], 1)
             sessions = self.statistics.get_counter('/nat44/total-sessions')
             self.assertEqual(sessions[0][0], 3)
 
@@ -6817,13 +6813,6 @@ class TestNAT44EndpointDependent(MethodHolder):
         self.pg_start()
         self.pg1.get_capture(1)
 
-        nsessions = 0
-        users = self.vapi.nat44_user_dump()
-        self.assertEqual(len(users), 1)
-        self.assertEqual(str(users[0].ip_address),
-                         self.pg0.remote_ip4)
-        self.assertEqual(users[0].nsessions, 1)
-
     def test_syslog_sess(self):
         """ Test syslog session creation and deletion """
         self.vapi.syslog_set_filter(