summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2020-02-12 08:50:29 +0000
committerDave Barach <openvpp@barachs.net>2020-02-13 13:32:41 +0000
commitadcfb15fa0b08403c5b5b170149f7d3662e65761 (patch)
tree586d00dc43724fc0822eabeb2a8bbff048f59e0d
parent622b5ce61971066917cfba9ae795d9cb926f2700 (diff)
vcl: handle close after reset
Can happen if a connection is reset before fully accepted. Type: fix Signed-off-by: Florin Coras <fcoras@cisco.com> Change-Id: I0ae68d71b66722dd19ca6f1cee44a080e5ff4447
-rw-r--r--src/vcl/vcl_private.h2
-rw-r--r--src/vcl/vppcom.c40
2 files changed, 32 insertions, 10 deletions
diff --git a/src/vcl/vcl_private.h b/src/vcl/vcl_private.h
index 4b08b65e929..f1c15bac0bc 100644
--- a/src/vcl/vcl_private.h
+++ b/src/vcl/vcl_private.h
@@ -70,7 +70,7 @@ typedef enum
STATE_ACCEPT = 0x04,
STATE_VPP_CLOSING = 0x08,
STATE_DISCONNECT = 0x10,
- STATE_FAILED = 0x20,
+ STATE_DETACHED = 0x20,
STATE_UPDATED = 0x40,
STATE_LISTEN_NO_MQ = 0x80,
} vcl_session_state_t;
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c
index 892d65c348c..39d665bdb27 100644
--- a/src/vcl/vppcom.c
+++ b/src/vcl/vppcom.c
@@ -84,8 +84,8 @@ vppcom_session_state_str (vcl_session_state_t state)
st = "STATE_DISCONNECT";
break;
- case STATE_FAILED:
- st = "STATE_FAILED";
+ case STATE_DETACHED:
+ st = "STATE_DETACHED";
break;
case STATE_UPDATED:
@@ -443,7 +443,7 @@ vcl_session_connected_handler (vcl_worker_t * wrk,
{
VDBG (0, "ERROR: session index %u: connect failed! %U",
session_index, format_api_error, ntohl (mp->retval));
- session->session_state = STATE_FAILED | STATE_DISCONNECT;
+ session->session_state = STATE_DETACHED | STATE_DISCONNECT;
session->vpp_handle = mp->handle;
return session_index;
}
@@ -457,7 +457,7 @@ vcl_session_connected_handler (vcl_worker_t * wrk,
{
VDBG (0, "segment for session %u is not mounted!",
session->session_index);
- session->session_state = STATE_FAILED | STATE_DISCONNECT;
+ session->session_state = STATE_DETACHED | STATE_DISCONNECT;
vcl_send_session_disconnect (wrk, session);
return session_index;
}
@@ -479,7 +479,7 @@ vcl_session_connected_handler (vcl_worker_t * wrk,
{
VDBG (0, "ct segment for session %u is not mounted!",
session->session_index);
- session->session_state = STATE_FAILED | STATE_DISCONNECT;
+ session->session_state = STATE_DETACHED | STATE_DISCONNECT;
vcl_send_session_disconnect (wrk, session);
return session_index;
}
@@ -565,7 +565,7 @@ vcl_session_bound_handler (vcl_worker_t * wrk, session_bound_msg_t * mp)
format_api_error, mp->retval);
if (session)
{
- session->session_state = STATE_FAILED;
+ session->session_state = STATE_DETACHED;
session->vpp_handle = mp->handle;
return sid;
}
@@ -699,6 +699,10 @@ vcl_session_disconnected_handler (vcl_worker_t * wrk,
return 0;
}
+ /* Late disconnect notification on a session that has been closed */
+ if (session->session_state == STATE_CLOSED)
+ return 0;
+
/* Caught a disconnect before actually accepting the session */
if (session->session_state == STATE_LISTEN)
{
@@ -708,7 +712,10 @@ vcl_session_disconnected_handler (vcl_worker_t * wrk,
return 0;
}
- session->session_state = STATE_VPP_CLOSING;
+ /* If not already reset change state */
+ if (session->session_state != STATE_DISCONNECT)
+ session->session_state = STATE_VPP_CLOSING;
+
return session;
}
@@ -727,6 +734,14 @@ vcl_session_cleanup_handler (vcl_worker_t * wrk, void *data)
}
vcl_session_table_del_vpp_handle (wrk, msg->handle);
+ /* Should not happen. App did not close the connection so don't free it. */
+ if (session->session_state != STATE_CLOSED)
+ {
+ VDBG (0, "app did not close session %d", session->session_index);
+ session->session_state = STATE_DETACHED;
+ session->vpp_handle = VCL_INVALID_SESSION_HANDLE;
+ return;
+ }
vcl_session_free (wrk, session);
}
@@ -906,7 +921,7 @@ vppcom_wait_for_session_state_change (u32 session_index,
{
return VPPCOM_OK;
}
- if (session->session_state & STATE_FAILED)
+ if (session->session_state & STATE_DETACHED)
{
return VPPCOM_ECONNREFUSED;
}
@@ -1308,6 +1323,12 @@ vcl_session_cleanup (vcl_worker_t * wrk, vcl_session_t * session,
vcl_send_session_reset_reply (mq, wrk->my_client_index,
session->vpp_handle, 0);
}
+ else if (state == STATE_DETACHED)
+ {
+ /* Should not happen. VPP cleaned up before app confirmed close */
+ VDBG (0, "vpp freed session %d before close", session->session_index);
+ goto free_session;
+ }
session->session_state = STATE_CLOSED;
@@ -1316,6 +1337,7 @@ vcl_session_cleanup (vcl_worker_t * wrk, vcl_session_t * session,
cleanup:
vcl_session_table_del_vpp_handle (wrk, vpp_handle);
+free_session:
vcl_session_free (wrk, session);
vcl_evt (VCL_EVT_CLOSE, session, rv);
@@ -2772,7 +2794,7 @@ vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
add_event = 1;
events[*num_ev].events |= EPOLLOUT;
session_evt_data = session->vep.ev.data.u64;
- if (session->session_state & STATE_FAILED)
+ if (session->session_state & STATE_DETACHED)
events[*num_ev].events |= EPOLLHUP;
break;
case SESSION_CTRL_EVT_DISCONNECTED: