+ return session_send_evt_to_thread (f, 0, f->master_thread_index, evt_type);
+}
+
+int
+session_send_io_evt_to_thread_custom (void *data, u32 thread_index,
+ session_evt_type_t evt_type)
+{
+ return session_send_evt_to_thread (data, 0, thread_index, evt_type);
+}
+
+int
+session_send_ctrl_evt_to_thread (stream_session_t * s,
+ session_evt_type_t evt_type)
+{
+ /* only event supported for now is disconnect */
+ ASSERT (evt_type == FIFO_EVENT_DISCONNECT);
+ return session_send_evt_to_thread (s, 0, s->thread_index,
+ FIFO_EVENT_DISCONNECT);
+}
+
+void
+session_send_rpc_evt_to_thread (u32 thread_index, void *fp, void *rpc_args)
+{
+ if (thread_index != vlib_get_thread_index ())
+ session_send_evt_to_thread (fp, rpc_args, thread_index, FIFO_EVENT_RPC);
+ else
+ {
+ void (*fnp) (void *) = fp;
+ fnp (rpc_args);
+ }
+}
+
+static void
+session_program_transport_close (stream_session_t * s)
+{
+ u32 thread_index = vlib_get_thread_index ();
+ session_manager_worker_t *wrk;
+ session_event_t *evt;
+
+ /* If we are in the handler thread, or being called with the worker barrier
+ * held, just append a new event to pending disconnects vector. */
+ if (vlib_thread_is_main_w_barrier () || thread_index == s->thread_index)
+ {
+ wrk = session_manager_get_worker (s->thread_index);
+ vec_add2 (wrk->pending_disconnects, evt, 1);
+ clib_memset (evt, 0, sizeof (*evt));
+ evt->session_handle = session_handle (s);
+ evt->event_type = FIFO_EVENT_DISCONNECT;
+ }
+ else
+ session_send_ctrl_evt_to_thread (s, FIFO_EVENT_DISCONNECT);
+}
+
+stream_session_t *
+session_alloc (u32 thread_index)
+{
+ session_manager_worker_t *wrk = &session_manager_main.wrk[thread_index];