tcp: cleanup timers 41/21041/6
authorFlorin Coras <fcoras@cisco.com>
Fri, 2 Aug 2019 22:17:21 +0000 (15:17 -0700)
committerDave Barach <openvpp@barachs.net>
Thu, 8 Aug 2019 22:02:36 +0000 (22:02 +0000)
Type:refactor

Change-Id: I37dbc8b55827d66c2578d6ab8b86ed7e18198aa6
Signed-off-by: Florin Coras <fcoras@cisco.com>
src/vnet/tcp/tcp.c
src/vnet/tcp/tcp.h
src/vnet/tcp/tcp_input.c
src/vnet/tcp/tcp_output.c

index adff77c..752257f 100644 (file)
@@ -213,7 +213,6 @@ tcp_half_open_connection_cleanup (tcp_connection_t * tc)
   /* Make sure this is the owning thread */
   if (tc->c_thread_index != vlib_get_thread_index ())
     return 1;
-  tcp_timer_reset (tc, TCP_TIMER_ESTABLISH_AO);
   tcp_timer_reset (tc, TCP_TIMER_RETRANSMIT_SYN);
   tcp_half_open_connection_del (tc);
   return 0;
@@ -1288,55 +1287,6 @@ tcp_connection_tx_pacer_reset (tcp_connection_t * tc, u32 window,
                                       start_bucket, last_time);
 }
 
-static void
-tcp_timer_keep_handler (u32 conn_index)
-{
-  u32 thread_index = vlib_get_thread_index ();
-  tcp_connection_t *tc;
-
-  tc = tcp_connection_get (conn_index, thread_index);
-  tc->timers[TCP_TIMER_KEEP] = TCP_TIMER_HANDLE_INVALID;
-
-  tcp_connection_close (tc);
-}
-
-static void
-tcp_timer_establish_handler (u32 conn_index)
-{
-  tcp_connection_t *tc;
-
-  tc = tcp_connection_get (conn_index, vlib_get_thread_index ());
-  /* note: the connection may have already disappeared */
-  if (PREDICT_FALSE (tc == 0))
-    return;
-  ASSERT (tc->state == TCP_STATE_SYN_RCVD);
-  tc->timers[TCP_TIMER_ESTABLISH] = TCP_TIMER_HANDLE_INVALID;
-  tcp_connection_set_state (tc, TCP_STATE_CLOSED);
-  tcp_connection_timers_reset (tc);
-  /* Start cleanup. Do NOT delete the session until we do the connection
-   * cleanup. Otherwise, we end up with a dangling session index in the
-   * tcp connection. */
-  tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME);
-}
-
-static void
-tcp_timer_establish_ao_handler (u32 conn_index)
-{
-  tcp_connection_t *tc;
-
-  tc = tcp_half_open_connection_get (conn_index);
-  if (!tc)
-    return;
-
-  ASSERT (tc->state == TCP_STATE_SYN_SENT);
-  /* Notify app if we haven't tried to clean this up already */
-  if (!(tc->flags & TCP_CONN_HALF_OPEN_DONE))
-    session_stream_connect_notify (&tc->connection, 1 /* fail */ );
-
-  tc->timers[TCP_TIMER_ESTABLISH_AO] = TCP_TIMER_HANDLE_INVALID;
-  tcp_connection_cleanup (tc);
-}
-
 static void
 tcp_timer_waitclose_handler (u32 conn_index)
 {
@@ -1346,6 +1296,7 @@ tcp_timer_waitclose_handler (u32 conn_index)
   tc = tcp_connection_get (conn_index, thread_index);
   if (!tc)
     return;
+
   tc->timers[TCP_TIMER_WAITCLOSE] = TCP_TIMER_HANDLE_INVALID;
 
   switch (tc->state)
@@ -1412,11 +1363,8 @@ static timer_expiration_handler *timer_expiration_handlers[TCP_N_TIMERS] =
     tcp_timer_retransmit_handler,
     tcp_timer_delack_handler,
     tcp_timer_persist_handler,
-    tcp_timer_keep_handler,
     tcp_timer_waitclose_handler,
     tcp_timer_retransmit_syn_handler,
-    tcp_timer_establish_handler,
-    tcp_timer_establish_ao_handler,
 };
 /* *INDENT-ON* */
 
