session: disconnect and echo client improvements

Change-Id: If421bad17b6cfe8e321257c93bb38931e37d7b64
Signed-off-by: Florin Coras <fcoras@cisco.com>
diff --git a/src/vnet/session-apps/echo_client.c b/src/vnet/session-apps/echo_client.c
index b8a4fb3..c38b533 100644
--- a/src/vnet/session-apps/echo_client.c
+++ b/src/vnet/session-apps/echo_client.c
@@ -257,7 +257,10 @@
 	      __sync_fetch_and_add (&ecm->ready_connections, -1);
 	    }
 	  else
-	    clib_warning ("session AWOL?");
+	    {
+	      clib_warning ("session AWOL?");
+	      vec_delete (connections_this_batch, 1, i);
+	    }
 
 	  /* Kick the debug CLI process */
 	  if (ecm->ready_connections == 0)
@@ -407,7 +410,6 @@
 static int
 echo_clients_rx_callback (stream_session_t * s)
 {
-  clib_warning ("BUG");
   return 0;
 }
 
@@ -424,7 +426,7 @@
 static clib_error_t *
 echo_clients_attach (u8 * appns_id, u64 appns_flags, u64 appns_secret)
 {
-  u32 prealloc_fifos, segment_size = 2 << 20;
+  u32 prealloc_fifos, segment_size = 256 << 20;
   echo_client_main_t *ecm = &echo_client_main;
   vnet_app_attach_args_t _a, *a = &_a;
   u64 options[16];
@@ -543,15 +545,16 @@
 {
   echo_client_main_t *ecm = &echo_client_main;
   vlib_thread_main_t *thread_main = vlib_get_thread_main ();
-  uword *event_data = 0, event_type;
-  u8 *default_uri = (u8 *) "tcp://6.0.1.1/1234", *appns_id = 0;
   u64 tmp, total_bytes, appns_flags = 0, appns_secret = 0;
   f64 test_timeout = 20.0, syn_timeout = 20.0, delta;
+  char *default_uri = "tcp://6.0.1.1/1234";
+  uword *event_data = 0, event_type;
   f64 time_before_connects;
   u32 n_clients = 1;
   int preallocate_sessions = 0;
   char *transfer_type;
   clib_error_t *error = 0;
+  u8 *appns_id = 0;
   int i;
 
   ecm->bytes_to_send = 8192;
@@ -644,8 +647,8 @@
 
   if (!ecm->connect_uri)
     {
-      clib_warning ("No uri provided. Using default: %v", default_uri);
-      ecm->connect_uri = default_uri;
+      clib_warning ("No uri provided. Using default: %s", default_uri);
+      ecm->connect_uri = format (0, "%s%c", default_uri, 0);
     }
 
 #if ECHO_CLIENT_PTHREAD
@@ -785,6 +788,7 @@
     }
   if (error)
     ec_cli_output ("test failed");
+  vec_free (ecm->connect_uri);
   return error;
 }
 
diff --git a/src/vnet/session/application_interface.c b/src/vnet/session/application_interface.c
index 63666a6..ad4c28b 100644
--- a/src/vnet/session/application_interface.c
+++ b/src/vnet/session/application_interface.c
@@ -500,8 +500,7 @@
   /* We're peeking into another's thread pool. Make sure */
   ASSERT (s->session_index == index);
 
-  session_send_session_evt_to_thread (a->handle, FIFO_EVENT_DISCONNECT,
-				      thread_index);
+  stream_session_disconnect (s);
   return 0;
 }
 
diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c
index c3a794b..83b8388 100644
--- a/src/vnet/session/segment_manager.c
+++ b/src/vnet/session/segment_manager.c
@@ -306,12 +306,7 @@
 
 	  /* Instead of directly removing the session call disconnect */
 	  if (session->session_state != SESSION_STATE_CLOSED)
-	    {
-	      session->session_state = SESSION_STATE_CLOSED;
-	      session_send_session_evt_to_thread (session_handle (session),
-						  FIFO_EVENT_DISCONNECT,
-						  thread_index);
-	    }
+	    stream_session_disconnect (session);
 	  fifo = fifo->next;
 	}
 
@@ -611,7 +606,7 @@
       segments = svm_fifo_segment_segments_pool ();
       vlib_cli_output (vm, "%d svm fifo segments allocated",
 		       pool_elts (segments));
