tcp: cleanup timers
[vpp.git] / src / vnet / tcp / tcp.c
index f72b957..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;
@@ -270,6 +269,9 @@ tcp_connection_cleanup (tcp_connection_t * tc)
       vec_free (tc->snd_sacks);
       vec_free (tc->snd_sacks_fl);
 
+      if (tc->flags & TCP_CONN_RATE_SAMPLE)
+       tcp_bt_cleanup (tc);
+
       /* Poison the entry */
       if (CLIB_DEBUG > 0)
        clib_memset (tc, 0xFA, sizeof (*tc));
@@ -344,6 +346,7 @@ tcp_connection_reset (tcp_connection_t * tc)
       tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
       session_transport_reset_notify (&tc->connection);
       tcp_connection_set_state (tc, TCP_STATE_CLOSED);
+      session_transport_closed_notify (&tc->connection);
       break;
     case TCP_STATE_CLOSE_WAIT:
     case TCP_STATE_FIN_WAIT_1:
@@ -354,8 +357,8 @@ tcp_connection_reset (tcp_connection_t * tc)
       tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
       /* Make sure we mark the session as closed. In some states we may
        * be still trying to send data */
-      session_transport_closed_notify (&tc->connection);
       tcp_connection_set_state (tc, TCP_STATE_CLOSED);
+      session_transport_closed_notify (&tc->connection);
       break;
     case TCP_STATE_CLOSED:
     case TCP_STATE_TIME_WAIT:
@@ -405,6 +408,7 @@ tcp_connection_close (tcp_connection_t * tc)
          tcp_connection_timers_reset (tc);
          tcp_connection_set_state (tc, TCP_STATE_CLOSED);
          tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
+         session_transport_closed_notify (&tc->connection);
          break;
        }
       if (!transport_max_tx_dequeue (&tc->connection))
@@ -662,6 +666,11 @@ tcp_connection_init_vars (tcp_connection_t * tc)
   if (transport_connection_is_tx_paced (&tc->connection)
       || tcp_main.tx_pacing)
     tcp_enable_pacing (tc);
+
+  if (tc->flags & TCP_CONN_RATE_SAMPLE)
+    tcp_bt_init (tc);
+
+  tc->start_ts = tcp_time_now_us (tc->c_thread_index);
 }
 
 static int
@@ -855,6 +864,27 @@ format_tcp_congestion (u8 * s, va_list * args)
   return s;
 }
 
+static u8 *
+format_tcp_stats (u8 * s, va_list * args)
+{
+  tcp_connection_t *tc = va_arg (*args, tcp_connection_t *);
+  u32 indent = format_get_indent (s);
+  s = format (s, "in segs %lu dsegs %lu bytes %lu dupacks %u\n",
+             tc->segs_in, tc->data_segs_in, tc->bytes_in, tc->dupacks_in);
+  s = format (s, "%Uout segs %lu dsegs %lu bytes %lu dupacks %u\n",
+             format_white_space, indent, tc->segs_out,
+             tc->data_segs_out, tc->bytes_out, tc->dupacks_out);
+  s = format (s, "%Ufr %u tr %u rxt segs %lu bytes %lu duration %.3f\n",
+             format_white_space, indent, tc->fr_occurences,
+             tc->tr_occurences, tc->segs_retrans, tc->bytes_retrans,
+             tcp_time_now_us (tc->c_thread_index) - tc->start_ts);
+  s = format (s, "%Uerr wnd data below %u above %u ack below %u above %u",
+             format_white_space, indent, tc->errors.below_data_wnd,
+             tc->errors.above_data_wnd, tc->errors.below_ack_wnd,
+             tc->errors.above_ack_wnd);
+  return s;
+}
+
 static u8 *
 format_tcp_vars (u8 * s, va_list * args)
 {
@@ -888,6 +918,7 @@ format_tcp_vars (u8 * s, va_list * args)
     {
       s = format (s, " sboard: %U\n", format_tcp_scoreboard, &tc->sack_sb,
                  tc);
+      s = format (s, " stats: %U\n", format_tcp_stats, tc);
     }
   if (vec_len (tc->snd_sacks))
     s = format (s, " sacks tx: %U\n", format_tcp_sacks, tc);
@@ -958,6 +989,7 @@ static u8 *
 format_tcp_listener_session (u8 * s, va_list * args)
 {
   u32 tci = va_arg (*args, u32);
+  u32 __clib_unused thread_index = va_arg (*args, u32);
   u32 verbose = va_arg (*args, u32);
   tcp_connection_t *tc = tcp_listener_get (tci);
   s = format (s, "%-50U", format_tcp_connection_id, tc);
@@ -970,6 +1002,7 @@ static u8 *
 format_tcp_half_open_session (u8 * s, va_list * args)
 {
   u32 tci = va_arg (*args, u32);
+  u32 __clib_unused thread_index = va_arg (*args, u32);
   tcp_connection_t *tc = tcp_half_open_connection_get (tci);
   return format (s, "%U", format_tcp_connection_id, tc);
 }
@@ -1186,8 +1219,6 @@ tcp_update_time (f64 now, u8 thread_index)
 
   tcp_set_time_now (wrk);
   tw_timer_expire_timers_16t_2w_512sl (&wrk->timer_wheel, now);
-  tcp_do_fastretransmits (wrk);
-  tcp_send_acks (wrk);
   tcp_flush_frames_to_output (wrk);
 }
 
@@ -1218,11 +1249,14 @@ const static transport_proto_vft_t tcp_proto = {
   .update_time = tcp_update_time,
   .tx_fifo_offset = tcp_session_tx_fifo_offset,
   .flush_data = tcp_session_flush_data,
+  .custom_tx = tcp_session_custom_tx,
   .format_connection = format_tcp_session,
   .format_listener = format_tcp_listener_session,
   .format_half_open = format_tcp_half_open_session,
-  .tx_type = TRANSPORT_TX_PEEK,
-  .service_type = TRANSPORT_SERVICE_VC,
+  .transport_options = {
+    .tx_type = TRANSPORT_TX_PEEK,
+    .service_type = TRANSPORT_SERVICE_VC,
+  },
 };
 /* *INDENT-ON* */
 
@@ -1253,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)
 {
@@ -1311,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)
@@ -1341,12 +1327,12 @@ tcp_timer_waitclose_handler (u32 conn_index)
       break;
     case TCP_STATE_FIN_WAIT_1:
       tcp_connection_timers_reset (tc);
