+static int
+ct_connect (app_worker_t * client_wrk, session_t * ll,
+ session_endpoint_cfg_t * sep)
+{
+ u32 thread_index, ho_index;
+ ct_main_t *cm = &ct_main;
+ ct_connection_t *ho;
+
+ /* Simple round-robin policy for spreading sessions over workers. We skip
+ * thread index 0, i.e., offset the index by 1, when we have workers as it
+ * is the one dedicated to main thread. Note that n_workers does not include
+ * main thread */
+ cm->n_sessions += 1;
+ thread_index = cm->n_workers ? (cm->n_sessions % cm->n_workers) + 1 : 0;
+
+ /*
+ * Alloc and init client half-open transport
+ */
+
+ ho = ct_half_open_alloc ();
+ ho_index = ho->c_c_index;
+ ho->c_rmt_port = sep->port;
+ ho->c_lcl_port = 0;
+ ho->c_is_ip4 = sep->is_ip4;
+ ho->client_opaque = sep->opaque;
+ ho->client_wrk = client_wrk->wrk_index;
+ ho->peer_index = ll->session_index;
+ ho->c_proto = TRANSPORT_PROTO_NONE;
+ ho->c_flags |= TRANSPORT_CONNECTION_F_NO_LOOKUP;
+ clib_memcpy (&ho->c_rmt_ip, &sep->ip, sizeof (sep->ip));
+ ho->flags |= CT_CONN_F_CLIENT;
+ ho->c_s_index = ~0;
+
+ /*
+ * Accept connection on thread selected above. Connected reply comes
+ * after server accepts the connection.
+ */
+
+ session_send_rpc_evt_to_thread_force (thread_index,
+ ct_accept_rpc_wrk_handler,
+ uword_to_pointer (ho_index, void *));
+
+ return ho_index;