Overall tcp performance improvements (VPP-846)

- limit minimum rto per connection
- cleanup sack scoreboard
- switched svm fifo out-of-order data handling from absolute offsets to
  relative offsets.
- improve cwnd handling when using sacks
- add cc event debug stats
- improved uri tcp test client/server:  bugfixes and added half-duplex mode
- expanded builtin client/server
- updated uri socket client/server code to work in half-duplex
- ensure session node unsets fifo event for empty fifo
- fix session detach

Change-Id: Ia446972340e32a65e0694ee2844355167d0c170d
Signed-off-by: Florin Coras <fcoras@cisco.com>
diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c
index c679b1f..4bdb102 100644
--- a/src/vnet/session/application.c
+++ b/src/vnet/session/application.c
@@ -117,7 +117,7 @@
   /* Actual listener cleanup */
   for (i = 0; i < vec_len (handles); i++)
     {
-      a->app_index = app->api_client_index;
+      a->app_index = app->index;
       a->handle = handles[i];
       /* seg manager is removed when unbind completes */
       vnet_unbind (a);
diff --git a/src/vnet/session/node.c b/src/vnet/session/node.c
index 07eeae8..c0ab1bf 100644
--- a/src/vnet/session/node.c
+++ b/src/vnet/session/node.c
@@ -171,7 +171,10 @@
 
   /* Nothing to read return */
   if (max_dequeue0 == 0)
-    return 0;
+    {
+      svm_fifo_unset_event (s0->server_tx_fifo);
+      return 0;
+    }
 
   /* Ensure we're not writing more than transport window allows */
   if (max_dequeue0 < snd_space0)
@@ -393,7 +396,7 @@
 
   s0 = stream_session_get_if_valid (session_index0, thread_index);
 
-  ASSERT (s0->thread_index == thread_index);
+  ASSERT (s0 == 0 || s0->thread_index == thread_index);
 
   return s0;
 }
diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c
index caf8eaa..bf57196 100644
--- a/src/vnet/session/segment_manager.c
+++ b/src/vnet/session/segment_manager.c
@@ -306,11 +306,13 @@
 	  if (added_a_segment)
 	    {
 	      clib_warning ("added a segment, still cant allocate a fifo");
+	      clib_spinlock_unlock (&sm->lockp);
 	      return SESSION_ERROR_NEW_SEG_NO_SPACE;
 	    }
 
 	  if (session_manager_add_segment (sm))
 	    {
+	      clib_spinlock_unlock (&sm->lockp);
 	      return VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
 	    }
 
@@ -320,6 +322,7 @@
       else
 	{
 	  clib_warning ("No space to allocate fifos!");
+	  clib_spinlock_unlock (&sm->lockp);
 	  return SESSION_ERROR_NO_SPACE;
 	}
     }
@@ -361,8 +364,10 @@
   if (sm->segment_indices[0] != svm_segment_index
       && !svm_fifo_segment_has_fifos (fifo_segment))
     {
+      clib_spinlock_lock (&sm->lockp);
       svm_fifo_segment_delete (fifo_segment);
       vec_del1 (sm->segment_indices, svm_segment_index);
+      clib_spinlock_unlock (&sm->lockp);
     }
 }
 
diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c
index 534598d..fe19804 100644
--- a/src/vnet/session/session.c
+++ b/src/vnet/session/session.c
@@ -700,7 +700,7 @@
   svm_fifo_init_pointers (s->server_tx_fifo, tx_pointer);
 }
 
-void
+int
 stream_session_connect_notify (transport_connection_t * tc, u8 sst,
 			       u8 is_fail)
 {
@@ -709,6 +709,7 @@
   stream_session_t *new_s = 0;
   u64 handle;
   u32 api_context = 0;
+  int error = 0;
 
   handle = stream_session_half_open_lookup (smm, &tc->lcl_ip, &tc->rmt_ip,
 					    tc->lcl_port, tc->rmt_port,
@@ -716,7 +717,7 @@
   if (handle == HALF_OPEN_LOOKUP_INVALID_VALUE)
     {
       clib_warning ("This can't be good!");
-      return;
+      return -1;
     }
 
   /* Get the app's index from the handle we stored when opening connection */
@@ -730,9 +731,12 @@
 
       /* Create new session (svm segments are allocated if needed) */
       if (stream_session_create_i (sm, tc, &new_s))
-	return;
-
-      new_s->app_index = app->index;
+	{
+	  is_fail = 1;
+	  error = -1;
+	}
+      else
+	new_s->app_index = app->index;
     }
 
   /* Notify client */
@@ -741,6 +745,8 @@
 
   /* Cleanup session lookup */
   stream_session_half_open_table_del (smm, sst, tc);
+
+  return error;
 }
 
 void
@@ -981,8 +987,13 @@
 
   /* Based on request block (or not) for lack of space */
   if (PREDICT_TRUE (q->cursize < q->maxsize))
-    unix_shared_memory_queue_add (q, (u8 *) & evt,
-				  0 /* do wait for mutex */ );
+    {
+      if (unix_shared_memory_queue_add (q, (u8 *) & evt,
+					1 /* do wait for mutex */ ))
+	{
+	  clib_warning ("failed to enqueue evt");
+	}
+    }
   else
     {
       clib_warning ("queue full");
diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h
index d9c38bd..5fa4225 100644
--- a/src/vnet/session/session.h
+++ b/src/vnet/session/session.h
@@ -368,8 +368,8 @@
 			   u32 offset, u32 max_bytes);
 u32 stream_session_dequeue_drop (transport_connection_t * tc, u32 max_bytes);
 
-void stream_session_connect_notify (transport_connection_t * tc, u8 sst,
-				    u8 is_fail);
+int stream_session_connect_notify (transport_connection_t * tc, u8 sst,
+				   u8 is_fail);
 void stream_session_init_fifos_pointers (transport_connection_t * tc,
 					 u32 rx_pointer, u32 tx_pointer);
 
diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c
index f772cb9..60f764a 100755
--- a/src/vnet/session/session_api.c
+++ b/src/vnet/session/session_api.c
@@ -419,7 +419,7 @@
   REPLY_MACRO (VL_API_UNBIND_URI_REPLY);
 }
 
-void
+static void
 vl_api_connect_uri_t_handler (vl_api_connect_uri_t * mp)
 {
   vl_api_connect_uri_reply_t *rmp;
diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h
index e5f788b..04bd5ca 100644
--- a/src/vnet/session/transport.h
+++ b/src/vnet/session/transport.h
@@ -39,6 +39,7 @@
 
 #if TRANSPORT_DEBUG
   elog_track_t elog_track;	/**< Event logging */
+  u32 cc_stat_tstamp;		/**< CC stats timestamp */
 #endif
 
   /** Macros for 'derived classes' where base is named "connection" */
@@ -57,6 +58,7 @@
 #define c_is_ip4 connection.is_ip4
 #define c_thread_index connection.thread_index
 #define c_elog_track connection.elog_track
+#define c_cc_stat_tstamp connection.cc_stat_tstamp
 } transport_connection_t;
 
 /*