aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/session/session.c
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2019-07-12 15:01:53 -0700
committerJohn Lo <loj@cisco.com>2019-07-15 01:39:15 +0000
commit692b9498ee5511a17bfbc3a2c6e87339aa3b8df8 (patch)
treeb588c705f6ab71c61e005705a387e7b4991c0605 /src/vnet/session/session.c
parent53c5015121b3d457377a1b1afac076e6218e5326 (diff)
session: allow transports to generate closed notifications
In contrast to the closing notification, whereby a transport informs the session layer that is beginning the closing procedure, this allows transports to notify the session layer of the fact that the transport is "fully" closed, i.e., it expects no more data. Also: - adds app closed state for sessions - changes tcp to have it notify when an active close has finished Type: feature Change-Id: I13c738006c03f85015e05ab82843a33a69382aaf Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/vnet/session/session.c')
-rw-r--r--src/vnet/session/session.c53
1 files changed, 27 insertions, 26 deletions
diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c
index 5b4e840f053..cbc8d800d72 100644
--- a/src/vnet/session/session.c
+++ b/src/vnet/session/session.c
@@ -796,6 +796,7 @@ session_transport_delete_notify (transport_connection_t * tc)
break;
case SESSION_STATE_ACCEPTING:
case SESSION_STATE_TRANSPORT_CLOSING:
+ case SESSION_STATE_CLOSING:
/* If transport finishes or times out before we get a reply
* from the app, mark transport as closed and wait for reply
* before removing the session. Cleanup session table in advance
@@ -806,18 +807,17 @@ session_transport_delete_notify (transport_connection_t * tc)
session_cleanup_notify (s, SESSION_CLEANUP_TRANSPORT);
svm_fifo_dequeue_drop_all (s->tx_fifo);
break;
- case SESSION_STATE_CLOSING:
- case SESSION_STATE_CLOSED_WAITING:
+ case SESSION_STATE_APP_CLOSED:
/* Cleanup lookup table as transport needs to still be valid.
* Program transport close to ensure that all session events
* have been cleaned up. Once transport close is called, the
* session is just removed because both transport and app have
* confirmed the close*/
session_lookup_del_session (s);
- s->session_state = SESSION_STATE_TRANSPORT_CLOSED;
- session_program_transport_close (s);
+ s->session_state = SESSION_STATE_CLOSED;
session_cleanup_notify (s, SESSION_CLEANUP_TRANSPORT);
svm_fifo_dequeue_drop_all (s->tx_fifo);
+ session_program_transport_close (s);
break;
case SESSION_STATE_TRANSPORT_CLOSED:
break;
@@ -834,16 +834,17 @@ session_transport_delete_notify (transport_connection_t * tc)
}
/**
- * Notification from transport that session can be closed
+ * Notification from transport that it is closed
*
- * Should be called by transport only if it was closed with non-empty
- * tx fifo and once it decides to begin the closing procedure prior to
- * issuing a delete notify. This gives the chance to the session layer
- * to cleanup any outstanding events.
+ * Should be called by transport, prior to calling delete notify, once it
+ * knows that no more data will be exchanged. This could serve as an
+ * early acknowledgment of an active close especially if transport delete
+ * can be delayed a long time, e.g., tcp time-wait.
*/
void
session_transport_closed_notify (transport_connection_t * tc)
{
+ app_worker_t *app_wrk;
session_t *s;
if (!(s = session_get_if_valid (tc->s_index, tc->thread_index)))
@@ -855,6 +856,7 @@ session_transport_closed_notify (transport_connection_t * tc)
{
session_transport_closing_notify (tc);
svm_fifo_dequeue_drop_all (s->tx_fifo);
+ s->session_state = SESSION_STATE_TRANSPORT_CLOSED;
}
/* If app close has not been received or has not yet resulted in
* a transport close, only mark the session transport as closed */
@@ -863,8 +865,13 @@ session_transport_closed_notify (transport_connection_t * tc)
session_lookup_del_session (s);
s->session_state = SESSION_STATE_TRANSPORT_CLOSED;
}
- else
+ /* In all closing states but transport closed switch to closed */
+ else if (s->session_state != SESSION_STATE_TRANSPORT_CLOSED)
s->session_state = SESSION_STATE_CLOSED;
+
+ app_wrk = app_worker_get_if_valid (s->app_wrk_index);
+ if (app_wrk)
+ app_worker_transport_closed_notify (app_wrk, s);
}
/**
@@ -1117,10 +1124,6 @@ session_close (session_t * s)
* acknowledge the close */
if (s->session_state == SESSION_STATE_TRANSPORT_CLOSED)
session_program_transport_close (s);
-
- /* Session already closed. Clear the tx fifo */
- if (s->session_state == SESSION_STATE_CLOSED)
- svm_fifo_dequeue_drop_all (s->tx_fifo);
return;
}
@@ -1138,23 +1141,21 @@ session_close (session_t * s)
void
session_transport_close (session_t * s)
{
- /* If transport is already closed, just free the session */
- if (s->session_state >= SESSION_STATE_TRANSPORT_CLOSED)
+ if (s->session_state >= SESSION_STATE_APP_CLOSED)
{
- session_free_w_fifos (s);
+ /* If transport is already closed, just free the session */
+ if (s->session_state >= SESSION_STATE_TRANSPORT_CLOSED)
+ session_free_w_fifos (s);
return;
}
- /* If tx queue wasn't drained, change state to closed waiting for transport.
- * This way, the transport, if it so wishes, can continue to try sending the
- * outstanding data (in closed state it cannot). It MUST however at one
- * point, either after sending everything or after a timeout, call delete
- * notify. This will finally lead to the complete cleanup of the session.
+ /* If the tx queue wasn't drained, the transport can continue to try
+ * sending the outstanding data (in closed state it cannot). It MUST however
+ * at one point, either after sending everything or after a timeout, call
+ * delete notify. This will finally lead to the complete cleanup of the
+ * session.
*/
- if (svm_fifo_max_dequeue_cons (s->tx_fifo))
- s->session_state = SESSION_STATE_CLOSED_WAITING;
- else
- s->session_state = SESSION_STATE_CLOSED;
+ s->session_state = SESSION_STATE_APP_CLOSED;
transport_close (session_get_transport_proto (s), s->connection_index,
s->thread_index);