nat: timed out session scavenging upgrade
[vpp.git] / src / plugins / nat / in2out_ed.c
index 581d7b4..ca737d5 100644 (file)
@@ -209,14 +209,18 @@ slow_path_ed (snat_main_t * sm,
   };
   nat44_is_idle_session_ctx_t ctx;
 
-  nat44_session_try_cleanup (&key->l_addr, rx_fib_index, thread_index, now);
+  u32 cleared = 0;
 
   if (PREDICT_FALSE (nat44_maximum_sessions_exceeded (sm, thread_index)))
     {
-      b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
-      nat_ipfix_logging_max_sessions (thread_index, sm->max_translations);
-      nat_elog_notice ("maximum sessions exceeded");
-      return NAT_NEXT_DROP;
+      if (PREDICT_FALSE
+         (!(cleared = nat44_users_cleanup (thread_index, now))))
+       {
+         b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
+         nat_ipfix_logging_max_sessions (thread_index, sm->max_translations);
+         nat_elog_notice ("maximum sessions exceeded");
+         return NAT_NEXT_DROP;
+       }
     }
 
   key0.addr = key->l_addr;
@@ -224,6 +228,7 @@ slow_path_ed (snat_main_t * sm,
   key1.protocol = key0.protocol = proto;
   key0.fib_index = rx_fib_index;
   key1.fib_index = sm->outside_fib_index;
+
   /* First try to match static mapping by local address and port */
   if (snat_static_mapping_match
       (sm, key0, &key1, 0, 0, 0, &lb, 0, &identity_nat))
@@ -234,9 +239,16 @@ slow_path_ed (snat_main_t * sm,
                                               sm->port_per_thread,
                                               tsm->snat_thread_index))
        {
-         nat_elog_notice ("addresses exhausted");
-         b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
-         return NAT_NEXT_DROP;
+         if (cleared || !nat44_out_of_ports_cleanup (thread_index, now) ||
+             snat_alloc_outside_address_and_port (sm->addresses,
+                                                  rx_fib_index, thread_index,
+                                                  &key1, sm->port_per_thread,
+                                                  tsm->snat_thread_index))
+           {
+             nat_elog_notice ("addresses exhausted");
+             b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
+             return NAT_NEXT_DROP;
+           }
        }
     }
   else
@@ -246,16 +258,19 @@ slow_path_ed (snat_main_t * sm,
          *sessionp = s;
          return next;
        }
-
       is_sm = 1;
     }
 
-  if (proto == SNAT_PROTOCOL_TCP)
+  if (PREDICT_TRUE (proto == SNAT_PROTOCOL_TCP))
     {
-      if (!tcp_flags_is_init
-         (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
+      if (PREDICT_FALSE
+         (!tcp_flags_is_init
+          (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
        {
          b->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN];
+         if (!is_sm)
+           snat_free_outside_address_and_port (sm->addresses,
+                                               thread_index, &key1);
          return NAT_NEXT_DROP;
        }
     }
@@ -932,9 +947,23 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t * vm,
              next0 = def_slow;
              goto trace0;
            }
-
          s0 = pool_elt_at_index (tsm->sessions, value0.value);
 
+         // drop if session expired
+         u64 sess_timeout_time;
+         sess_timeout_time = s0->last_heard +
+           (f64) nat44_session_get_timeout (sm, s0);
+         if (now >= sess_timeout_time)
+           {
+             // delete session
+             nat_free_session_data (sm, s0, thread_index, 0);
+             nat44_delete_session (sm, s0, thread_index);
+
+             next0 = NAT_NEXT_DROP;
+             goto trace0;
+           }
+         //
+
          b0->flags |= VNET_BUFFER_F_IS_NATED;
 
          if (!is_output_feature)