+ if (mp->ext_config)
+ session_mq_free_ext_config (app, mp->ext_config);
+}
+
+static void
+session_mq_handle_connects_rpc (void *arg)
+{
+ u32 max_connects = 32, n_connects = 0;
+ vlib_main_t *vm = vlib_get_main ();
+ session_evt_elt_t *he, *elt, *next;
+ session_worker_t *fwrk, *wrk;
+
+ ASSERT (vlib_get_thread_index () == 0);
+
+ /* Pending connects on linked list pertaining to first worker */
+ fwrk = session_main_get_worker (1);
+ if (!fwrk->n_pending_connects)
+ goto update_state;
+
+ vlib_worker_thread_barrier_sync (vm);
+
+ he = clib_llist_elt (fwrk->event_elts, fwrk->pending_connects);
+ elt = clib_llist_next (fwrk->event_elts, evt_list, he);
+
+ /* Avoid holding the barrier for too long */
+ while (n_connects < max_connects && elt != he)
+ {
+ next = clib_llist_next (fwrk->event_elts, evt_list, elt);
+ clib_llist_remove (fwrk->event_elts, evt_list, elt);
+ session_mq_connect_one (session_evt_ctrl_data (fwrk, elt));
+ session_evt_ctrl_data_free (fwrk, elt);
+ clib_llist_put (fwrk->event_elts, elt);
+ elt = next;
+ n_connects += 1;
+ }
+
+ /* Decrement with worker barrier */
+ fwrk->n_pending_connects -= n_connects;
+
+ vlib_worker_thread_barrier_release (vm);
+
+update_state:
+
+ /* Switch worker to poll mode if it was in interrupt mode and had work or
+ * back to interrupt if threshold of loops without a connect is passed.
+ * While in poll mode, reprogram connects rpc */
+ wrk = session_main_get_worker (0);
+ if (wrk->state != SESSION_WRK_POLLING)
+ {
+ if (n_connects)
+ {
+ session_wrk_set_state (wrk, SESSION_WRK_POLLING);
+ vlib_node_set_state (vm, session_queue_node.index,
+ VLIB_NODE_STATE_POLLING);
+ wrk->no_connect_loops = 0;
+ }
+ }
+ else
+ {
+ if (!n_connects)
+ {
+ if (++wrk->no_connect_loops > 1e5)
+ {
+ session_wrk_set_state (wrk, SESSION_WRK_INTERRUPT);
+ vlib_node_set_state (vm, session_queue_node.index,
+ VLIB_NODE_STATE_INTERRUPT);
+ }
+ }
+ else
+ wrk->no_connect_loops = 0;
+ }
+
+ if (wrk->state == SESSION_WRK_POLLING)
+ {
+ elt = session_evt_alloc_ctrl (wrk);
+ elt->evt.event_type = SESSION_CTRL_EVT_RPC;
+ elt->evt.rpc_args.fp = session_mq_handle_connects_rpc;
+ }
+}
+
+static void
+session_mq_connect_handler (session_worker_t *wrk, session_evt_elt_t *elt)
+{
+ u32 thread_index = wrk - session_main.wrk;
+ session_evt_elt_t *he;
+
+ /* No workers, so just deal with the connect now */
+ if (PREDICT_FALSE (!thread_index))
+ {
+ session_mq_connect_one (session_evt_ctrl_data (wrk, elt));
+ return;
+ }
+
+ if (PREDICT_FALSE (thread_index != 1))
+ {
+ clib_warning ("Connect on wrong thread. Dropping");
+ return;
+ }
+
+ /* Add to pending list to be handled by main thread */
+ he = clib_llist_elt (wrk->event_elts, wrk->pending_connects);
+ clib_llist_add_tail (wrk->event_elts, evt_list, elt, he);
+
+ /* Decremented with worker barrier */
+ wrk->n_pending_connects += 1;
+ if (wrk->n_pending_connects == 1)
+ {
+ vlib_node_set_interrupt_pending (vlib_get_main_by_index (0),
+ session_queue_node.index);
+ session_send_rpc_evt_to_thread (0, session_mq_handle_connects_rpc, 0);
+ }