vcl/session: add api for changing session app worker
[vpp.git] / src / vnet / session / application.c
index 9b77af9..85b5f93 100644 (file)
@@ -94,6 +94,8 @@ app_worker_map_free (application_t * app, app_worker_map_t * map)
 static app_worker_map_t *
 app_worker_map_get (application_t * app, u32 map_index)
 {
+  if (pool_is_free_index (app->worker_maps, map_index))
+    return 0;
   return pool_elt_at_index (app->worker_maps, map_index);
 }
 
@@ -722,6 +724,48 @@ app_worker_stop_listen (app_worker_t * app_wrk, session_handle_t handle)
   return 0;
 }
 
+int
+app_worker_own_session (app_worker_t * app_wrk, stream_session_t * s)
+{
+  segment_manager_t *sm;
+  svm_fifo_t *rxf, *txf;
+
+  s->app_wrk_index = app_wrk->wrk_index;
+
+  rxf = s->server_rx_fifo;
+  txf = s->server_tx_fifo;
+
+  if (!rxf || !txf)
+    return 0;
+
+  s->server_rx_fifo = 0;
+  s->server_tx_fifo = 0;
+
+  sm = app_worker_get_or_alloc_connect_segment_manager (app_wrk);
+  if (session_alloc_fifos (sm, s))
+    return -1;
+
+  if (!svm_fifo_is_empty (rxf))
+    {
+      clib_memcpy_fast (s->server_rx_fifo->data, rxf->data, rxf->nitems);
+      s->server_rx_fifo->head = rxf->head;
+      s->server_rx_fifo->tail = rxf->tail;
+      s->server_rx_fifo->cursize = rxf->cursize;
+    }
+
+  if (!svm_fifo_is_empty (txf))
+    {
+      clib_memcpy_fast (s->server_tx_fifo->data, txf->data, txf->nitems);
+      s->server_tx_fifo->head = txf->head;
+      s->server_tx_fifo->tail = txf->tail;
+      s->server_tx_fifo->cursize = txf->cursize;
+    }
+
+  segment_manager_dealloc_fifos (rxf->segment_index, rxf, txf);
+
+  return 0;
+}
+
 /**
  * Start listening local transport endpoint for requested transport.
  *
@@ -887,6 +931,14 @@ app_worker_get_connect_segment_manager (app_worker_t * app)
   return segment_manager_get (app->connects_seg_manager);
 }
 
+segment_manager_t *
+app_worker_get_or_alloc_connect_segment_manager (app_worker_t * app_wrk)
+{
+  if (app_wrk->connects_seg_manager == (u32) ~ 0)
+    app_worker_alloc_connects_segment_manager (app_wrk);
+  return segment_manager_get (app_wrk->connects_seg_manager);
+}
+
 segment_manager_t *
 app_worker_get_listen_segment_manager (app_worker_t * app,
                                       stream_session_t * listener)
@@ -924,6 +976,7 @@ vnet_app_worker_add_del (vnet_app_worker_add_del_args_t * a)
       sm = segment_manager_get (app_wrk->first_segment_manager);
       fs = segment_manager_get_segment_w_lock (sm, 0);
       a->segment = &fs->ssvm;
+      a->segment_handle = segment_manager_segment_handle (sm, fs);
       segment_manager_segment_reader_unlock (sm);
       a->evt_q = app_wrk->event_queue;
       a->wrk_map_index = app_wrk->wrk_map_index;
@@ -1007,11 +1060,12 @@ application_use_mq_for_ctrl (application_t * app)
  * Send an API message to the external app, to map new segment
  */
 int
-app_worker_add_segment_notify (u32 app_wrk_index, ssvm_private_t * fs)
+app_worker_add_segment_notify (u32 app_wrk_index, u64 segment_handle)
 {
   app_worker_t *app_wrk = app_worker_get (app_wrk_index);
   application_t *app = application_get (app_wrk->app_index);
-  return app->cb_fns.add_segment_callback (app_wrk->api_client_index, fs);
+  return app->cb_fns.add_segment_callback (app_wrk->api_client_index,
+                                          segment_handle);
 }
 
 u32
