+static void
+vls_session_migrate (vcl_locked_session_t * vls)
+{
+ u32 wrk_index = vcl_get_worker_index ();
+ vcl_worker_t *wrk;
+ u32 src_sid, sid;
+ vcl_session_t *session;
+ uword *p;
+
+ if (!vls_mt_wrk_supported ())
+ return;
+
+ if (PREDICT_TRUE (vls->worker_index == wrk_index))
+ return;
+ if ((p = hash_get (vls->vcl_wrk_index_to_session_index, wrk_index)))
+ {
+ vls->worker_index = wrk_index;
+ vls->session_index = (u32) p[0];
+ return;
+ }
+
+ /* migrate from orignal vls */
+ if (!(p = hash_get (vls->vcl_wrk_index_to_session_index,
+ vls->owner_vcl_wrk_index)))
+ {
+ VERR ("session in owner worker(%u) is free", vls->owner_vcl_wrk_index);
+ ASSERT (0);
+ return;
+ }
+
+ src_sid = (u32) p[0];
+ wrk = vcl_worker_get_current ();
+ session = vcl_session_alloc (wrk);
+ sid = session->session_index;
+ vls_send_clone_and_share_rpc (wrk, vls, sid, vls_get_worker_index (),
+ vls->owner_vcl_wrk_index, vls->vls_index,
+ src_sid);
+ session->session_index = sid;
+ vls->worker_index = wrk_index;
+ vls->session_index = sid;
+ hash_set (vls->vcl_wrk_index_to_session_index, wrk_index, sid);
+ VDBG (1, "migrate session of worker (session): %u (%u) -> %u (%u)",
+ vls->owner_vcl_wrk_index, src_sid, wrk_index, sid);
+
+ if (PREDICT_FALSE (session->is_vep && session->vep.next_sh != ~0))
+ {
+ /* TODO: rollback? */
+ VERR ("can't migrate nonempty epoll session");
+ ASSERT (0);
+ return;
+ }
+ else if (PREDICT_FALSE (!session->is_vep &&
+ session->session_state != STATE_CLOSED))
+ {
+ /* TODO: rollback? */
+ VERR ("migrate NOT supported, session_status (%u)",
+ session->session_state);
+ ASSERT (0);
+ return;
+ }
+}
+