session: add unix socket api for app attachment
[vpp.git] / src / vnet / session / session.c
index d2dc85e..d27d1bb 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 #include <vnet/session/session.h>
-#include <vnet/session/session_debug.h>
 #include <vnet/session/application.h>
 #include <vnet/dpo/load_balance.h>
 #include <vnet/fib/ip4_fib.h>
@@ -283,6 +282,20 @@ session_delete (session_t * s)
   session_free_w_fifos (s);
 }
 
+void
+session_cleanup_half_open (transport_proto_t tp, session_handle_t ho_handle)
+{
+  transport_cleanup_half_open (tp, session_handle_index (ho_handle));
+}
+
+void
+session_half_open_delete_notify (transport_proto_t tp,
+                                session_handle_t ho_handle)
+{
+  app_worker_t *app_wrk = app_worker_get (session_handle_data (ho_handle));
+  app_worker_del_half_open (app_wrk, tp, ho_handle);
+}
+
 session_t *
 session_alloc_for_connection (transport_connection_t * tc)
 {
@@ -611,6 +624,11 @@ session_enqueue_notify_inline (session_t * s)
   SESSION_EVT (SESSION_EVT_ENQ, s, svm_fifo_max_dequeue_prod (s->rx_fifo));
 
   s->flags &= ~SESSION_F_RX_EVT;
+
+  /* Application didn't confirm accept yet */
+  if (PREDICT_FALSE (s->session_state == SESSION_STATE_ACCEPTING))
+    return 0;
+
   if (PREDICT_FALSE (app_worker_lock_and_send_event (app_wrk, s,
                                                     SESSION_IO_EVT_RX)))
     return -1;
@@ -735,15 +753,14 @@ session_main_flush_all_enqueue_events (u8 transport_proto)
   return errors;
 }
 
-static inline int
-session_stream_connect_notify_inline (transport_connection_t * tc,
-                                     session_error_t err,
-                                     session_state_t opened_state)
+int
+session_stream_connect_notify (transport_connection_t * tc,
+                              session_error_t err)
 {
+  session_handle_t ho_handle, wrk_handle;
   u32 opaque = 0, new_ti, new_si;
   app_worker_t *app_wrk;
   session_t *s = 0;
-  u64 ho_handle;
 
   /*
    * Find connection handle and cleanup half-open table
@@ -759,11 +776,19 @@ session_stream_connect_notify_inline (transport_connection_t * tc,
   /* Get the app's index from the handle we stored when opening connection
    * and the opaque (api_context for external apps) from transport session
    * index */
-  app_wrk = app_worker_get_if_valid (ho_handle >> 32);
+  app_wrk = app_worker_get_if_valid (session_handle_data (ho_handle));
   if (!app_wrk)
     return -1;
 
-  opaque = tc->s_index;
+  wrk_handle = app_worker_lookup_half_open (app_wrk, tc->proto, ho_handle);
+  if (wrk_handle == SESSION_INVALID_HANDLE)
+    return -1;
+
+  /* Make sure this is the same half-open index */
+  if (session_handle_index (wrk_handle) != session_handle_index (ho_handle))
+    return -1;
+
+  opaque = session_handle_data (wrk_handle);
 
   if (err)
     return app_worker_connect_notify (app_wrk, s, err, opaque);
@@ -782,33 +807,22 @@ session_stream_connect_notify_inline (transport_connection_t * tc,
     }
 
   s = session_get (new_si, new_ti);
-  s->session_state = opened_state;
+  s->session_state = SESSION_STATE_READY;
   session_lookup_add_connection (tc, session_handle (s));
 
   if (app_worker_connect_notify (app_wrk, s, SESSION_E_NONE, opaque))
     {
+      session_lookup_del_connection (tc);
+      /* Avoid notifying app about rejected session cleanup */
       s = session_get (new_si, new_ti);
-      session_free_w_fifos (s);
+      segment_manager_dealloc_fifos (s->rx_fifo, s->tx_fifo);
+      session_free (s);
       return -1;
     }
 
   return 0;
 }
 
-int
-session_stream_connect_notify (transport_connection_t * tc,
-                              session_error_t err)
-{
-  return session_stream_connect_notify_inline (tc, err, SESSION_STATE_READY);
-}
-
-int
-session_ho_stream_connect_notify (transport_connection_t * tc,
-                                 session_error_t err)
-{
-  return session_stream_connect_notify_inline (tc, err, SESSION_STATE_OPENED);
-}
-
 static void
 session_switch_pool_reply (void *arg)
 {
@@ -1199,7 +1213,7 @@ session_open_vc (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque)
 {
   transport_connection_t *tc;
   transport_endpoint_cfg_t *tep;
-  u64 handle;
+  u64 handle, wrk_handle;
   int rv;
 
   tep = session_endpoint_to_transport_cfg (rmt);
@@ -1219,15 +1233,21 @@ session_open_vc (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque)
    * is needed when the connect notify comes and we have to notify the
    * external app
    */
-  handle = (((u64) app_wrk_index) << 32) | (u64) tc->c_index;
+  handle = session_make_handle (tc->c_index, app_wrk_index);
   session_lookup_add_half_open (tc, handle);
 
-  /* Store api_context (opaque) for when the reply comes. Not the nicest
-   * thing but better than allocating a separate half-open pool.
+  /* Store the half-open handle in the connection. Transport will use it
+   * when cleaning up @ref session_half_open_delete_notify
    */
-  tc->s_index = opaque;
-  if (transport_half_open_has_fifos (rmt->transport_proto))
-    return session_ho_stream_connect_notify (tc, 0 /* is_fail */ );
+  tc->s_ho_handle = handle;
+
+  /* Track the half-open connections in case we want to forcefully
+   * clean them up @ref session_cleanup_half_open
+   */
+  wrk_handle = session_make_handle (tc->c_index, opaque);
+  app_worker_add_half_open (app_worker_get (app_wrk_index),
+                           rmt->transport_proto, handle, wrk_handle);
+
   return 0;
 }
 
@@ -1659,7 +1679,7 @@ session_manager_main_enable (vlib_main_t * vm)
       wrk->new_head = clib_llist_make_head (wrk->event_elts, evt_list);
       wrk->old_head = clib_llist_make_head (wrk->event_elts, evt_list);
       wrk->vm = vlib_mains[i];
-      wrk->last_vlib_time = vlib_time_now (vlib_mains[i]);
+      wrk->last_vlib_time = vlib_time_now (vm);
       wrk->last_vlib_us_time = wrk->last_vlib_time * CLIB_US_TIME_FREQ;
       vec_validate (wrk->session_to_enqueue, smm->last_transport_proto_type);
 
@@ -1705,6 +1725,8 @@ session_manager_main_enable (vlib_main_t * vm)
 
   /* Enable transports */
   transport_enable_disable (vm, 1);
+  session_debug_init ();
+
   return 0;
 }
 
@@ -1882,6 +1904,8 @@ session_config_fn (vlib_main_t * vm, unformat_input_t * input)
        ;
       else if (unformat (input, "enable"))
        smm->session_enable_asap = 1;
+      else if (unformat (input, "use-app-socket-api"))
+       appns_sapi_enable ();
       else
        return clib_error_return (0, "unknown input `%U'",
                                  format_unformat_error, input);