summaryrefslogtreecommitdiffstats
path: root/src/vnet/session
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2018-06-06 17:55:02 -0700
committerDave Barach <openvpp@barachs.net>2018-06-11 17:32:40 +0000
commit25579b4acd449e1bae30d2a20a44b77741c8e1fd (patch)
treeb82e8bb17fc8b2f257cb57dfd9e6ca628a5916a3 /src/vnet/session
parent40903ac34f89d9e2ad775e98b7bcec5b7feb0207 (diff)
tcp: cleanup connection/session fixes
- Cleanup session state after last ack and avoid using a cleanup timer. - Change session cleanup to free the session as opposed to waiting for delete notify. - When in close-wait, postpone sending the fin on close until all outstanding data has been sent. - Don't flush rx fifo unless in closed state Change-Id: Ic2a4f0d5568b65c83f4b55b6c469a7b24b947f39 Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/vnet/session')
-rw-r--r--src/vnet/session/session.c46
-rw-r--r--src/vnet/session/session.h2
-rw-r--r--src/vnet/session/session_node.c9
3 files changed, 34 insertions, 23 deletions
diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c
index cfba31ec406..6559e318ca8 100644
--- a/src/vnet/session/session.c
+++ b/src/vnet/session/session.c
@@ -414,7 +414,7 @@ stream_session_no_space (transport_connection_t * tc, u32 thread_index,
}
u32
-stream_session_tx_fifo_max_dequeue (transport_connection_t * tc)
+session_tx_fifo_max_dequeue (transport_connection_t * tc)
{
stream_session_t *s = session_get (tc->s_index, tc->thread_index);
if (!s->server_tx_fifo)
@@ -452,12 +452,10 @@ session_enqueue_notify (stream_session_t * s, u8 block)
session_fifo_event_t evt;
svm_queue_t *q;
- if (PREDICT_FALSE (s->session_state >= SESSION_STATE_CLOSING))
+ if (PREDICT_FALSE (s->session_state == SESSION_STATE_CLOSED))
{
/* Session is closed so app will never clean up. Flush rx fifo */
- u32 to_dequeue = svm_fifo_max_dequeue (s->server_rx_fifo);
- if (to_dequeue)
- svm_fifo_dequeue_drop (s->server_rx_fifo, to_dequeue);
+ svm_fifo_dequeue_drop_all (s->server_rx_fifo);
return 0;
}
@@ -727,10 +725,13 @@ stream_session_disconnect_notify (transport_connection_t * tc)
s = session_get (tc->s_index, tc->thread_index);
server = application_get (s->app_index);
server->cb_fns.session_disconnect_callback (s);
+ s->session_state = SESSION_STATE_CLOSING;
}
/**
* Cleans up session and lookup table.
+ *
+ * Transport connection must still be valid.
*/
void
stream_session_delete (stream_session_t * s)
@@ -1065,13 +1066,23 @@ stream_session_disconnect (stream_session_t * s)
session_manager_main_t *smm = &session_manager_main;
session_fifo_event_t *evt;
- if (!s || s->session_state >= SESSION_STATE_CLOSING)
+ if (!s)
return;
+
+ if (s->session_state >= SESSION_STATE_CLOSING)
+ {
+ /* Session already closed. Clear the tx fifo */
+ if (s->session_state == SESSION_STATE_CLOSED)
+ svm_fifo_dequeue_drop_all (s->server_tx_fifo);
+ return;
+ }
+
s->session_state = SESSION_STATE_CLOSING;
/* If we are in the handler thread, or being called with the worker barrier
- * held (api/cli), just append a new event pending disconnects vector. */
- if (thread_index > 0 || !vlib_get_current_process (vlib_get_main ()))
+ * held (api/cli), just append a new event to pending disconnects vector. */
+ if ((thread_index == 0 && !vlib_get_current_process (vlib_get_main ()))
+ || thread_index == s->thread_index)
{
ASSERT (s->thread_index == thread_index || thread_index == 0);
vec_add2 (smm->pending_disconnects[s->thread_index], evt, 1);
@@ -1103,23 +1114,24 @@ stream_session_disconnect_transport (stream_session_t * s)
/**
* Cleanup transport and session state.
*
- * Notify transport of the cleanup, wait for a delete notify to actually
- * remove the session state.
+ * Notify transport of the cleanup and free the session. This should
+ * be called only if transport reported some error and is already
+ * closed.
*/
void
stream_session_cleanup (stream_session_t * s)
{
- int rv;
-
s->session_state = SESSION_STATE_CLOSED;
- /* Delete from the main lookup table to avoid more enqueues */
- rv = session_lookup_del_session (s);
- if (rv)
- clib_warning ("hash delete error, rv %d", rv);
-
+ /* Delete from main lookup table before we axe the the transport */
+ session_lookup_del_session (s);
tp_vfts[session_get_transport_proto (s)].cleanup (s->connection_index,
s->thread_index);
+ /* Since we called cleanup, no delete notification will come. So, make
+ * sure the session is properly freed. */
+ segment_manager_dealloc_fifos (s->svm_segment_index, s->server_rx_fifo,
+ s->server_tx_fifo);
+ session_free (s);
}
transport_service_type_t
diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h
index 6908a568a0f..b57053c7f59 100644
--- a/src/vnet/session/session.h
+++ b/src/vnet/session/session.h
@@ -499,7 +499,7 @@ session_clone_safe (u32 session_index, u32 thread_index)
transport_connection_t *session_get_transport (stream_session_t * s);
-u32 stream_session_tx_fifo_max_dequeue (transport_connection_t * tc);
+u32 session_tx_fifo_max_dequeue (transport_connection_t * tc);
int
session_enqueue_stream_connection (transport_connection_t * tc,
diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c
index d6fcd911b08..2eea30be439 100644
--- a/src/vnet/session/session_node.c
+++ b/src/vnet/session/session_node.c
@@ -799,7 +799,8 @@ skip_dequeue:
}
break;
case FIFO_EVENT_DISCONNECT:
- /* Make sure stream disconnects run after the pending list is drained */
+ /* Make sure stream disconnects run after the pending list is
+ * drained */
s0 = session_get_from_handle (e0->session_handle);
if (!e0->postponed)
{
@@ -807,11 +808,9 @@ skip_dequeue:
vec_add1 (smm->pending_disconnects[thread_index], *e0);
continue;
}
- /* If tx queue is still not empty, wait a bit */
- if (svm_fifo_max_dequeue (s0->server_tx_fifo)
- && e0->postponed < 200)
+ /* If tx queue is still not empty, wait */
+ if (svm_fifo_max_dequeue (s0->server_tx_fifo))
{
- e0->postponed += 1;
vec_add1 (smm->pending_disconnects[thread_index], *e0);
continue;
}