api: multiple connections per process
[vpp.git] / src / vnet / tcp / tcp.c
index 86e5d94..7dce97e 100644 (file)
@@ -360,6 +360,7 @@ tcp_connection_reset (tcp_connection_t * tc)
        * cleanly close the connection */
       tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.closewait_time);
       session_transport_reset_notify (&tc->connection);
+      tcp_cong_recovery_off (tc);
       tcp_connection_set_state (tc, TCP_STATE_CLOSED);
       session_transport_closed_notify (&tc->connection);
       break;
@@ -370,6 +371,7 @@ tcp_connection_reset (tcp_connection_t * tc)
     case TCP_STATE_LAST_ACK:
       tcp_connection_timers_reset (tc);
       tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.closewait_time);
+      tcp_cong_recovery_off (tc);
       /* Make sure we mark the session as closed. In some states we may
        * be still trying to send data */
       tcp_connection_set_state (tc, TCP_STATE_CLOSED);
@@ -489,6 +491,7 @@ tcp_session_reset (u32 conn_index, u32 thread_index)
   session_transport_closed_notify (&tc->connection);
   tcp_send_reset (tc);
   tcp_connection_timers_reset (tc);
+  tcp_cong_recovery_off (tc);
   tcp_connection_set_state (tc, TCP_STATE_CLOSED);
   tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.cleanup_time);
 }
@@ -702,6 +705,9 @@ tcp_init_snd_vars (tcp_connection_t * tc)
   tc->snd_nxt = tc->iss + 1;
   tc->snd_una_max = tc->snd_nxt;
   tc->srtt = 100;              /* 100 ms */
+
+  if (!tcp_cfg.csum_offload)
+    tc->cfg_flags |= TCP_CFG_F_NO_CSUM_OFFLOAD;
 }
 
 void
@@ -1015,6 +1021,8 @@ format_tcp_vars (u8 * s, va_list * args)
              tc->rto, tc->rto_boff, tc->srtt, tc->mrtt_us * 1000, tc->rttvar,
              tc->rtt_ts);
   s = format (s, " rtt_seq %u\n", tc->rtt_seq - tc->iss);
+  s = format (s, " next_node %u opaque 0x%x\n", tc->next_node_index,
+             tc->next_node_opaque);
   s = format (s, " cong:   %U", format_tcp_congestion, tc);
 
   if (tc->state >= TCP_STATE_ESTABLISHED)
@@ -1391,33 +1399,33 @@ tcp_connection_tx_pacer_update (tcp_connection_t * tc)
   if (!transport_connection_is_tx_paced (&tc->connection))
     return;
 
+  f64 srtt = clib_min ((f64) tc->srtt * TCP_TICK, tc->mrtt_us);
+
   transport_connection_tx_pacer_update (&tc->connection,
-                                       tcp_cc_get_pacing_rate (tc));
+                                       tcp_cc_get_pacing_rate (tc),
+                                       srtt * CLIB_US_TIME_FREQ);
 }
 
 void
 tcp_connection_tx_pacer_reset (tcp_connection_t * tc, u32 window,
                               u32 start_bucket)
 {
-  tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
   f64 srtt = clib_min ((f64) tc->srtt * TCP_TICK, tc->mrtt_us);
-  u64 last_time = wrk->vm->clib_time.last_cpu_time;
-  transport_connection_tx_pacer_reset (&tc->connection, window / srtt,
-                                      start_bucket, last_time);
+  transport_connection_tx_pacer_reset (&tc->connection,
+                                      tcp_cc_get_pacing_rate (tc),
+                                      start_bucket,
+                                      srtt * CLIB_US_TIME_FREQ);
 }
 
 static void
