#define HALF_OPEN_LOOKUP_INVALID_VALUE ((u64)~0)
#define INVALID_INDEX ((u32)~0)
-#define SESSION_PROXY_LISTENER_INDEX ((u32)~0 - 1)
+#define SESSION_PROXY_LISTENER_INDEX ((u8)~0 - 1)
#define SESSION_LOCAL_HANDLE_PREFIX 0x7FFFFFFF
/* TODO decide how much since we have pre-data as well */
typedef enum
{
FIFO_EVENT_APP_RX,
+ SESSION_IO_EVT_CT_RX,
FIFO_EVENT_APP_TX,
- FIFO_EVENT_TIMEOUT,
+ SESSION_IO_EVT_CT_TX,
FIFO_EVENT_DISCONNECT,
FIFO_EVENT_BUILTIN_RX,
+ FIFO_EVENT_BUILTIN_TX,
FIFO_EVENT_RPC,
-} fifo_event_type_t;
+ SESSION_CTRL_EVT_BOUND,
+ SESSION_CTRL_EVT_ACCEPTED,
+ SESSION_CTRL_EVT_ACCEPTED_REPLY,
+ SESSION_CTRL_EVT_CONNECTED,
+ SESSION_CTRL_EVT_CONNECTED_REPLY,
+ SESSION_CTRL_EVT_DISCONNECTED,
+ SESSION_CTRL_EVT_DISCONNECTED_REPLY,
+ SESSION_CTRL_EVT_RESET,
+ SESSION_CTRL_EVT_RESET_REPLY
+} session_evt_type_t;
static inline const char *
-fifo_event_type_str (fifo_event_type_t et)
+fifo_event_type_str (session_evt_type_t et)
{
switch (et)
{
return "FIFO_EVENT_APP_RX";
case FIFO_EVENT_APP_TX:
return "FIFO_EVENT_APP_TX";
- case FIFO_EVENT_TIMEOUT:
- return "FIFO_EVENT_TIMEOUT";
case FIFO_EVENT_DISCONNECT:
return "FIFO_EVENT_DISCONNECT";
case FIFO_EVENT_BUILTIN_RX:
}
}
+typedef enum
+{
+ SESSION_MQ_IO_EVT_RING,
+ SESSION_MQ_CTRL_EVT_RING,
+ SESSION_MQ_N_RINGS
+} session_mq_rings_e;
+
#define foreach_session_input_error \
_(NO_SESSION, "No session drops") \
_(NO_LISTENER, "No listener for dst port drops") \
{
void *fp;
void *arg;
-} rpc_args_t;
+} session_rpc_args_t;
typedef u64 session_handle_t;
/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct {
+typedef struct
+{
+ u8 event_type;
+ u8 postponed;
union
+ {
+ svm_fifo_t *fifo;
+ session_handle_t session_handle;
+ session_rpc_args_t rpc_args;
+ struct
{
- svm_fifo_t * fifo;
- session_handle_t session_handle;
- rpc_args_t rpc_args;
+ u8 data[0];
};
- u8 event_type;
- u8 postponed;
-}) session_fifo_event_t;
+ };
+} __clib_packed session_event_t;
/* *INDENT-ON* */
+#define SESSION_MSG_NULL { }
+
typedef struct session_dgram_pre_hdr_
{
u32 data_length;
typedef int
(session_fifo_rx_fn) (vlib_main_t * vm, vlib_node_runtime_t * node,
- session_fifo_event_t * e0, stream_session_t * s0,
+ session_event_t * e0, stream_session_t * s0,
int *n_tx_pkts);
extern session_fifo_rx_fn session_tx_fifo_peek_and_snd;
extern session_fifo_rx_fn session_tx_fifo_dequeue_and_snd;
extern session_fifo_rx_fn session_tx_fifo_dequeue_internal;
-u8 session_node_lookup_fifo_event (svm_fifo_t * f, session_fifo_event_t * e);
+u8 session_node_lookup_fifo_event (svm_fifo_t * f, session_event_t * e);
-struct _session_manager_main
+typedef struct session_manager_worker_
{
- /** Per worker thread session pools */
- stream_session_t **sessions;
+ CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
+ /** Worker session pool */
+ stream_session_t *sessions;
+
+ /** vpp event message queue for worker */
+ svm_msg_q_t *vpp_event_queue;
+
+ /** Our approximation of a "complete" dispatch loop period */
+ f64 dispatch_period;
- /** Per worker-thread session pool peekers rw locks */
- clib_rwlock_t *peekers_rw_locks;
+ /** vlib_time_now last time around the track */
+ f64 last_vlib_time;
- /** Per-proto, per-worker enqueue epoch counters */
- u32 *current_enqueue_epoch[TRANSPORT_N_PROTO];
+ /** Per-proto enqueue epoch counters */
+ u64 current_enqueue_epoch[TRANSPORT_N_PROTO];
- /** Per-proto, per-worker thread vector of sessions to enqueue */
- u32 **session_to_enqueue[TRANSPORT_N_PROTO];
+ /** Per-proto vector of sessions to enqueue */
+ u32 *session_to_enqueue[TRANSPORT_N_PROTO];
- /** per-worker tx buffer free lists */
- u32 **tx_buffers;
+ /** Context for session tx */
+ session_tx_context_t ctx;
- /** Per worker-thread vector of partially read events */
- session_fifo_event_t **free_event_vector;
+ /** Vector of tx buffer free lists */
+ u32 *tx_buffers;
- /** per-worker active event vectors */
- session_fifo_event_t **pending_event_vector;
+ /** Vector of partially read events */
+ session_event_t *free_event_vector;
- /** per-worker postponed disconnects */
- session_fifo_event_t **pending_disconnects;
+ /** Vector of active event vectors */
+ session_event_t *pending_event_vector;
- /** per-worker session context */
- session_tx_context_t *ctx;
+ /** Vector of postponed disconnects */
+ session_event_t *pending_disconnects;
- /** vpp fifo event queue */
- svm_queue_t **vpp_event_queues;
+ /** Vector of postponed events */
+ session_event_t *postponed_event_vector;
+
+ /** Peekers rw lock */
+ clib_rwlock_t peekers_rw_locks;
+
+ u32 last_tx_packets;
+
+} session_manager_worker_t;
+
+struct _session_manager_main
+{
+ /** Worker contexts */
+ session_manager_worker_t *wrk;
/** Event queues memfd segment initialized only if so configured */
ssvm_private_t evt_qs_segment;
* Trade memory for speed, for now */
u32 *session_type_to_next;
+ /*
+ * Config parameters
+ */
+
/** Session manager is enabled */
u8 is_enabled;
/** vpp fifo event queue configured length */
u32 configured_event_queue_length;
- /*
- * Config parameters
- */
-
/** Session ssvm segment configs*/
uword session_baseva;
uword session_va_space_size;
return &session_manager_main;
}
+always_inline session_manager_worker_t *
+session_manager_get_worker (u32 thread_index)
+{
+ return &session_manager_main.wrk[thread_index];
+}
+
always_inline u8
stream_session_is_valid (u32 si, u8 thread_index)
{
stream_session_t *s;
- s = pool_elt_at_index (session_manager_main.sessions[thread_index], si);
+ s = pool_elt_at_index (session_manager_main.wrk[thread_index].sessions, si);
if (s->thread_index != thread_index || s->session_index != si
/* || s->server_rx_fifo->master_session_index != si
|| s->server_tx_fifo->master_session_index != si
stream_session_t *session_alloc (u32 thread_index);
int session_alloc_fifos (segment_manager_t * sm, stream_session_t * s);
void session_free (stream_session_t * s);
+void session_free_w_fifos (stream_session_t * s);
always_inline stream_session_t *
session_get (u32 si, u32 thread_index)
{
ASSERT (stream_session_is_valid (si, thread_index));
- return pool_elt_at_index (session_manager_main.sessions[thread_index], si);
+ return pool_elt_at_index (session_manager_main.wrk[thread_index].sessions,
+ si);
}
always_inline stream_session_t *
session_get_if_valid (u64 si, u32 thread_index)
{
- if (thread_index >= vec_len (session_manager_main.sessions))
+ if (thread_index >= vec_len (session_manager_main.wrk))
return 0;
- if (pool_is_free_index (session_manager_main.sessions[thread_index], si))
+ if (pool_is_free_index (session_manager_main.wrk[thread_index].sessions,
+ si))
return 0;
ASSERT (stream_session_is_valid (si, thread_index));
- return pool_elt_at_index (session_manager_main.sessions[thread_index], si);
+ return pool_elt_at_index (session_manager_main.wrk[thread_index].sessions,
+ si);
}
always_inline session_handle_t
session_manager_main_t *smm = &session_manager_main;
u32 session_index, thread_index;
session_parse_handle (handle, &session_index, &thread_index);
- return pool_elt_at_index (smm->sessions[thread_index], session_index);
+ return pool_elt_at_index (smm->wrk[thread_index].sessions, session_index);
}
always_inline stream_session_t *
return (proto << 1 | is_ip4);
}
+always_inline u64
+session_segment_handle (stream_session_t * s)
+{
+ svm_fifo_t *f = s->server_rx_fifo;
+ return segment_manager_make_segment_handle (f->segment_manager,
+ f->segment_index);
+}
+
always_inline u8
session_has_transport (stream_session_t * s)
{
always_inline void
session_pool_add_peeker (u32 thread_index)
{
- session_manager_main_t *smm = &session_manager_main;
+ session_manager_worker_t *wrk = &session_manager_main.wrk[thread_index];
if (thread_index == vlib_get_thread_index ())
return;
- clib_rwlock_reader_lock (&smm->peekers_rw_locks[thread_index]);
+ clib_rwlock_reader_lock (&wrk->peekers_rw_locks);
}
always_inline void
session_pool_remove_peeker (u32 thread_index)
{
- session_manager_main_t *smm = &session_manager_main;
+ session_manager_worker_t *wrk = &session_manager_main.wrk[thread_index];
if (thread_index == vlib_get_thread_index ())
return;
- clib_rwlock_reader_unlock (&smm->peekers_rw_locks[thread_index]);
+ clib_rwlock_reader_unlock (&wrk->peekers_rw_locks);
}
/**
always_inline stream_session_t *
session_get_from_handle_safe (u64 handle)
{
- session_manager_main_t *smm = &session_manager_main;
u32 thread_index = session_thread_from_handle (handle);
+ session_manager_worker_t *wrk = &session_manager_main.wrk[thread_index];
+
if (thread_index == vlib_get_thread_index ())
{
- return pool_elt_at_index (smm->sessions[thread_index],
+ return pool_elt_at_index (wrk->sessions,
session_index_from_handle (handle));
}
else
{
session_pool_add_peeker (thread_index);
/* Don't use pool_elt_at index. See @ref session_pool_add_peeker */
- return smm->sessions[thread_index] + session_index_from_handle (handle);
+ return wrk->sessions + session_index_from_handle (handle);
}
}
return s->server_tx_fifo->nitems;
}
+always_inline u8
+transport_rx_fifo_has_ooo_data (transport_connection_t * tc)
+{
+ stream_session_t *s = session_get (tc->c_index, tc->thread_index);
+ return svm_fifo_has_ooo_data (s->server_rx_fifo);
+}
+
+always_inline f64
+transport_dispatch_period (u32 thread_index)
+{
+ return session_manager_main.wrk[thread_index].dispatch_period;
+}
+
+always_inline f64
+transport_time_now (u32 thread_index)
+{
+ return session_manager_main.wrk[thread_index].last_vlib_time;
+}
+
always_inline u32
session_get_index (stream_session_t * s)
{
- return (s - session_manager_main.sessions[s->thread_index]);
+ return (s - session_manager_main.wrk[s->thread_index].sessions);
}
always_inline stream_session_t *
*/
session_pool_add_peeker (thread_index);
new_s = session_alloc (current_thread_index);
- old_s = session_manager_main.sessions[thread_index] + session_index;
- clib_memcpy (new_s, old_s, sizeof (*new_s));
+ old_s = session_manager_main.wrk[thread_index].sessions + session_index;
+ clib_memcpy_fast (new_s, old_s, sizeof (*new_s));
session_pool_remove_peeker (thread_index);
new_s->thread_index = current_thread_index;
new_s->session_index = session_get_index (new_s);
int stream_session_accept (transport_connection_t * tc, u32 listener_index,
u8 notify);
int session_open (u32 app_index, session_endpoint_t * tep, u32 opaque);
-int stream_session_listen (stream_session_t * s, session_endpoint_t * tep);
-int stream_session_stop_listen (stream_session_t * s);
+int session_listen (stream_session_t * s, session_endpoint_cfg_t * sep);
+int session_stop_listen (stream_session_t * s);
void stream_session_disconnect (stream_session_t * s);
void stream_session_disconnect_transport (stream_session_t * s);
void stream_session_cleanup (stream_session_t * s);
-void session_send_session_evt_to_thread (u64 session_handle,
- fifo_event_type_t evt_type,
- u32 thread_index);
+int session_send_io_evt_to_thread (svm_fifo_t * f,
+ session_evt_type_t evt_type);
+int session_send_io_evt_to_thread_custom (void *data, u32 thread_index,
+ session_evt_type_t evt_type);
+void session_send_rpc_evt_to_thread (u32 thread_index, void *fp,
+ void *rpc_args);
+
ssvm_private_t *session_manager_get_evt_q_segment (void);
u8 *format_stream_session (u8 * s, va_list * args);
const transport_proto_vft_t * vft, u8 is_ip4,
u32 output_node);
+always_inline void
+transport_add_tx_event (transport_connection_t * tc)
+{
+ stream_session_t *s = session_get (tc->s_index, tc->thread_index);
+ if (svm_fifo_has_event (s->server_tx_fifo))
+ return;
+ session_send_io_evt_to_thread (s->server_tx_fifo, FIFO_EVENT_APP_TX);
+}
+
clib_error_t *vnet_session_enable_disable (vlib_main_t * vm, u8 is_en);
-always_inline svm_queue_t *
+always_inline svm_msg_q_t *
session_manager_get_vpp_event_queue (u32 thread_index)
{
- return session_manager_main.vpp_event_queues[thread_index];
+ return session_manager_main.wrk[thread_index].vpp_event_queue;
}
int session_manager_flush_enqueue_events (u8 proto, u32 thread_index);