nat: session cleanup fix
[vpp.git] / src / plugins / nat / nat.c
index 0a30caf..d85fb26 100755 (executable)
@@ -38,6 +38,9 @@
 
 snat_main_t snat_main;
 
+fib_source_t nat_fib_src_hi;
+fib_source_t nat_fib_src_low;
+
 /* *INDENT-OFF* */
 /* Hook up input features */
 VNET_FEATURE_INIT (nat_pre_in2out, static) = {
@@ -459,6 +462,7 @@ nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index,
                            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);
+
   sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
   if (now >= sess_timeout_time)
     {
@@ -536,7 +540,7 @@ snat_add_del_addr_to_fib (ip4_address_t * addr, u8 p_len, u32 sw_if_index,
   if (is_add)
     fib_table_entry_update_one_path (fib_index,
                                     &prefix,
-                                    FIB_SOURCE_PLUGIN_LOW,
+                                    nat_fib_src_low,
                                     (FIB_ENTRY_FLAG_CONNECTED |
                                      FIB_ENTRY_FLAG_LOCAL |
                                      FIB_ENTRY_FLAG_EXCLUSIVE),
@@ -545,7 +549,7 @@ snat_add_del_addr_to_fib (ip4_address_t * addr, u8 p_len, u32 sw_if_index,
                                     sw_if_index,
                                     ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
   else
-    fib_table_entry_delete (fib_index, &prefix, FIB_SOURCE_PLUGIN_LOW);
+    fib_table_entry_delete (fib_index, &prefix, nat_fib_src_low);
 }
 
 int
@@ -577,7 +581,7 @@ snat_add_address (snat_main_t * sm, ip4_address_t * addr, u32 vrf_id,
   if (vrf_id != ~0)
     ap->fib_index =
       fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
-                                        FIB_SOURCE_PLUGIN_LOW);
+                                        nat_fib_src_low);
   else
     ap->fib_index = ~0;
 #define _(N, i, n, s) \
@@ -813,7 +817,7 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
              local->vrf_id = vrf_id;
              local->fib_index =
                fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
-                                                  FIB_SOURCE_PLUGIN_LOW);
+                                                  nat_fib_src_low);
              m_key.addr = m->local_addr;
              m_key.port = m->local_port;
              m_key.protocol = m->proto;
@@ -834,13 +838,13 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
       if (vrf_id != ~0)
        fib_index =
          fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
-                                            FIB_SOURCE_PLUGIN_LOW);
+                                            nat_fib_src_low);
       /* If not specified use inside VRF id from SNAT plugin startup config */
       else
        {
          fib_index = sm->inside_fib_index;
          vrf_id = sm->inside_vrf_id;
-         fib_table_lock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_LOW);
+         fib_table_lock (fib_index, FIB_PROTOCOL_IP4, nat_fib_src_low);
        }
 
       if (!(out2in_only || identity_nat))
@@ -1133,7 +1137,7 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
            }
        }
 
-      fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_LOW);
+      fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, nat_fib_src_low);
       if (pool_elts (m->locals))
        return 0;
 
@@ -1291,7 +1295,7 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
          locals[i].fib_index =
            fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
                                               locals[i].vrf_id,
-                                              FIB_SOURCE_PLUGIN_LOW);
+                                              nat_fib_src_low);
          m_key.addr = locals[i].addr;
          m_key.fib_index = locals[i].fib_index;
          if (!out2in_only)
@@ -1381,7 +1385,7 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
       pool_foreach (local, m->locals,
       ({
           fib_table_unlock (local->fib_index, FIB_PROTOCOL_IP4,
-                            FIB_SOURCE_PLUGIN_LOW);
+                            nat_fib_src_low);
           m_key.addr = local->addr;
           if (!out2in_only)
             {
@@ -1514,7 +1518,7 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
       local->vrf_id = vrf_id;
       local->fib_index =
        fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
-                                          FIB_SOURCE_PLUGIN_LOW);
+                                          nat_fib_src_low);
 
       if (!is_out2in_only_static_mapping (m))
        {
@@ -1536,7 +1540,7 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
        return VNET_API_ERROR_UNSPECIFIED;
 
       fib_table_unlock (match_local->fib_index, FIB_PROTOCOL_IP4,
-                       FIB_SOURCE_PLUGIN_LOW);
+                       nat_fib_src_low);
 
       if (!is_out2in_only_static_mapping (m))
        {
@@ -1687,7 +1691,7 @@ snat_del_address (snat_main_t * sm, ip4_address_t addr, u8 delete_sm,
     }
 
   if (a->fib_index != ~0)
-    fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_LOW);
+    fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP4, nat_fib_src_low);
 
   /* Delete sessions using address */
   if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
