tcp: cubic as default cc algorithm
[vpp.git] / src / vnet / tcp / tcp.c
index 2ac938a..df3d61d 100644 (file)
@@ -186,7 +186,7 @@ tcp_session_get_listener (u32 listener_index)
  *
  */
 static void
-tcp_half_open_connection_del (tcp_connection_t * tc)
+tcp_half_open_connection_free (tcp_connection_t * tc)
 {
   tcp_main_t *tm = vnet_get_tcp_main ();
   clib_spinlock_lock_if_init (&tm->half_open_lock);
@@ -208,11 +208,16 @@ tcp_half_open_connection_del (tcp_connection_t * tc)
 int
 tcp_half_open_connection_cleanup (tcp_connection_t * tc)
 {
+  tcp_worker_ctx_t *wrk;
+
   /* Make sure this is the owning thread */
   if (tc->c_thread_index != vlib_get_thread_index ())
     return 1;
-  tcp_timer_reset (tc, TCP_TIMER_RETRANSMIT_SYN);
-  tcp_half_open_connection_del (tc);
+
+  session_half_open_delete_notify (TRANSPORT_PROTO_TCP, tc->c_s_ho_handle);
+  wrk = tcp_get_worker (tc->c_thread_index);
+  tcp_timer_reset (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT_SYN);
+  tcp_half_open_connection_free (tc);
   return 0;
 }
 
@@ -354,6 +359,8 @@ tcp_program_cleanup (tcp_worker_ctx_t * wrk, tcp_connection_t * tc)
 void
 tcp_connection_close (tcp_connection_t * tc)
 {
+  tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
+
   TCP_EVT (TCP_EVT_CLOSE, tc);
 
   /* Send/Program FIN if needed and switch state */
@@ -368,7 +375,8 @@ tcp_connection_close (tcp_connection_t * tc)
       tcp_connection_timers_reset (tc);
       tcp_send_fin (tc);
       tcp_connection_set_state (tc, TCP_STATE_FIN_WAIT_1);
-      tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait1_time);
+      tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_WAITCLOSE,
+                       tcp_cfg.finwait1_time);
       break;
     case TCP_STATE_ESTABLISHED:
       /* If closing with unread data, reset the connection */
@@ -379,7 +387,7 @@ tcp_connection_close (tcp_connection_t * tc)
          tcp_connection_set_state (tc, TCP_STATE_CLOSED);
          session_transport_closed_notify (&tc->connection);
          tcp_program_cleanup (tcp_get_worker (tc->c_thread_index), tc);
-         tcp_worker_stats_inc (tc->c_thread_index, rst_unread, 1);
+         tcp_worker_stats_inc (wrk, rst_unread, 1);
          break;
        }
       if (!transport_max_tx_dequeue (&tc->connection))
@@ -390,7 +398,8 @@ tcp_connection_close (tcp_connection_t * tc)
       /* Set a timer in case the peer stops responding. Otherwise the
        * connection will be stuck here forever. */
       ASSERT (tc->timers[TCP_TIMER_WAITCLOSE] == TCP_TIMER_HANDLE_INVALID);
-      tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait1_time);
+      tcp_timer_set (&wrk->timer_wheel, tc, TCP_TIMER_WAITCLOSE,
+                    tcp_cfg.finwait1_time);
       break;
     case TCP_STATE_CLOSE_WAIT:
       if (!transport_max_tx_dequeue (&tc->connection))
@@ -398,13 +407,15 @@ tcp_connection_close (tcp_connection_t * tc)
          tcp_send_fin (tc);
          tcp_connection_timers_reset (tc);
          tcp_connection_set_state (tc, TCP_STATE_LAST_ACK);
-         tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.lastack_time);
+         tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_WAITCLOSE,
+                           tcp_cfg.lastack_time);
        }
       else
        tc->flags |= TCP_CONN_FINPNDG;
       break;
     case TCP_STATE_FIN_WAIT_1:
-      tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait1_time);
+      tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_WAITCLOSE,
+                       tcp_cfg.finwait1_time);
       break;
     case TCP_STATE_CLOSED:
       /* Cleanup should've been programmed already */
@@ -433,6 +444,18 @@ tcp_session_cleanup (u32 conn_index, u32 thread_index)
   tcp_connection_cleanup (tc);
 }
 
+static void
+tcp_session_cleanup_ho (u32 conn_index)
+{
+  tcp_worker_ctx_t *wrk;
+  tcp_connection_t *tc;
+
+  tc = tcp_half_open_connection_get (conn_index);
+  wrk = tcp_get_worker (tc->c_thread_index);
+  tcp_timer_reset (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT_SYN);
+  tcp_half_open_connection_free (tc);
+}
+
 static void
 tcp_session_reset (u32 conn_index, u32 thread_index)
 {
@@ -469,11 +492,11 @@ tcp_connection_timers_init (tcp_connection_t * tc)
 void
 tcp_connection_timers_reset (tcp_connection_t * tc)
 {
+  tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
   int i;
+
   for (i = 0; i < TCP_N_TIMERS; i++)
-    {
-      tcp_timer_reset (tc, i);
-    }
+    tcp_timer_reset (&wrk->timer_wheel, tc, i);
 }
 
 #if 0
@@ -728,10 +751,7 @@ tcp_alloc_custom_local_endpoint (tcp_main_t * tm, ip46_address_t * lcl_addr,
     }
   port = transport_alloc_local_port (TRANSPORT_PROTO_TCP, lcl_addr);
   if (port < 1)
-    {
-      clib_warning ("Failed to allocate src port");
-      return -1;
-    }
+    return SESSION_E_NOPORT;
   *lcl_port = port;
   return 0;
 }
