aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/session
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/session')
-rw-r--r--src/vnet/session/application.c2
-rw-r--r--src/vnet/session/segment_manager.c73
-rw-r--r--src/vnet/session/session.c18
-rw-r--r--src/vnet/session/session_node.c21
4 files changed, 61 insertions, 53 deletions
diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c
index d105119c557..2b789c5f420 100644
--- a/src/vnet/session/application.c
+++ b/src/vnet/session/application.c
@@ -111,6 +111,8 @@ application_del (application_t * app)
hash_foreach (handle, index, app->listeners_table,
({
vec_add1 (handles, handle);
+ sm = segment_manager_get (index);
+ sm->app_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
}));
/* *INDENT-ON* */
diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c
index c23e4c0237c..48d027553b1 100644
--- a/src/vnet/session/segment_manager.c
+++ b/src/vnet/session/segment_manager.c
@@ -197,27 +197,24 @@ u8
segment_manager_has_fifos (segment_manager_t * sm)
{
svm_fifo_segment_private_t *segment;
- /* Weird, but handle it */
- if (vec_len (sm->segment_indices) == 0)
- return 0;
- if (vec_len (sm->segment_indices) == 1)
- {
- segment = svm_fifo_segment_get_segment (sm->segment_indices[0]);
- if (svm_fifo_segment_num_fifos (segment) == 0)
- return 0;
- }
- if (CLIB_DEBUG)
+ int i;
+
+ for (i = 0; i < vec_len (sm->segment_indices); i++)
{
- svm_fifo_segment_private_t *segment;
- int i;
- for (i = 1; i < vec_len (sm->segment_indices); i++)
- {
- segment = svm_fifo_segment_get_segment (sm->segment_indices[i]);
- if (!svm_fifo_segment_has_fifos (segment))
- clib_warning ("segment has no fifos!");
- }
+ segment = svm_fifo_segment_get_segment (sm->segment_indices[i]);
+ if (CLIB_DEBUG && i && !svm_fifo_segment_has_fifos (segment)
+ && !(segment->h->flags & FIFO_SEGMENT_F_IS_PREALLOCATED))
+ clib_warning ("segment %d has no fifos!", sm->segment_indices[i]);
+ if (svm_fifo_segment_has_fifos (segment))
+ return 1;
}
- return 1;
+ return 0;
+}
+
+static u8
+segment_manager_app_detached (segment_manager_t * sm)
+{
+ return (sm->app_index == SEGMENT_MANAGER_INVALID_APP_INDEX);
}
static void
@@ -228,6 +225,13 @@ segment_manager_del_segment (segment_manager_t * sm, u32 segment_index)
clib_spinlock_lock (&sm->lockp);
svm_segment_index = sm->segment_indices[segment_index];
fifo_segment = svm_fifo_segment_get_segment (svm_segment_index);
+ if (!fifo_segment
+ || ((fifo_segment->h->flags & FIFO_SEGMENT_F_IS_PREALLOCATED)
+ && !segment_manager_app_detached (sm)))
+ {
+ clib_spinlock_unlock (&sm->lockp);
+ return;
+ }
svm_fifo_segment_delete (fifo_segment);
vec_del1 (sm->segment_indices, segment_index);
clib_spinlock_unlock (&sm->lockp);
@@ -288,26 +292,29 @@ segment_manager_del_sessions (segment_manager_t * sm)
*
* Since the fifos allocated in the segment keep backpointers to the sessions
* prior to removing the segment, we call session disconnect. This
- * subsequently propages into transport.
+ * subsequently propagates into transport.
*/
void
segment_manager_del (segment_manager_t * sm)
{
+ int i;
- ASSERT (vec_len (sm->segment_indices) <= 1);
- if (vec_len (sm->segment_indices))
+ ASSERT (!segment_manager_has_fifos (sm)
+ && segment_manager_app_detached (sm));
+
+ /* If we have empty preallocated segments that haven't been removed, remove
+ * them now. Apart from that, the first segment in the first segment manager
+ * is not removed when all fifos are removed. It can only be removed when
+ * the manager is explicitly deleted/detached by the app. */
+ for (i = vec_len (sm->segment_indices) - 1; i >= 0; i--)
{
- /* The first segment in the first segment manager is not removed when
- * all fifos are removed. It can only be removed when the manager is
- * explicitly deleted/detached by the app. */
if (CLIB_DEBUG)
{
- svm_fifo_segment_private_t *fifo_segment;
- fifo_segment =
- svm_fifo_segment_get_segment (sm->segment_indices[0]);
- ASSERT (!svm_fifo_segment_has_fifos (fifo_segment));
+ svm_fifo_segment_private_t *segment;
+ segment = svm_fifo_segment_get_segment (sm->segment_indices[i]);
+ ASSERT (!svm_fifo_segment_has_fifos (segment));
}
- segment_manager_del_segment (sm, 0);
+ segment_manager_del_segment (sm, i);
}
clib_spinlock_free (&sm->lockp);
if (CLIB_DEBUG)
@@ -322,8 +329,7 @@ segment_manager_init_del (segment_manager_t * sm)
segment_manager_del_sessions (sm);
else
{
- ASSERT (!sm->first_is_protected
- || sm->app_index == SEGMENT_MANAGER_INVALID_APP_INDEX);
+ ASSERT (!sm->first_is_protected || segment_manager_app_detached (sm));
segment_manager_del (sm);
}
}
@@ -478,7 +484,8 @@ segment_manager_dealloc_fifos (u32 svm_segment_index, svm_fifo_t * rx_fifo,
}
/* Remove segment manager if no sessions and detached from app */
- if (sm->app_index == SEGMENT_MANAGER_INVALID_APP_INDEX && is_first)
+ if (segment_manager_app_detached (sm)
+ && !segment_manager_has_fifos (sm))
segment_manager_del (sm);
}
}
diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c
index 792e6612dc1..dc930ce87d3 100644
--- a/src/vnet/session/session.c
+++ b/src/vnet/session/session.c
@@ -453,7 +453,7 @@ stream_session_connect_notify (transport_connection_t * tc, u8 is_fail)
st);
if (handle == HALF_OPEN_LOOKUP_INVALID_VALUE)
{
- clib_warning ("half-open was removed!");
+ TCP_DBG ("half-open was removed!");
return -1;
}
@@ -732,6 +732,7 @@ session_send_session_evt_to_thread (u64 session_handle,
u32 thread_index)
{
static u16 serial_number = 0;
+ u32 tries = 0;
session_fifo_event_t evt;
unix_shared_memory_queue_t *q;
@@ -741,21 +742,14 @@ session_send_session_evt_to_thread (u64 session_handle,
evt.event_id = serial_number++;
q = session_manager_get_vpp_event_queue (thread_index);
-
- /* Based on request block (or not) for lack of space */
- if (PREDICT_TRUE (q->cursize < q->maxsize))
+ while (unix_shared_memory_queue_add (q, (u8 *) & evt, 1))
{
- if (unix_shared_memory_queue_add (q, (u8 *) & evt,
- 0 /* do wait for mutex */ ))
+ if (tries++ == 3)
{
- clib_warning ("failed to enqueue evt");
+ TCP_DBG ("failed to enqueue evt");
+ break;
}
}
- else
- {
- clib_warning ("queue full");
- return;
- }
}
/**
diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c
index 09687687189..d015584990e 100644
--- a/src/vnet/session/session_node.c
+++ b/src/vnet/session/session_node.c
@@ -168,15 +168,19 @@ session_tx_fifo_read_and_snd_i (vlib_main_t * vm, vlib_node_runtime_t * node,
return 0;
}
+ /* Check how much we can pull. */
+ max_dequeue0 = svm_fifo_max_dequeue (s0->server_tx_fifo);
+
if (peek_data)
{
- /* Offset in rx fifo from where to peek data */
+ /* Offset in rx fifo from where to peek data */
tx_offset = transport_vft->tx_fifo_offset (tc0);
+ if (PREDICT_FALSE (tx_offset >= max_dequeue0))
+ max_dequeue0 = 0;
+ else
+ max_dequeue0 -= tx_offset;
}
- /* Check how much we can pull. If buffering, subtract the offset */
- max_dequeue0 = svm_fifo_max_dequeue (s0->server_tx_fifo) - tx_offset;
-
/* Nothing to read return */
if (max_dequeue0 == 0)
{
@@ -277,6 +281,8 @@ session_tx_fifo_read_and_snd_i (vlib_main_t * vm, vlib_node_runtime_t * node,
{
n_bytes_read = svm_fifo_peek (s0->server_tx_fifo, tx_offset,
len_to_deq0, data0);
+ if (n_bytes_read <= 0)
+ goto dequeue_fail;
/* Keep track of progress locally, transport is also supposed to
* increment it independently when pushing the header */
tx_offset += n_bytes_read;
@@ -285,11 +291,10 @@ session_tx_fifo_read_and_snd_i (vlib_main_t * vm, vlib_node_runtime_t * node,
{
n_bytes_read = svm_fifo_dequeue_nowait (s0->server_tx_fifo,
len_to_deq0, data0);
+ if (n_bytes_read <= 0)
+ goto dequeue_fail;
}
- if (n_bytes_read <= 0)
- goto dequeue_fail;
-
b0->current_length = n_bytes_read;
left_to_snd0 -= n_bytes_read;
@@ -616,7 +621,7 @@ skip_dequeue:
case FIFO_EVENT_APP_TX:
s0 = session_event_get_session (e0, my_thread_index);
- if (CLIB_DEBUG && !s0)
+ if (PREDICT_FALSE (!s0))
{
clib_warning ("It's dead, Jim!");
continue;