@@ -2306,7 +2310,7 @@ snat_init (vlib_main_t * vm)
   sm->vnet_main = vnet_get_main ();
   sm->ip4_main = im;
   sm->ip4_lookup_main = lm;
-  sm->api_main = &api_main;
+  sm->api_main = vlibapi_get_main ();
   sm->first_worker_index = 0;
   sm->num_workers = 0;
   sm->num_snat_thread = 1;
@@ -2315,10 +2319,8 @@ snat_init (vlib_main_t * vm)
   sm->fq_in2out_index = ~0;
   sm->fq_in2out_output_index = ~0;
   sm->fq_out2in_index = ~0;
-  sm->udp_timeout = SNAT_UDP_TIMEOUT;
-  sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
-  sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
-  sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
+
+
   sm->alloc_addr_and_port = nat_alloc_addr_and_port_default;
   sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT;
   sm->forwarding_enabled = 0;
@@ -2340,8 +2342,6 @@ snat_init (vlib_main_t * vm)
   node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-out2in");
   sm->pre_out2in_node_index = node->index;
 
-  // TODO: output ?? (special node)
-
   node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out");
   sm->in2out_node_index = node->index;
   node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output");
@@ -2464,6 +2464,13 @@ snat_init (vlib_main_t * vm)
   };
   vec_add1 (ip4_main.table_bind_callbacks, cbt4);
 
+  nat_fib_src_hi = fib_source_allocate ("nat-hi",
+                                       FIB_SOURCE_PRIORITY_HI,
+                                       FIB_SOURCE_BH_SIMPLE);
+  nat_fib_src_low = fib_source_allocate ("nat-low",
+                                        FIB_SOURCE_PRIORITY_LOW,
+                                        FIB_SOURCE_BH_SIMPLE);
+
   /* Init virtual fragmenentation reassembly */
   return nat_reass_init (vm);
 }
@@ -2915,13 +2922,13 @@ nat44_add_del_address_dpo (ip4_address_t addr, u8 is_add)
   if (is_add)
     {
       nat_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4);
-      fib_table_entry_special_dpo_add (0, &pfx, FIB_SOURCE_PLUGIN_HI,
+      fib_table_entry_special_dpo_add (0, &pfx, nat_fib_src_hi,
                                       FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4);
       dpo_reset (&dpo_v4);
     }
   else
     {
-      fib_table_entry_special_remove (0, &pfx, FIB_SOURCE_PLUGIN_HI);
+      fib_table_entry_special_remove (0, &pfx, nat_fib_src_hi);
     }
 }
 