-tcp_timer_waitclose_handler (u32 conn_index)
+tcp_timer_waitclose_handler (u32 conn_index, u32 thread_index)
 {
-  u32 thread_index = vlib_get_thread_index ();
   tcp_connection_t *tc;
 
   tc = tcp_connection_get (conn_index, thread_index);
   if (!tc)
     return;
 
-  tc->timers[TCP_TIMER_WAITCLOSE] = TCP_TIMER_HANDLE_INVALID;
-
   switch (tc->state)
     {
     case TCP_STATE_CLOSE_WAIT:
@@ -1490,19 +1498,38 @@ static timer_expiration_handler *timer_expiration_handlers[TCP_N_TIMERS] =
 static void
 tcp_expired_timers_dispatch (u32 * expired_timers)
 {
-  int i;
+  u32 thread_index = vlib_get_thread_index ();
   u32 connection_index, timer_id;
+  tcp_connection_t *tc;
+  int i;
 
+  /*
+   * Invalidate all timer handles before dispatching. This avoids dangling
+   * index references to timer wheel pool entries that have been freed.
+   */
   for (i = 0; i < vec_len (expired_timers); i++)
     {
-      /* Get session index and timer id */
       connection_index = expired_timers[i] & 0x0FFFFFFF;
       timer_id = expired_timers[i] >> 28;
 
+      if (timer_id != TCP_TIMER_RETRANSMIT_SYN)
+       tc = tcp_connection_get (connection_index, thread_index);
+      else
+       tc = tcp_half_open_connection_get (connection_index);
+
       TCP_EVT (TCP_EVT_TIMER_POP, connection_index, timer_id);
 
-      /* Handle expiration */
-      (*timer_expiration_handlers[timer_id]) (connection_index);
+      tc->timers[timer_id] = TCP_TIMER_HANDLE_INVALID;
+    }
+
+  /*
+   * Dispatch expired timers
+   */
+  for (i = 0; i < vec_len (expired_timers); i++)
+    {
+      connection_index = expired_timers[i] & 0x0FFFFFFF;
+      timer_id = expired_timers[i] >> 28;
+      (*timer_expiration_handlers[timer_id]) (connection_index, thread_index);
     }
 }
 
@@ -1649,6 +1676,7 @@ tcp_configuration_init (void)
   tcp_cfg.initial_cwnd_multiplier = 0;
   tcp_cfg.enable_tx_pacing = 1;
   tcp_cfg.allow_tso = 0;
+  tcp_cfg.csum_offload = 1;
   tcp_cfg.cc_algo = TCP_CC_NEWRENO;
   tcp_cfg.rwnd_min_update_ack = 1;
 
@@ -1758,10 +1786,26 @@ tcp_config_fn (vlib_main_t * vm, unformat_input_t * input)
        ;
       else if (unformat (input, "max-rx-fifo %U", unformat_memory_size,
                         &memory_size))
-       tcp_cfg.max_rx_fifo = memory_size;
+       {
+         if (memory_size >= 0x100000000)
+           {
+             return clib_error_return
+               (0, "max-rx-fifo %llu (0x%llx) too large", memory_size,
+                memory_size);
+           }
+         tcp_cfg.max_rx_fifo = memory_size;
+       }
       else if (unformat (input, "min-rx-fifo %U", unformat_memory_size,
                         &memory_size))
-       tcp_cfg.min_rx_fifo = memory_size;
+       {
+         if (memory_size >= 0x100000000)
+           {
+             return clib_error_return
+               (0, "min-rx-fifo %llu (0x%llx) too large", memory_size,
+                memory_size);
+           }
+         tcp_cfg.min_rx_fifo = memory_size;
+       }
       else if (unformat (input, "mtu %u", &tcp_cfg.default_mtu))
        ;
       else if (unformat (input, "rwnd-min-update-ack %d",
@@ -1774,6 +1818,8 @@ tcp_config_fn (vlib_main_t * vm, unformat_input_t * input)
        tcp_cfg.enable_tx_pacing = 0;
       else if (unformat (input, "tso"))
        tcp_cfg.allow_tso = 1;
+      else if (unformat (input, "no-csum-offload"))
+       tcp_cfg.csum_offload = 0;
       else if (unformat (input, "cc-algo %U", unformat_tcp_cc_algo,
                         &tcp_cfg.cc_algo))
        ;