-      vlib_cli_output (vm, "%-15s%10s%15s%15s%15s%15s", "Name", "Type",
+      vlib_cli_output (vm, "%-15s%15s%15s%15s%15s%15s", "Name", "Type",
 		       "HeapSize (M)", "ActiveFifos", "FreeFifos", "Address");
 
       /* *INDENT-OFF* */
@@ -619,7 +614,7 @@
 	svm_fifo_segment_info (seg, &address, &size);
 	active_fifos = svm_fifo_segment_num_fifos (seg);
         free_fifos = svm_fifo_segment_num_free_fifos (seg, ~0 /* size */);
-	vlib_cli_output (vm, "%-15v%10U%15llu%15u%15u%15llx",
+	vlib_cli_output (vm, "%-15v%15U%15llu%15u%15u%15llx",
 	                 ssvm_name (&seg->ssvm), format_svm_fifo_segment_type,
 	                 seg, size >> 20ULL, active_fifos, free_fifos,
 	                 address);
diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c
index be98e71..ec6d781 100644
--- a/src/vnet/session/session.c
+++ b/src/vnet/session/session.c
@@ -599,7 +599,7 @@
     {
       SESSION_DBG ("failed to notify app");
       if (!is_fail)
-	stream_session_disconnect (new_s);
+	stream_session_disconnect_transport (new_s);
     }
   else
     {
@@ -924,15 +924,31 @@
 }
 
 /**
- * Disconnect session and propagate to transport. This should eventually
- * result in a delete notification that allows us to cleanup session state.
- * Called for both active/passive disconnects.
+ * Initialize session disconnect.
  *
- * Should be called from the session's thread.
+ * Request is always sent to session node to ensure that all outstanding
+ * requests are served before transport is notified.
  */
 void
 stream_session_disconnect (stream_session_t * s)
 {
+  if (!s || s->session_state == SESSION_STATE_CLOSED)
+    return;
+  s->session_state = SESSION_STATE_CLOSED;
+  session_send_session_evt_to_thread (session_handle (s),
+				      FIFO_EVENT_DISCONNECT, s->thread_index);
+}
+
+/**
+ * Notify transport the session can be disconnected. This should eventually
+ * result in a delete notification that allows us to cleanup session state.
+ * Called for both active/passive disconnects.
+ *
+ * Must be called from the session's thread.
+ */
+void
+stream_session_disconnect_transport (stream_session_t * s)
+{
   s->session_state = SESSION_STATE_CLOSED;
   tp_vfts[session_get_transport_proto (s)].close (s->connection_index,
 						  s->thread_index);
diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h
index 98e8acb..da9332a 100644
--- a/src/vnet/session/session.h
+++ b/src/vnet/session/session.h
@@ -448,6 +448,7 @@
 int stream_session_listen (stream_session_t * s, session_endpoint_t * tep);
 int stream_session_stop_listen (stream_session_t * s);
 void stream_session_disconnect (stream_session_t * s);
+void stream_session_disconnect_transport (stream_session_t * s);
 void stream_session_cleanup (stream_session_t * s);
 void session_send_session_evt_to_thread (u64 session_handle,
 					 fifo_event_type_t evt_type,
diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c
index a1608f4..796056e 100644
--- a/src/vnet/session/session_node.c
+++ b/src/vnet/session/session_node.c
@@ -649,7 +649,7 @@
 	      continue;
 	    }
 	  s0 = session_get_from_handle (e0->session_handle);
-	  stream_session_disconnect (s0);
+	  stream_session_disconnect_transport (s0);
 	  break;
 	case FIFO_EVENT_BUILTIN_RX:
 	  s0 = session_event_get_session (e0, my_thread_index);
diff --git a/src/vnet/tcp/tcp_debug.h b/src/vnet/tcp/tcp_debug.h
index e0db7f4..5d4f7d6 100755
--- a/src/vnet/tcp/tcp_debug.h
+++ b/src/vnet/tcp/tcp_debug.h
@@ -19,7 +19,7 @@
 #include <vlib/vlib.h>
 
 #define TCP_DEBUG (1)
-#define TCP_DEBUG_SM (1)
+#define TCP_DEBUG_SM (0)
 #define TCP_DEBUG_CC (0)
 #define TCP_DEBUG_CC_STAT (1)
 #define TCP_DEBUG_BUFFER_ALLOCATION (0)