+static void
+ct_handle_cleanups (void *args)
+{
+ uword thread_index = pointer_to_uword (args);
+ const u32 max_cleanups = 100;
+ ct_cleanup_req_t *req;
+ ct_connection_t *ct;
+ u32 n_to_handle = 0;
+ ct_worker_t *wrk;
+ session_t *s;
+
+ wrk = ct_worker_get (thread_index);
+ wrk->have_cleanups = 0;
+ n_to_handle = clib_fifo_elts (wrk->pending_cleanups);
+ n_to_handle = clib_min (n_to_handle, max_cleanups);
+
+ while (n_to_handle)
+ {
+ clib_fifo_sub2 (wrk->pending_cleanups, req);
+ ct = ct_connection_get (req->ct_index, thread_index);
+ s = session_get (ct->c_s_index, ct->c_thread_index);
+ if (!svm_fifo_has_event (s->tx_fifo))
+ ct_session_postponed_cleanup (ct);
+ else
+ clib_fifo_add1 (wrk->pending_cleanups, *req);
+ n_to_handle -= 1;
+ }
+
+ if (clib_fifo_elts (wrk->pending_cleanups))
+ {
+ wrk->have_cleanups = 1;
+ session_send_rpc_evt_to_thread_force (
+ thread_index, ct_handle_cleanups,
+ uword_to_pointer (thread_index, void *));
+ }
+}
+
+static void
+ct_program_cleanup (ct_connection_t *ct)
+{
+ ct_cleanup_req_t *req;
+ uword thread_index;
+ ct_worker_t *wrk;
+
+ thread_index = ct->c_thread_index;
+ wrk = ct_worker_get (ct->c_thread_index);
+
+ clib_fifo_add2 (wrk->pending_cleanups, req);
+ req->ct_index = ct->c_c_index;
+
+ if (wrk->have_cleanups)
+ return;
+
+ wrk->have_cleanups = 1;
+ session_send_rpc_evt_to_thread_force (
+ thread_index, ct_handle_cleanups, uword_to_pointer (thread_index, void *));
+}
+
+static void
+ct_session_close (u32 ct_index, u32 thread_index)
+{
+ ct_connection_t *ct, *peer_ct;
+ session_t *s;
+
+ ct = ct_connection_get (ct_index, thread_index);
+ s = session_get (ct->c_s_index, ct->c_thread_index);
+ peer_ct = ct_connection_get (ct->peer_index, thread_index);
+ if (peer_ct)
+ {
+ peer_ct->peer_index = ~0;
+ /* Make sure session was allocated */
+ if (peer_ct->flags & CT_CONN_F_HALF_OPEN)
+ {
+ ct_session_connect_notify (s, SESSION_E_REFUSED);
+ ct->peer_index = ~0;
+ }
+ else if (peer_ct->c_s_index == ~0)
+ {
+ /* should not happen */
+ clib_warning ("ct peer without session");
+ ct_connection_free (peer_ct);
+ }
+ }
+
+ /* Do not send closed notify to make sure pending tx events are
+ * still delivered and program cleanup */
+ ct_program_cleanup (ct);
+}
+