+ if (s->thread_index != thread_index || s->session_index != si)
+ return 0;
+
+ if (s->session_state == SESSION_STATE_TRANSPORT_DELETED
+ || s->session_state <= SESSION_STATE_LISTENING)
+ return 1;
+
+ tc = session_get_transport (s);
+ if (s->connection_index != tc->c_index
+ || s->thread_index != tc->thread_index || tc->s_index != si)
+ return 0;
+
+ return 1;
+}
+
+static void
+session_cleanup_notify (session_t * s, session_cleanup_ntf_t ntf)
+{
+ app_worker_t *app_wrk;
+
+ app_wrk = app_worker_get_if_valid (s->app_wrk_index);
+ if (!app_wrk)
+ return;
+ app_worker_cleanup_notify (app_wrk, s, ntf);
+}
+
+void
+session_free_w_fifos (session_t * s)
+{
+ session_cleanup_notify (s, SESSION_CLEANUP_SESSION);
+ segment_manager_dealloc_fifos (s->rx_fifo, s->tx_fifo);
+ session_free (s);
+}
+
+/**
+ * Cleans up session and lookup table.
+ *
+ * Transport connection must still be valid.
+ */
+static void
+session_delete (session_t * s)
+{
+ int rv;
+
+ /* Delete from the main lookup table. */
+ if ((rv = session_lookup_del_session (s)))
+ clib_warning ("session %u hash delete rv %d", s->session_index, rv);
+
+ session_free_w_fifos (s);
+}
+
+session_t *
+session_alloc_for_connection (transport_connection_t * tc)
+{
+ session_t *s;
+ u32 thread_index = tc->thread_index;
+
+ ASSERT (thread_index == vlib_get_thread_index ()
+ || transport_protocol_is_cl (tc->proto));
+
+ s = session_alloc (thread_index);
+ s->session_type = session_type_from_proto_and_ip (tc->proto, tc->is_ip4);
+ s->session_state = SESSION_STATE_CLOSED;
+
+ /* Attach transport to session and vice versa */
+ s->connection_index = tc->c_index;
+ tc->s_index = s->session_index;
+ return s;
+}
+
+/**
+ * Discards bytes from buffer chain
+ *
+ * It discards n_bytes_to_drop starting at first buffer after chain_b
+ */
+always_inline void
+session_enqueue_discard_chain_bytes (vlib_main_t * vm, vlib_buffer_t * b,
+ vlib_buffer_t ** chain_b,
+ u32 n_bytes_to_drop)
+{
+ vlib_buffer_t *next = *chain_b;
+ u32 to_drop = n_bytes_to_drop;
+ ASSERT (b->flags & VLIB_BUFFER_NEXT_PRESENT);
+ while (to_drop && (next->flags & VLIB_BUFFER_NEXT_PRESENT))
+ {
+ next = vlib_get_buffer (vm, next->next_buffer);
+ if (next->current_length > to_drop)
+ {
+ vlib_buffer_advance (next, to_drop);
+ to_drop = 0;
+ }
+ else
+ {
+ to_drop -= next->current_length;
+ next->current_length = 0;
+ }
+ }
+ *chain_b = next;
+
+ if (to_drop == 0)
+ b->total_length_not_including_first_buffer -= n_bytes_to_drop;