@@ -1589,14 +1643,15 @@ application_local_session_connect (app_worker_t * client_wrk,
                                   local_session_t * ll, u32 opaque)
 {
   u32 seg_size, evt_q_sz, evt_q_elts, margin = 16 << 10;
+  u32 round_rx_fifo_sz, round_tx_fifo_sz, sm_index;
   segment_manager_properties_t *props, *cprops;
-  u32 round_rx_fifo_sz, round_tx_fifo_sz;
   int rv, has_transport, seg_index;
   svm_fifo_segment_private_t *seg;
   application_t *server, *client;
   segment_manager_t *sm;
   local_session_t *ls;
   svm_msg_q_t *sq, *cq;
+  u64 segment_handle;
 
   ls = application_local_session_alloc (server_wrk);
   server = application_get (server_wrk->app_index);
@@ -1651,8 +1706,13 @@ application_local_session_connect (app_worker_t * client_wrk,
       segment_manager_segment_reader_unlock (sm);
       goto failed;
     }
+  sm_index = segment_manager_index (sm);
   ls->server_rx_fifo->ct_session_index = ls->session_index;
   ls->server_tx_fifo->ct_session_index = ls->session_index;
+  ls->server_rx_fifo->segment_manager = sm_index;
+  ls->server_tx_fifo->segment_manager = sm_index;
+  ls->server_rx_fifo->segment_index = seg_index;
+  ls->server_tx_fifo->segment_index = seg_index;
   ls->svm_segment_index = seg_index;
   ls->listener_index = ll->session_index;
   ls->client_wrk_index = client_wrk->wrk_index;
@@ -1660,8 +1720,9 @@ application_local_session_connect (app_worker_t * client_wrk,
   ls->listener_session_type = ll->session_type;
   ls->session_state = SESSION_STATE_READY;
 
+  segment_handle = segment_manager_segment_handle (sm, seg);
   if ((rv = server->cb_fns.add_segment_callback (server_wrk->api_client_index,
-                                                &seg->ssvm)))
+                                                segment_handle)))
     {
       clib_warning ("failed to notify server of new segment");
       segment_manager_segment_reader_unlock (sm);
@@ -1684,14 +1745,14 @@ failed:
   return rv;
 }
 
-static uword
+static u64
 application_client_local_connect_key (local_session_t * ls)
 {
-  return ((uword) ls->app_wrk_index << 32 | (uword) ls->session_index);
+  return (((u64) ls->app_wrk_index) << 32 | (u64) ls->session_index);
 }
 
 static void
-application_client_local_connect_key_parse (uword key, u32 * app_wrk_index,
+application_client_local_connect_key_parse (u64 key, u32 * app_wrk_index,
                                            u32 * session_index)
 {
   *app_wrk_index = key >> 32;
@@ -1706,7 +1767,8 @@ application_local_session_connect_notify (local_session_t * ls)
   segment_manager_t *sm;
   application_t *client;
   int rv, is_fail = 0;
-  uword client_key;
+  u64 segment_handle;
+  u64 client_key;
 
   client_wrk = app_worker_get (ls->client_wrk_index);
   server_wrk = app_worker_get (ls->app_wrk_index);
@@ -1714,8 +1776,9 @@ application_local_session_connect_notify (local_session_t * ls)
 
   sm = application_get_local_segment_manager_w_session (server_wrk, ls);
   seg = segment_manager_get_segment_w_lock (sm, ls->svm_segment_index);
+  segment_handle = segment_manager_segment_handle (sm, seg);
   if ((rv = client->cb_fns.add_segment_callback (client_wrk->api_client_index,
-                                                &seg->ssvm)))
+                                                segment_handle)))
     {
       clib_warning ("failed to notify client %u of new segment",
                    ls->client_wrk_index);
@@ -1746,7 +1809,7 @@ application_local_session_cleanup (app_worker_t * client_wrk,
   svm_fifo_segment_private_t *seg;
   stream_session_t *listener;
   segment_manager_t *sm;
-  uword client_key;
+  u64 client_key;
   u8 has_transport;
 
   /* Retrieve listener transport type as it is the one that decides where
@@ -1770,13 +1833,14 @@ application_local_session_cleanup (app_worker_t * client_wrk,
   if (!has_transport)
     {
       application_t *server = application_get (server_wrk->app_index);
+      u64 segment_handle = segment_manager_segment_handle (sm, seg);
       server->cb_fns.del_segment_callback (server_wrk->api_client_index,
-                                          &seg->ssvm);
+                                          segment_handle);
       if (client_wrk)
        {
          application_t *client = application_get (client_wrk->app_index);
          client->cb_fns.del_segment_callback (client_wrk->api_client_index,
-                                              &seg->ssvm);
+                                              segment_handle);
        }
       segment_manager_del_segment (sm, seg);
     }
@@ -2165,7 +2229,7 @@ app_worker_format_local_connects (app_worker_t * app, int verbose)
   u32 app_wrk_index, session_index;
   app_worker_t *server_wrk;
   local_session_t *ls;
-  uword client_key;
+  u64 client_key;
   u64 value;
 
   /* Header */
@@ -2379,7 +2443,7 @@ show_app_command_fn (vlib_main_t * vm, unformat_input_t * input,
 
   if (app_index != ~0)
     {
-      app = application_get (app_index);
+      app = application_get_if_valid (app_index);
       if (!app)
        return clib_error_return (0, "No app with index %u", app_index);