index aa93bbf..ae50947 100644 (file)
@@ -71,11 +71,8 @@ format_function_t format_tcp_rcv_sacks;
   _(RETRANSMIT, "RETRANSMIT")           \
   _(DELACK, "DELAYED ACK")              \
   _(PERSIST, "PERSIST")                 \
-  _(KEEP, "KEEP")                       \
   _(WAITCLOSE, "WAIT CLOSE")            \
   _(RETRANSMIT_SYN, "RETRANSMIT SYN")   \
-  _(ESTABLISH, "ESTABLISH")            \
-  _(ESTABLISH_AO, "ESTABLISH_AO")      \
 
 typedef enum _tcp_timers
 {
@@ -98,7 +95,6 @@ extern timer_expiration_handler tcp_timer_retransmit_syn_handler;
 #define TCP_TO_TIMER_TICK       TCP_TICK*10    /* Period for converting from TCP
                                                 * ticks to timer units */
 #define TCP_DELACK_TIME         1      /* 0.1s */
-#define TCP_ESTABLISH_TIME      750    /* 75s */
 #define TCP_SYN_RCVD_TIME      600     /* 60s */
 #define TCP_2MSL_TIME           300    /* 30s */
 #define TCP_CLOSEWAIT_TIME     20      /* 2s */
@@ -113,6 +109,7 @@ extern timer_expiration_handler tcp_timer_retransmit_syn_handler;
 #define TCP_RTO_SYN_RETRIES 3  /* SYN retries without doubling RTO */
 #define TCP_RTO_INIT 1 * THZ   /* Initial retransmit timer */
 #define TCP_RTO_BOFF_MAX 8     /* Max number of retries before reset */
+#define TCP_ESTABLISH_TIME (60 * THZ)  /* Connection establish timeout */
 
 /** TCP connection flags */
 #define foreach_tcp_connection_flag             \
index 2fadab5..504133c 100755 (executable)
@@ -2439,7 +2439,6 @@ tcp46_syn_sent_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
       new_tc0->c_thread_index = my_thread_index;
       new_tc0->rcv_nxt = vnet_buffer (b0)->tcp.seq_end;
       new_tc0->irs = seq0;
-      new_tc0->timers[TCP_TIMER_ESTABLISH_AO] = TCP_TIMER_HANDLE_INVALID;
       new_tc0->timers[TCP_TIMER_RETRANSMIT_SYN] = TCP_TIMER_HANDLE_INVALID;
       new_tc0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
 
@@ -2714,7 +2713,6 @@ tcp46_rcv_process_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
 
          /* Reset SYN-ACK retransmit and SYN_RCV establish timers */
          tcp_retransmit_timer_reset (tc0);
-         tcp_timer_reset (tc0, TCP_TIMER_ESTABLISH);
          if (session_stream_accept_notify (&tc0->connection))
            {
              error0 = TCP_ERROR_MSG_QUEUE_FULL;
@@ -3160,7 +3158,6 @@ tcp46_listen_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
       TCP_EVT_DBG (TCP_EVT_SYN_RCVD, child0, 1);
       child0->tx_fifo_size = transport_tx_fifo_size (&child0->connection);
       tcp_send_synack (child0);
-      tcp_timer_set (child0, TCP_TIMER_ESTABLISH, TCP_SYN_RCVD_TIME);
 
     drop:
 
index 751d8b3..ef8b756 100644 (file)
@@ -942,7 +942,6 @@ tcp_send_syn (tcp_connection_t * tc)
    * Setup retransmit and establish timers before requesting buffer
    * such that we can return if we've ran out.
    */
-  tcp_timer_set (tc, TCP_TIMER_ESTABLISH_AO, TCP_ESTABLISH_TIME);
   tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN,
                    tc->rto * TCP_TO_TIMER_TICK);
 
@@ -1467,8 +1466,8 @@ tcp_cc_init_rxt_timeout (tcp_connection_t * tc)
   tcp_recovery_on (tc);
 }
 
-static inline void
-tcp_timer_retransmit_handler_i (u32 index, u8 is_syn)
+void
+tcp_timer_retransmit_handler (u32 tc_index)
 {
   u32 thread_index = vlib_get_thread_index ();
   tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index);
@@ -1477,25 +1476,17 @@ tcp_timer_retransmit_handler_i (u32 index, u8 is_syn)
   vlib_buffer_t *b = 0;
   u32 bi, n_bytes;
 