@@ -3739,24 +3746,36 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
 {
   snat_main_t *sm = &snat_main;
   nat66_main_t *nm = &nat66_main;
-  u32 translation_buckets = 1024;
-  u32 translation_memory_size = 128 << 20;
-  u32 user_buckets = 128;
-  u32 user_memory_size = 64 << 20;
-  u32 max_translations_per_user = 100;
-  u32 outside_vrf_id = 0;
-  u32 outside_ip6_vrf_id = 0;
-  u32 inside_vrf_id = 0;
+  dslite_main_t *dm = &dslite_main;
+  snat_main_per_thread_data_t *tsm;
+
   u32 static_mapping_buckets = 1024;
   u32 static_mapping_memory_size = 64 << 20;
+
   u32 nat64_bib_buckets = 1024;
   u32 nat64_bib_memory_size = 128 << 20;
+
   u32 nat64_st_buckets = 2048;
   u32 nat64_st_memory_size = 256 << 20;
+
+  u32 user_buckets = 128;
+  u32 user_memory_size = 64 << 20;
+  u32 translation_buckets = 1024;
+  u32 translation_memory_size = 128 << 20;
+
+  u32 max_translations_per_user = ~0;
+
+  u32 outside_vrf_id = 0;
+  u32 outside_ip6_vrf_id = 0;
+  u32 inside_vrf_id = 0;
   u8 static_mapping_only = 0;
   u8 static_mapping_connection_tracking = 0;
-  snat_main_per_thread_data_t *tsm;
-  dslite_main_t *dm = &dslite_main;
+
+  u32 udp_timeout = SNAT_UDP_TIMEOUT;
+  u32 icmp_timeout = SNAT_ICMP_TIMEOUT;
+
+  u32 tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
+  u32 tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
 
   sm->deterministic = 0;
   sm->out2in_dpo = 0;
@@ -3767,6 +3786,14 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
       if (unformat
          (input, "translation hash buckets %d", &translation_buckets))
        ;
+      else if (unformat (input, "udp timeout %d", &udp_timeout))
+       ;
+      else if (unformat (input, "icmp timeout %d", &icmp_timeout))
+       ;
+      else if (unformat (input, "tcp transitory timeout %d",
+                        &tcp_transitory_timeout));
+      else if (unformat (input, "tcp established timeout %d",
+                        &tcp_established_timeout));
       else if (unformat (input, "translation hash memory %d",
                         &translation_memory_size));
       else if (unformat (input, "user hash buckets %d", &user_buckets))
@@ -3825,26 +3852,35 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
     return clib_error_return (0,
                              "out2in dpo mode available only for simple nat");
 
-  /* for show commands, etc. */
+  /* optionally configurable timeouts for testing purposes */
+  sm->udp_timeout = udp_timeout;
+  sm->icmp_timeout = icmp_timeout;
+  sm->tcp_transitory_timeout = tcp_transitory_timeout;
+  sm->tcp_established_timeout = tcp_established_timeout;
+
+  sm->user_buckets = user_buckets;
+  sm->user_memory_size = user_memory_size;
+
   sm->translation_buckets = translation_buckets;
   sm->translation_memory_size = translation_memory_size;
+
   /* do not exceed load factor 10 */
   sm->max_translations = 10 * translation_buckets;
-  sm->user_buckets = user_buckets;
-  sm->user_memory_size = user_memory_size;
-  sm->max_translations_per_user = max_translations_per_user;
+  sm->max_translations_per_user = max_translations_per_user == ~0 ?
+    sm->max_translations : max_translations_per_user;
+
   sm->outside_vrf_id = outside_vrf_id;
   sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
                                                             outside_vrf_id,
-                                                            FIB_SOURCE_PLUGIN_HI);
+                                                            nat_fib_src_hi);
   nm->outside_vrf_id = outside_ip6_vrf_id;
   nm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
                                                             outside_ip6_vrf_id,
-                                                            FIB_SOURCE_PLUGIN_HI);
+                                                            nat_fib_src_hi);
   sm->inside_vrf_id = inside_vrf_id;
   sm->inside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
                                                            inside_vrf_id,
-                                                           FIB_SOURCE_PLUGIN_HI);
+                                                           nat_fib_src_hi);
   sm->static_mapping_only = static_mapping_only;
   sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
 
@@ -3868,7 +3904,6 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
 
          sm->handoff_out2in_index = nat_pre_out2in_node.index;
          sm->handoff_in2out_index = nat_pre_in2out_node.index;
-         // TODO: test
          sm->handoff_in2out_output_index = nat44_ed_in2out_output_node.index;
 
          sm->in2out_node_index = nat44_ed_in2out_node.index;
@@ -3888,7 +3923,6 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
 
          sm->handoff_out2in_index = snat_in2out_node.index;
          sm->handoff_in2out_index = snat_out2in_node.index;
-         // TODO: test
          sm->handoff_in2out_output_index = snat_in2out_output_node.index;
 
          sm->in2out_node_index = snat_in2out_node.index;