@@ -757,7 +777,20 @@ tcp_session_open (transport_endpoint_cfg_t * rmt)
                                         rmt, &lcl_addr, &lcl_port);
 
   if (rv)
-    return -1;
+    {
+      if (rv != SESSION_E_PORTINUSE)
+       return rv;
+
+      if (session_lookup_connection (rmt->fib_index, &lcl_addr, &rmt->ip,
+                                    lcl_port, rmt->port, TRANSPORT_PROTO_UDP,
+                                    rmt->is_ip4))
+       return SESSION_E_PORTINUSE;
+
+      /* 5-tuple is available so increase lcl endpoint refcount and proceed
+       * with connection allocation */
+      transport_share_local_endpoint (TRANSPORT_PROTO_UDP, &lcl_addr,
+                                     lcl_port);
+    }
 
   /*
    * Create connection and send SYN
@@ -956,7 +989,7 @@ tcp_timer_waitclose_handler (tcp_connection_t * tc)
          tcp_connection_set_state (tc, TCP_STATE_CLOSED);
          session_transport_closed_notify (&tc->connection);
          tcp_program_cleanup (wrk, tc);
-         tcp_workerp_stats_inc (wrk, to_closewait, 1);
+         tcp_worker_stats_inc (wrk, to_closewait, 1);
          break;
        }
 
@@ -969,8 +1002,9 @@ tcp_timer_waitclose_handler (tcp_connection_t * tc)
       session_transport_closed_notify (&tc->connection);
 
       /* Make sure we don't wait in LAST ACK forever */
-      tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.lastack_time);
-      tcp_workerp_stats_inc (wrk, to_closewait2, 1);
+      tcp_timer_set (&wrk->timer_wheel, tc, TCP_TIMER_WAITCLOSE,
+                    tcp_cfg.lastack_time);
+      tcp_worker_stats_inc (wrk, to_closewait2, 1);
 
       /* Don't delete the connection yet */
       break;
@@ -992,21 +1026,21 @@ tcp_timer_waitclose_handler (tcp_connection_t * tc)
          tcp_program_cleanup (wrk, tc);
        }
       session_transport_closed_notify (&tc->connection);
-      tcp_workerp_stats_inc (wrk, to_finwait1, 1);
+      tcp_worker_stats_inc (wrk, to_finwait1, 1);
       break;
     case TCP_STATE_LAST_ACK:
       tcp_connection_timers_reset (tc);
       tcp_connection_set_state (tc, TCP_STATE_CLOSED);
       session_transport_closed_notify (&tc->connection);
       tcp_program_cleanup (wrk, tc);
-      tcp_workerp_stats_inc (wrk, to_lastack, 1);
+      tcp_worker_stats_inc (wrk, to_lastack, 1);
       break;
     case TCP_STATE_CLOSING:
       tcp_connection_timers_reset (tc);
       tcp_connection_set_state (tc, TCP_STATE_CLOSED);
       session_transport_closed_notify (&tc->connection);
       tcp_program_cleanup (wrk, tc);
-      tcp_workerp_stats_inc (wrk, to_closing, 1);
+      tcp_worker_stats_inc (wrk, to_closing, 1);
       break;
     case TCP_STATE_FIN_WAIT_2:
       tcp_send_reset (tc);
@@ -1014,7 +1048,7 @@ tcp_timer_waitclose_handler (tcp_connection_t * tc)
       tcp_connection_set_state (tc, TCP_STATE_CLOSED);
       session_transport_closed_notify (&tc->connection);
       tcp_program_cleanup (wrk, tc);
-      tcp_workerp_stats_inc (wrk, to_finwait2, 1);
+      tcp_worker_stats_inc (wrk, to_finwait2, 1);
       break;
     case TCP_STATE_TIME_WAIT:
       tcp_connection_set_state (tc, TCP_STATE_CLOSED);
@@ -1127,6 +1161,7 @@ const static transport_proto_vft_t tcp_proto = {
   .connect = tcp_session_open,
   .close = tcp_session_close,
   .cleanup = tcp_session_cleanup,
+  .cleanup_ho = tcp_session_cleanup_ho,
   .reset = tcp_session_reset,
   .send_params = tcp_session_send_params,
   .update_time = tcp_update_time,
@@ -1186,7 +1221,7 @@ tcp_expired_timers_dispatch (u32 * expired_timers)
 
   wrk = tcp_get_worker (thread_index);
   n_expired = vec_len (expired_timers);
-  tcp_workerp_stats_inc (wrk, timer_expirations, n_expired);
+  tcp_worker_stats_inc (wrk, timer_expirations, n_expired);
   n_left = clib_fifo_elts (wrk->pending_timers);
 
   /*
@@ -1386,7 +1421,7 @@ tcp_configuration_init (void)
   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.cc_algo = TCP_CC_CUBIC;
   tcp_cfg.rwnd_min_update_ack = 1;
 
   /* Time constants defined as timer tick (100ms) multiples */