*/
stream_session_t *
stream_session_lookup4 (ip4_address_t * lcl, ip4_address_t * rmt,
- u16 lcl_port, u16 rmt_port, u8 proto,
- u32 my_thread_index)
+ u16 lcl_port, u16 rmt_port, u8 proto)
{
session_manager_main_t *smm = &session_manager_main;
session_kv4_t kv4;
+ stream_session_t *s;
int rv;
/* Lookup session amongst established ones */
make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
rv = clib_bihash_search_inline_16_8 (&smm->v4_session_hash, &kv4);
if (rv == 0)
- return stream_session_get_tsi (kv4.value, my_thread_index);
+ return stream_session_get_from_handle (kv4.value);
/* If nothing is found, check if any listener is available */
- return stream_session_lookup_listener4 (lcl, lcl_port, proto);
+ if ((s = stream_session_lookup_listener4 (lcl, lcl_port, proto)))
+ return s;
+
+ /* Finally, try half-open connections */
+ rv = clib_bihash_search_inline_16_8 (&smm->v4_half_open_hash, &kv4);
+ if (rv == 0)
+ return stream_session_get_from_handle (kv4.value);
+ return 0;
}
stream_session_t *
* wildcarded local source (listener bound to all interfaces) */
stream_session_t *
stream_session_lookup6 (ip6_address_t * lcl, ip6_address_t * rmt,
- u16 lcl_port, u16 rmt_port, u8 proto,
- u32 my_thread_index)
+ u16 lcl_port, u16 rmt_port, u8 proto)
{
session_manager_main_t *smm = vnet_get_session_manager_main ();
session_kv6_t kv6;
+ stream_session_t *s;
int rv;
make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
rv = clib_bihash_search_inline_48_8 (&smm->v6_session_hash, &kv6);
if (rv == 0)
- return stream_session_get_tsi (kv6.value, my_thread_index);
+ return stream_session_get_from_handle (kv6.value);
/* If nothing is found, check if any listener is available */
- return stream_session_lookup_listener6 (lcl, lcl_port, proto);
+ if ((s = stream_session_lookup_listener6 (lcl, lcl_port, proto)))
+ return s;
+
+ /* Finally, try half-open connections */
+ rv = clib_bihash_search_inline_48_8 (&smm->v6_half_open_hash, &kv6);
+ if (rv == 0)
+ return stream_session_get_from_handle (kv6.value);
+ return 0;
}
stream_session_t *
}
transport_connection_t *
-stream_session_lookup_transport4 (ip4_address_t * lcl, ip4_address_t * rmt,
- u16 lcl_port, u16 rmt_port, u8 proto,
- u32 my_thread_index)
+stream_session_lookup_transport_wt4 (ip4_address_t * lcl, ip4_address_t * rmt,
+ u16 lcl_port, u16 rmt_port, u8 proto,
+ u32 my_thread_index)
{
session_manager_main_t *smm = &session_manager_main;
session_kv4_t kv4;
rv = clib_bihash_search_inline_16_8 (&smm->v4_half_open_hash, &kv4);
if (rv == 0)
return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF);
+ return 0;
+}
+transport_connection_t *
+stream_session_lookup_transport4 (ip4_address_t * lcl, ip4_address_t * rmt,
+ u16 lcl_port, u16 rmt_port, u8 proto)
+{
+ session_manager_main_t *smm = &session_manager_main;
+ session_kv4_t kv4;
+ stream_session_t *s;
+ int rv;
+
+ /* Lookup session amongst established ones */
+ make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
+ rv = clib_bihash_search_inline_16_8 (&smm->v4_session_hash, &kv4);
+ if (rv == 0)
+ {
+ s = stream_session_get_from_handle (kv4.value);
+ return tp_vfts[s->session_type].get_connection (s->connection_index,
+ s->thread_index);
+ }
+
+ /* If nothing is found, check if any listener is available */
+ s = stream_session_lookup_listener4 (lcl, lcl_port, proto);
+ if (s)
+ return tp_vfts[s->session_type].get_listener (s->connection_index);
+
+ /* Finally, try half-open connections */
+ rv = clib_bihash_search_inline_16_8 (&smm->v4_half_open_hash, &kv4);
+ if (rv == 0)
+ return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF);
return 0;
}
transport_connection_t *
-stream_session_lookup_transport6 (ip6_address_t * lcl, ip6_address_t * rmt,
- u16 lcl_port, u16 rmt_port, u8 proto,
- u32 my_thread_index)
+stream_session_lookup_transport_wt6 (ip6_address_t * lcl, ip6_address_t * rmt,
+ u16 lcl_port, u16 rmt_port, u8 proto,
+ u32 my_thread_index)
{
session_manager_main_t *smm = &session_manager_main;
stream_session_t *s;
return 0;
}
+transport_connection_t *
+stream_session_lookup_transport6 (ip6_address_t * lcl, ip6_address_t * rmt,
+ u16 lcl_port, u16 rmt_port, u8 proto)
+{
+ session_manager_main_t *smm = &session_manager_main;
+ stream_session_t *s;
+ session_kv6_t kv6;
+ int rv;
+
+ make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
+ rv = clib_bihash_search_inline_48_8 (&smm->v6_session_hash, &kv6);
+ if (rv == 0)
+ {
+ s = stream_session_get_from_handle (kv6.value);
+ return tp_vfts[s->session_type].get_connection (s->connection_index,
+ s->thread_index);
+ }
+
+ /* If nothing is found, check if any listener is available */
+ s = stream_session_lookup_listener6 (lcl, lcl_port, proto);
+ if (s)
+ return tp_vfts[s->session_type].get_listener (s->connection_index);
+
+ /* Finally, try half-open connections */
+ rv = clib_bihash_search_inline_48_8 (&smm->v6_half_open_hash, &kv6);
+ if (rv == 0)
+ return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF);
+
+ return 0;
+}
+
int
stream_session_create_i (segment_manager_t * sm, transport_connection_t * tc,
stream_session_t ** ret_s)
u32 thread_index = tc->thread_index;
int rv;
+ ASSERT (thread_index == vlib_get_thread_index ());
+
if ((rv = segment_manager_alloc_session_fifos (sm, &server_rx_fifo,
&server_tx_fifo,
&fifo_segment_index)))
return rv;
/* Create the session */
- pool_get (smm->sessions[thread_index], s);
+ pool_get_aligned (smm->sessions[thread_index], s, CLIB_CACHE_LINE_BYTES);
memset (s, 0, sizeof (*s));
/* Initialize backpointers */
stream_session_no_space (transport_connection_t * tc, u32 thread_index,
u16 data_len)
{
- stream_session_t *s = stream_session_get (tc->c_index, thread_index);
+ stream_session_t *s = stream_session_get (tc->s_index, thread_index);
if (PREDICT_FALSE (s->session_state != SESSION_STATE_READY))
return 1;
}
u32
+stream_session_tx_fifo_max_dequeue (transport_connection_t * tc)
+{
+ stream_session_t *s = stream_session_get (tc->s_index, tc->thread_index);
+ if (s->session_state != SESSION_STATE_READY)
+ return 0;
+ return svm_fifo_max_dequeue (s->server_tx_fifo);
+}
+
+int
stream_session_peek_bytes (transport_connection_t * tc, u8 * buffer,
u32 offset, u32 max_bytes)
{
svm_fifo_init_pointers (s->server_tx_fifo, tx_pointer);
}
-void
+int
stream_session_connect_notify (transport_connection_t * tc, u8 sst,
u8 is_fail)
{
stream_session_t *new_s = 0;
u64 handle;
u32 api_context = 0;
+ int error = 0;
handle = stream_session_half_open_lookup (smm, &tc->lcl_ip, &tc->rmt_ip,
tc->lcl_port, tc->rmt_port,
if (handle == HALF_OPEN_LOOKUP_INVALID_VALUE)
{
clib_warning ("This can't be good!");
- return;
+ return -1;
}
/* Get the app's index from the handle we stored when opening connection */
/* Create new session (svm segments are allocated if needed) */
if (stream_session_create_i (sm, tc, &new_s))
- return;
-
- new_s->app_index = app->index;
+ {
+ is_fail = 1;
+ error = -1;
+ }
+ else
+ new_s->app_index = app->index;
}
/* Notify client */
/* Cleanup session lookup */
stream_session_half_open_table_del (smm, sst, tc);
+
+ return error;
}
void
s->app_index = server->index;
s->listener_index = listener_index;
+ s->session_state = SESSION_STATE_ACCEPTING;
/* Shoulder-tap the server */
if (notify)
/* Based on request block (or not) for lack of space */
if (PREDICT_TRUE (q->cursize < q->maxsize))
- unix_shared_memory_queue_add (q, (u8 *) & evt,
- 0 /* do wait for mutex */ );
+ {
+ if (unix_shared_memory_queue_add (q, (u8 *) & evt,
+ 1 /* do wait for mutex */ ))
+ {
+ clib_warning ("failed to enqueue evt");
+ }
+ }
else
{
clib_warning ("queue full");
{
api_main_t *am = &api_main;
void *oldheap;
+ u32 event_queue_length = 2048;
if (smm->vpp_event_queues[thread_index] == 0)
{
/* Allocate event fifo in the /vpe-api shared-memory segment */
oldheap = svm_push_data_heap (am->vlib_rp);
+ if (smm->configured_event_queue_length)
+ event_queue_length = smm->configured_event_queue_length;
+
smm->vpp_event_queues[thread_index] =
- unix_shared_memory_queue_init (2048 /* nels $$$$ config */ ,
- sizeof (session_fifo_event_t),
- 0 /* consumer pid */ ,
- 0
- /* (do not) send signal when queue non-empty */
- );
+ unix_shared_memory_queue_init
+ (event_queue_length,
+ sizeof (session_fifo_event_t), 0 /* consumer pid */ ,
+ 0 /* (do not) send signal when queue non-empty */ );
svm_pop_heap (oldheap);
}
}
+session_type_t
+session_type_from_proto_and_ip (transport_proto_t proto, u8 is_ip4)
+{
+ if (proto == TRANSPORT_PROTO_TCP)
+ {
+ if (is_ip4)
+ return SESSION_TYPE_IP4_TCP;
+ else
+ return SESSION_TYPE_IP6_TCP;
+ }
+ else
+ {
+ if (is_ip4)
+ return SESSION_TYPE_IP4_UDP;
+ else
+ return SESSION_TYPE_IP6_UDP;
+ }
+
+ return SESSION_N_TYPES;
+}
+
static clib_error_t *
session_manager_main_enable (vlib_main_t * vm)
{
vec_validate (smm->sessions, num_threads - 1);
vec_validate (smm->session_indices_to_enqueue_by_thread, num_threads - 1);
vec_validate (smm->tx_buffers, num_threads - 1);
- vec_validate (smm->fifo_events, num_threads - 1);
- vec_validate (smm->evts_partially_read, num_threads - 1);
+ vec_validate (smm->pending_event_vector, num_threads - 1);
+ vec_validate (smm->free_event_vector, num_threads - 1);
vec_validate (smm->current_enqueue_epoch, num_threads - 1);
vec_validate (smm->vpp_event_queues, num_threads - 1);
+ for (i = 0; i < num_threads; i++)
+ {
+ vec_validate (smm->free_event_vector[i], 0);
+ _vec_len (smm->free_event_vector[i]) = 0;
+ vec_validate (smm->pending_event_vector[i], 0);
+ _vec_len (smm->pending_event_vector[i]) = 0;
+ }
+
#if SESSION_DBG
vec_validate (smm->last_event_poll_by_thread, num_threads - 1);
#endif
session_vpp_event_queue_allocate (smm, i);
/* $$$$ preallocate hack config parameter */
- for (i = 0; i < 200000; i++)
+ for (i = 0; i < smm->preallocated_sessions; i++)
{
- stream_session_t *ss;
- pool_get (smm->sessions[0], ss);
- memset (ss, 0, sizeof (*ss));
+ stream_session_t *ss __attribute__ ((unused));
+ pool_get_aligned (smm->sessions[0], ss, CLIB_CACHE_LINE_BYTES);
}
- for (i = 0; i < 200000; i++)
+ for (i = 0; i < smm->preallocated_sessions; i++)
pool_put_index (smm->sessions[0], i);
clib_bihash_init_16_8 (&smm->v4_session_hash, "v4 session table",
return 0;
}
-VLIB_INIT_FUNCTION (session_manager_main_init)
+VLIB_INIT_FUNCTION (session_manager_main_init);
+
+static clib_error_t *
+session_config_fn (vlib_main_t * vm, unformat_input_t * input)
+{
+ session_manager_main_t *smm = &session_manager_main;
+ u32 nitems;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "event-queue-length %d", &nitems))
+ {
+ if (nitems >= 2048)
+ smm->configured_event_queue_length = nitems;
+ else
+ clib_warning ("event queue length %d too small, ignored", nitems);
+ }
+ if (unformat (input, "preallocated-sessions %d",
+ &smm->preallocated_sessions))
+ ;
+ else
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ }
+ return 0;
+}
+
+VLIB_CONFIG_FUNCTION (session_config_fn, "session");
+
/*
* fd.io coding-style-patch-verification: ON
*