-  if (is_syn)
-    {
-      tc = tcp_half_open_connection_get (index);
-      /* Note: the connection may have transitioned to ESTABLISHED... */
-      if (PREDICT_FALSE (tc == 0 || tc->state != TCP_STATE_SYN_SENT))
-       return;
-      tc->timers[TCP_TIMER_RETRANSMIT_SYN] = TCP_TIMER_HANDLE_INVALID;
-    }
-  else
-    {
-      tc = tcp_connection_get (index, thread_index);
-      /* Note: the connection may have been closed and pool_put */
-      if (PREDICT_FALSE (tc == 0 || tc->state == TCP_STATE_SYN_SENT))
-       return;
-      tc->timers[TCP_TIMER_RETRANSMIT] = TCP_TIMER_HANDLE_INVALID;
-      /* Wait-close and retransmit could pop at the same time */
-      if (tc->state == TCP_STATE_CLOSED)
-       return;
-    }
+  tc = tcp_connection_get (tc_index, thread_index);
+
+  /* Note: the connection may have been closed and pool_put */
+  if (PREDICT_FALSE (tc == 0 || tc->state == TCP_STATE_SYN_SENT))
+    return;
+
+  tc->timers[TCP_TIMER_RETRANSMIT] = TCP_TIMER_HANDLE_INVALID;
+
+  /* Wait-close and retransmit could pop at the same time */
+  if (tc->state == TCP_STATE_CLOSED)
+    return;
 
   if (tc->state >= TCP_STATE_ESTABLISHED)
     {
@@ -1551,19 +1542,20 @@ tcp_timer_retransmit_handler_i (u32 index, u8 is_syn)
 
       /* First retransmit timeout */
       if (tc->rto_boff == 1)
-       tcp_cc_init_rxt_timeout (tc);
+       {
+         tcp_cc_init_rxt_timeout (tc);
+         /* Record timestamp. Eifel detection algorithm RFC3522 */
+         tc->snd_rxt_ts = tcp_tstamp (tc);
+       }
 
       if (tc->flags & TCP_CONN_RATE_SAMPLE)
        tcp_bt_flush_samples (tc);
 
       /* If we've sent beyond snd_congestion, update it */
       tc->snd_congestion = seq_max (tc->snd_nxt, tc->snd_congestion);
-
       tc->snd_nxt = tc->snd_una;
-      tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
 
-      /* Send one segment. Note that n_bytes may be zero due to buffer
-       * shortfall */
+      /* Send one segment. n_bytes may be zero due to buffer shortfall */
       n_bytes = tcp_prepare_retransmit_segment (wrk, tc, 0, tc->snd_mss, &b);
       if (!n_bytes)
        {
@@ -1572,73 +1564,39 @@ tcp_timer_retransmit_handler_i (u32 index, u8 is_syn)
        }
 
       bi = vlib_get_buffer_index (vm, b);
-
-      /* For first retransmit, record timestamp (Eifel detection RFC3522) */
-      if (tc->rto_boff == 1)
-       tc->snd_rxt_ts = tcp_tstamp (tc);
-
       tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
+
+      tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
       tcp_retransmit_timer_force_update (tc);
     }
-  /* Retransmit for SYN */
-  else if (tc->state == TCP_STATE_SYN_SENT)
+  /* Retransmit SYN-ACK */
+  else if (tc->state == TCP_STATE_SYN_RCVD)
     {
-      /* Half-open connection actually moved to established but we were
-       * waiting for syn retransmit to pop to call cleanup from the right
-       * thread. */
-      if (tc->flags & TCP_CONN_HALF_OPEN_DONE)
-       {
-         if (tcp_half_open_connection_cleanup (tc))
-           TCP_DBG ("could not remove half-open connection");
-         return;
-       }
-
       TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 2);
 
-      /* Try without increasing RTO a number of times. If this fails,
-       * start growing RTO exponentially */
-      tc->rto_boff += 1;
-      if (tc->rto_boff > TCP_RTO_SYN_RETRIES)
-       tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
+      tc->rtt_ts = 0;
 