+      session_transport_closed_notify (&tc->connection);
       if (tc->flags & TCP_CONN_FINPNDG)
        {
          /* If FIN pending, we haven't sent everything, but we did try.
           * Notify session layer that transport is closed. */
          tcp_connection_set_state (tc, TCP_STATE_CLOSED);
-         session_transport_closed_notify (&tc->connection);
          tcp_send_reset (tc);
          tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME);
        }
@@ -1377,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* */
 
@@ -1464,17 +1447,9 @@ tcp_main_enable (vlib_main_t * vm)
 
   for (thread = 0; thread < num_threads; thread++)
     {
-      vec_validate (tm->wrk_ctx[thread].pending_fast_rxt, 255);
-      vec_validate (tm->wrk_ctx[thread].ongoing_fast_rxt, 255);
-      vec_validate (tm->wrk_ctx[thread].postponed_fast_rxt, 255);
       vec_validate (tm->wrk_ctx[thread].pending_deq_acked, 255);
-      vec_validate (tm->wrk_ctx[thread].pending_acks, 255);
       vec_validate (tm->wrk_ctx[thread].pending_disconnects, 255);
-      vec_reset_length (tm->wrk_ctx[thread].pending_fast_rxt);
-      vec_reset_length (tm->wrk_ctx[thread].ongoing_fast_rxt);
-      vec_reset_length (tm->wrk_ctx[thread].postponed_fast_rxt);
       vec_reset_length (tm->wrk_ctx[thread].pending_deq_acked);
-      vec_reset_length (tm->wrk_ctx[thread].pending_acks);
       vec_reset_length (tm->wrk_ctx[thread].pending_disconnects);
       tm->wrk_ctx[thread].vm = vlib_mains[thread];
 
@@ -1567,6 +1542,7 @@ tcp_init (vlib_main_t * vm)
   tm->tx_pacing = 1;
   tm->cc_algo = TCP_CC_NEWRENO;
   tm->default_mtu = 1460;
+  tm->initial_cwnd_multiplier = 0;
   return 0;
 }
 
@@ -1636,6 +1612,9 @@ tcp_config_fn (vlib_main_t * vm, unformat_input_t * input)
        ;
       else if (unformat (input, "mtu %d", &tm->default_mtu))
        ;
+      else if (unformat (input, "initial-cwnd-multiplier %d",
+                        &tm->initial_cwnd_multiplier))
+       ;
       else if (unformat (input, "no-tx-pacing"))
        tm->tx_pacing = 0;
       else if (unformat (input, "cc-algo %U", unformat_tcp_cc_algo,