session/vcl: support worker ownership change for listeners
[vpp.git] / src / vnet / session / application.c
index 01dc818..044ab29 100644 (file)
@@ -724,6 +724,77 @@ 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;
+
+  if (s->session_state == SESSION_STATE_LISTENING)
+    {
+      app_worker_t *old_wrk = app_worker_get (s->app_wrk_index);
+      u64 lsh = listen_session_get_handle (s);
+      app_listener_t *app_listener;
+      application_t *app;
+
+      if (!old_wrk)
+       return -1;
+
+      hash_unset (old_wrk->listeners_table, lsh);
+      if (!(sm = app_worker_alloc_segment_manager (app_wrk)))
+       return -1;
+
+      hash_set (app_wrk->listeners_table, lsh, segment_manager_index (sm));
+      s->app_wrk_index = app_wrk->wrk_index;
+
+      app = application_get (old_wrk->app_index);
+      if (!app)
+       return -1;
+
+      app_listener = app_listener_get (app, s->listener_db_index);
+      app_listener->workers = clib_bitmap_set (app_listener->workers,
+                                              app_wrk->wrk_map_index, 1);
+      app_listener->workers = clib_bitmap_set (app_listener->workers,
+                                              old_wrk->wrk_map_index, 0);
+      return 0;
+    }
+
+  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.
  *
@@ -889,6 +960,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)
@@ -1695,14 +1774,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;
@@ -1718,7 +1797,7 @@ application_local_session_connect_notify (local_session_t * ls)
   application_t *client;
   int rv, is_fail = 0;
   u64 segment_handle;
-  uword client_key;
+  u64 client_key;
 
   client_wrk = app_worker_get (ls->client_wrk_index);
   server_wrk = app_worker_get (ls->app_wrk_index);
@@ -1759,7 +1838,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
@@ -2179,7 +2258,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 */