tcp: minimal set of worker stats
[vpp.git] / src / vnet / tcp / tcp_output.c
index d6e1adc..1b9530b 100644 (file)
@@ -55,12 +55,12 @@ format_tcp_tx_trace (u8 * s, va_list * args)
   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
   tcp_tx_trace_t *t = va_arg (*args, tcp_tx_trace_t *);
+  tcp_connection_t *tc = &t->tcp_connection;
   u32 indent = format_get_indent (s);
 
-  s = format (s, "%U\n%U%U",
-             format_tcp_header, &t->tcp_header, 128,
-             format_white_space, indent,
-             format_tcp_connection, &t->tcp_connection, 1);
+  s = format (s, "%U state %U\n%U%U", format_tcp_connection_id, tc,
+             format_tcp_state, tc->state, format_white_space, indent,
+             format_tcp_header, &t->tcp_header, 128);
 
   return s;
 }
@@ -1210,13 +1210,11 @@ tcp_program_retransmit (tcp_connection_t * tc)
  * Sends delayed ACK when timer expires
  */
 void
-tcp_timer_delack_handler (u32 index)
+tcp_timer_delack_handler (u32 index, u32 thread_index)
 {
-  u32 thread_index = vlib_get_thread_index ();
   tcp_connection_t *tc;
 
   tc = tcp_connection_get (index, thread_index);
-  tc->timers[TCP_TIMER_DELACK] = TCP_TIMER_HANDLE_INVALID;
   tcp_send_ack (tc);
 }
 
@@ -1402,6 +1400,7 @@ tcp_prepare_retransmit_segment (tcp_worker_ctx_t * wrk,
 
   tc->bytes_retrans += n_bytes;
   tc->segs_retrans += 1;
+  tcp_workerp_stats_inc (wrk, rxt_segs, 1);
   TCP_EVT (TCP_EVT_CC_RTX, tc, offset, n_bytes);
 
   return n_bytes;
@@ -1446,23 +1445,21 @@ tcp_cc_init_rxt_timeout (tcp_connection_t * tc)
 }
 
 void
-tcp_timer_retransmit_handler (u32 tc_index)
+tcp_timer_retransmit_handler (u32 tc_index, u32 thread_index)
 {
-  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, n_bytes;
 
+  tcp_workerp_stats_inc (wrk, tr_events, 1);
   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;
@@ -1510,6 +1507,7 @@ tcp_timer_retransmit_handler (u32 tc_index)
          session_transport_closed_notify (&tc->connection);
          tcp_connection_timers_reset (tc);
          tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.closewait_time);
+         tcp_workerp_stats_inc (wrk, tr_abort, 1);
          return;
        }
 
@@ -1561,6 +1559,7 @@ tcp_timer_retransmit_handler (u32 tc_index)
          tcp_connection_set_state (tc, TCP_STATE_CLOSED);
          tcp_connection_timers_reset (tc);
          tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.cleanup_time);
+         tcp_workerp_stats_inc (wrk, tr_abort, 1);
          return;
        }
 
@@ -1595,9 +1594,8 @@ tcp_timer_retransmit_handler (u32 tc_index)
  * SYN retransmit timer handler. Active open only.
  */
 void
-tcp_timer_retransmit_syn_handler (u32 tc_index)
+tcp_timer_retransmit_syn_handler (u32 tc_index, u32 thread_index)
 {
-  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;
@@ -1610,8 +1608,6 @@ tcp_timer_retransmit_syn_handler (u32 tc_index)
   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. */
@@ -1664,9 +1660,8 @@ tcp_timer_retransmit_syn_handler (u32 tc_index)
  *
  */
 void
-tcp_timer_persist_handler (u32 index)
+tcp_timer_persist_handler (u32 index, u32 thread_index)
 {
-  u32 thread_index = vlib_get_thread_index ();
   tcp_worker_ctx_t *wrk = tcp_get_worker (thread_index);
   u32 bi, max_snd_bytes, available_bytes, offset;
   tcp_main_t *tm = vnet_get_tcp_main ();
@@ -1680,9 +1675,6 @@ tcp_timer_persist_handler (u32 index)
   if (!tc)
     return;
 
-  /* Make sure timer handle is set to invalid */
-  tc->timers[TCP_TIMER_PERSIST] = TCP_TIMER_HANDLE_INVALID;
-
   /* Problem already solved or worse */
   if (tc->state == TCP_STATE_CLOSED || tc->snd_wnd > tc->snd_mss
       || (tc->flags & TCP_CONN_FINSNT))
@@ -1700,10 +1692,7 @@ tcp_timer_persist_handler (u32 index)
     }
 
   if (available_bytes <= offset)
-    {
-      ASSERT (tcp_timer_is_active (tc, TCP_TIMER_RETRANSMIT));
-      return;
-    }
+    return;
 
   /* Increment RTO backoff */
   tc->rto_boff += 1;
@@ -1936,8 +1925,10 @@ tcp_retransmit_sack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
              u32 n_segs_new;
              int av_wnd;
 
+             /* Make sure we don't exceed available window and leave space
+              * for one more packet, to avoid zero window acks */
              av_wnd = (int) tc->snd_wnd - (tc->snd_nxt - tc->snd_una);
-             av_wnd = clib_max (av_wnd, 0);
+             av_wnd = clib_max (av_wnd - tc->snd_mss, 0);
              snd_space = clib_min (snd_space, av_wnd);
              snd_space = clib_min (max_deq, snd_space);
              burst_size = clib_min (burst_size - n_segs,
@@ -1960,16 +1951,16 @@ tcp_retransmit_sack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
           * unSACKed sequence number SHOULD be returned, and RescueRxt set to
           * RecoveryPoint. HighRxt MUST NOT be updated.
           */
-         max_bytes = clib_min (tc->snd_mss,
-                               tc->snd_congestion - tc->snd_una);
+         hole = scoreboard_last_hole (sb);
+         max_bytes = clib_min (tc->snd_mss, hole->end - hole->start);
          max_bytes = clib_min (max_bytes, snd_space);
-         offset = tc->snd_congestion - tc->snd_una - max_bytes;
-         sb->rescue_rxt = tc->snd_congestion;
+         offset = hole->end - tc->snd_una - max_bytes;
          n_written = tcp_prepare_retransmit_segment (wrk, tc, offset,
                                                      max_bytes, &b);
          if (!n_written)
            goto done;
 
+         sb->rescue_rxt = tc->snd_congestion;
          bi = vlib_get_buffer_index (vm, b);
          tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
          n_segs += 1;
@@ -2236,16 +2227,17 @@ static void
 tcp46_output_trace_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
                          u32 * to_next, u32 n_bufs)
 {
-  u32 n_trace = vlib_get_trace_count (vm, node);
   tcp_connection_t *tc;
   tcp_tx_trace_t *t;
   vlib_buffer_t *b;
   tcp_header_t *th;
   int i;
 
-  for (i = 0; i < clib_min (n_trace, n_bufs); i++)
+  for (i = 0; i < n_bufs; i++)
     {
       b = vlib_get_buffer (vm, to_next[i]);
+      if (!(b->flags & VLIB_BUFFER_IS_TRACED))
+       continue;
       th = vlib_buffer_get_current (b);
       tc = tcp_connection_get (vnet_buffer (b)->tcp.connection_index,
                               vm->thread_index);