-      tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN,
-                       tc->rto * TCP_TO_TIMER_TICK);
+      /* Passive open establish timeout */
+      if (tc->rto > TCP_ESTABLISH_TIME >> 1)
+       {
+         tcp_connection_set_state (tc, TCP_STATE_CLOSED);
+         tcp_connection_timers_reset (tc);
+         tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME);
+         return;
+       }
 
       if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
        {
-         tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN, 1);
+         tcp_timer_update (tc, TCP_TIMER_RETRANSMIT, 1);
          return;
        }
 
-      b = vlib_get_buffer (vm, bi);
-      tcp_init_buffer (vm, b);
-      tcp_make_syn (tc, b);
-
-      tc->rtt_ts = 0;
-      TCP_EVT_DBG (TCP_EVT_SYN_RXT, tc, 0);
-
-      /* This goes straight to ipx_lookup. Retransmit timer set already */
-      tcp_push_ip_hdr (wrk, tc, b);
-      tcp_enqueue_to_ip_lookup (wrk, b, bi, tc->c_is_ip4, tc->c_fib_index);
-    }
-  /* Retransmit SYN-ACK */
-  else if (tc->state == TCP_STATE_SYN_RCVD)
-    {
-      TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 2);
-
       tc->rto_boff += 1;
       if (tc->rto_boff > TCP_RTO_SYN_RETRIES)
        tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
-      tc->rtt_ts = 0;
 
       tcp_retransmit_timer_force_update (tc);
 
-      if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
-       {
-         tcp_timer_update (tc, TCP_TIMER_RETRANSMIT, 1);
-         return;
-       }
-
       b = vlib_get_buffer (vm, bi);
       tcp_init_buffer (vm, b);
       tcp_make_synack (tc, b);
@@ -1654,16 +1612,72 @@ tcp_timer_retransmit_handler_i (u32 index, u8 is_syn)
     }
 }
 
+/**
+ * SYN retransmit timer handler. Active open only.
+ */
 void
-tcp_timer_retransmit_handler (u32 index)
+tcp_timer_retransmit_syn_handler (u32 tc_index)
 {
-  tcp_timer_retransmit_handler_i (index, 0);
-}
+  u32 thread_index = vlib_get_thread_index ();
+  tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index);
+  vlib_main_t *vm = wrk->vm;
+  tcp_connection_t *tc;
+  vlib_buffer_t *b = 0;
+  u32 bi;
 
-void
-tcp_timer_retransmit_syn_handler (u32 index)
-{
-  tcp_timer_retransmit_handler_i (index, 1);
+  tc = tcp_half_open_connection_get (tc_index);
+
+  /* Note: the connection may have transitioned to ESTABLISHED... */
+  if (PREDICT_FALSE (tc == 0 || tc->state != TCP_STATE_SYN_SENT))
+    return;
+
+  tc->timers[TCP_TIMER_RETRANSMIT_SYN] = TCP_TIMER_HANDLE_INVALID;
+
+  /* Half-open connection actually moved to established but we were
+   * waiting for syn retransmit to pop to call cleanup from the right
+   * thread. */
+  if (tc->flags & TCP_CONN_HALF_OPEN_DONE)
+    {
+      if (tcp_half_open_connection_cleanup (tc))
+       TCP_DBG ("could not remove half-open connection");
+      return;
+    }
+
+  TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 2);
+  tc->rtt_ts = 0;
+
+  /* Active open establish timeout */
+  if (tc->rto >= TCP_ESTABLISH_TIME >> 1)
+    {
+      session_stream_connect_notify (&tc->connection, 1 /* fail */ );
+      tcp_connection_cleanup (tc);
+      return;
+    }
+
+  if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
+    {
+      tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN, 1);
+      return;
+    }
+
+  /* Try without increasing RTO a number of times. If this fails,
+   * start growing RTO exponentially */
+  tc->rto_boff += 1;
+  if (tc->rto_boff > TCP_RTO_SYN_RETRIES)
+    tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
+
+  b = vlib_get_buffer (vm, bi);
+  tcp_init_buffer (vm, b);
+  tcp_make_syn (tc, b);
+
+  TCP_EVT_DBG (TCP_EVT_SYN_RXT, tc, 0);
+
+  /* This goes straight to ipx_lookup */
+  tcp_push_ip_hdr (wrk, tc, b);
+  tcp_enqueue_to_ip_lookup (wrk, b, bi, tc->c_is_ip4, tc->c_fib_index);
+
+  tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN,
+                   tc->rto * TCP_TO_TIMER_TICK);
 }
 
 /**