session: improve close procedure 81/14881/2
authorFlorin Coras <fcoras@cisco.com>
Tue, 18 Sep 2018 23:12:50 +0000 (16:12 -0700)
committerMarco Varlese <marco.varlese@suse.de>
Wed, 19 Sep 2018 06:05:29 +0000 (06:05 +0000)
Change-Id: I6201a044e70ab6a58db8212960c57edc77c41f96
Signed-off-by: Florin Coras <fcoras@cisco.com>
src/vlib/threads.h
src/vnet/session/application_interface.c
src/vnet/session/segment_manager.c
src/vnet/session/session.c
src/vnet/session/session.h
src/vnet/session/stream_session.h

index b47a633..1794453 100644 (file)
@@ -445,6 +445,14 @@ vlib_get_worker_vlib_main (u32 worker_index)
   return vm;
 }
 
+static inline u8
+vlib_thread_is_main_w_barrier (void)
+{
+  return (!vlib_num_workers ()
+         || ((vlib_get_thread_index () == 0
+              && vlib_worker_threads->wait_at_barrier[0])));
+}
+
 static inline void
 vlib_put_frame_queue_elt (vlib_frame_queue_elt_t * hf)
 {
index 72a9985..d35a829 100644 (file)
@@ -82,9 +82,7 @@ const char test_srv_key_rsa[] =
 const u32 test_srv_key_rsa_len = sizeof (test_srv_key_rsa);
 
 #define app_interface_check_thread_and_barrier(_fn, _arg)              \
-  if (PREDICT_FALSE (vlib_get_thread_index () != 0 ||                  \
-                     (vlib_worker_threads[0].wait_at_barrier &&                \
-                     !vlib_worker_threads[0].wait_at_barrier[0])))     \
+  if (PREDICT_FALSE (!vlib_thread_is_main_w_barrier ()))               \
     {                                                                  \
       vlib_rpc_call_main_thread (_fn, (u8 *) _arg, sizeof(*_arg));     \
       return 0;                                                                \
index 0c19293..bf62040 100644 (file)
@@ -591,7 +591,9 @@ segment_manager_dealloc_fifos (u32 segment_index, svm_fifo_t * rx_fifo,
       /* Remove segment manager if no sessions and detached from app */
       if (segment_manager_app_detached (sm)
          && !segment_manager_has_fifos (sm))
-       segment_manager_del (sm);
+       {
+         segment_manager_del (sm);
+       }
     }
   else
     segment_manager_segment_reader_unlock (sm);
index 133c91c..3eaf984 100644 (file)
@@ -152,6 +152,14 @@ session_free (stream_session_t * s)
     memset (s, 0xFA, sizeof (*s));
 }
 
+static void
+session_free_w_fifos (stream_session_t * s)
+{
+  segment_manager_dealloc_fifos (s->svm_segment_index, s->server_rx_fifo,
+                                s->server_tx_fifo);
+  session_free (s);
+}
+
 int
 session_alloc_fifos (segment_manager_t * sm, stream_session_t * s)
 {
@@ -751,7 +759,7 @@ stream_session_disconnect_notify (transport_connection_t * tc)
   stream_session_t *s;
 
   s = session_get (tc->s_index, tc->thread_index);
-  s->session_state = SESSION_STATE_CLOSING;
+  s->session_state = SESSION_STATE_TRANSPORT_CLOSING;
   app_wrk = app_worker_get_if_valid (s->app_wrk_index);
   if (!app_wrk)
     return;
@@ -773,10 +781,7 @@ stream_session_delete (stream_session_t * s)
   if ((rv = session_lookup_del_session (s)))
     clib_warning ("hash delete error, rv %d", rv);
 
-  /* Cleanup fifo segments */
-  segment_manager_dealloc_fifos (s->svm_segment_index, s->server_rx_fifo,
-                                s->server_tx_fifo);
-  session_free (s);
+  session_free_w_fifos (s);
 }
 
 /**
@@ -793,10 +798,30 @@ stream_session_delete_notify (transport_connection_t * tc)
   stream_session_t *s;
 
   /* App might've been removed already */
-  s = session_get_if_valid (tc->s_index, tc->thread_index);
-  if (!s)
+  if (!(s = session_get_if_valid (tc->s_index, tc->thread_index)))
     return;
-  stream_session_delete (s);
+
+  /* Make sure we don't try to send anything more */
+  svm_fifo_dequeue_drop_all (s->server_tx_fifo);
+
+  switch (s->session_state)
+    {
+    case SESSION_STATE_TRANSPORT_CLOSING:
+      /* If transport finishes or times out before we get a reply
+       * from the app, do the whole disconnect since we might still
+       * have lingering events */
+      stream_session_disconnect (s);
+      break;
+    case SESSION_STATE_CLOSING:
+      /* Cleanup lookup table. Transport needs to still be valid */
+      session_lookup_del_session (s);
+      break;
+    case SESSION_STATE_CLOSED:
+      stream_session_delete (s);
+      break;
+    }
+
+  s->session_state = SESSION_STATE_CLOSED;
 }
 
 /**
@@ -1050,11 +1075,9 @@ stream_session_disconnect (stream_session_t * s)
   s->session_state = SESSION_STATE_CLOSING;
 
   /* If we are in the handler thread, or being called with the worker barrier
-   * held (api/cli), just append a new event to pending disconnects vector. */
-  if ((thread_index == 0 && !vlib_get_current_process (vlib_get_main ()))
-      || thread_index == s->thread_index)
+   * held, just append a new event to pending disconnects vector. */
+  if (vlib_thread_is_main_w_barrier () || thread_index == s->thread_index)
     {
-      ASSERT (s->thread_index == thread_index || thread_index == 0);
       vec_add2 (smm->pending_disconnects[s->thread_index], evt, 1);
       memset (evt, 0, sizeof (*evt));
       evt->session_handle = session_handle (s);
@@ -1074,6 +1097,12 @@ stream_session_disconnect (stream_session_t * s)
 void
 stream_session_disconnect_transport (stream_session_t * s)
 {
+  /* If transport is already closed, just free the session */
+  if (s->session_state == SESSION_STATE_CLOSED)
+    {
+      session_free_w_fifos (s);
+      return;
+    }
   s->session_state = SESSION_STATE_CLOSED;
   tp_vfts[session_get_transport_proto (s)].close (s->connection_index,
                                                  s->thread_index);
@@ -1097,9 +1126,7 @@ stream_session_cleanup (stream_session_t * s)
                                                    s->thread_index);
   /* Since we called cleanup, no delete notification will come. So, make
    * sure the session is properly freed. */
-  segment_manager_dealloc_fifos (s->svm_segment_index, s->server_rx_fifo,
-                                s->server_tx_fifo);
-  session_free (s);
+  session_free_w_fifos (s);
 }
 
 transport_service_type_t
index 19609da..aa82755 100644 (file)
@@ -561,6 +561,7 @@ int session_send_io_evt_to_thread_custom (svm_fifo_t * f, u32 thread_index,
                                          session_evt_type_t evt_type);
 void session_send_rpc_evt_to_thread (u32 thread_index, void *fp,
                                     void *rpc_args);
+
 ssvm_private_t *session_manager_get_evt_q_segment (void);
 
 u8 *format_stream_session (u8 * s, va_list * args);
index b08f959..30178d7 100644 (file)
@@ -31,6 +31,7 @@ typedef enum
   SESSION_STATE_ACCEPTING,
   SESSION_STATE_READY,
   SESSION_STATE_OPENED,
+  SESSION_STATE_TRANSPORT_CLOSING,
   SESSION_STATE_CLOSING,
   SESSION_STATE_CLOSED,
   SESSION_STATE_N_STATES,