diff options
author | Dave Wallace <dwallacelf@gmail.com> | 2017-11-21 03:45:09 -0500 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2017-11-21 23:16:50 +0000 |
commit | 4878cbe276ec1131d0cf30ac5df18aa9ba699bc4 (patch) | |
tree | c0c6e746c75aac7e335d6caf96c4e68264b5eaec | |
parent | 6a9b68b268f9dc87a221fac0ec9b0b67c16106ca (diff) |
VCL: close-on-empty state transition refactoring.
- Refactor session disconnect/close state
transitions. Only remove session state
when app calls close(). Add HUP/reset
feedback by returning ECONNRESET.
- Update debug messages.
- Use VCL_LOCK_AND_GET_SESSION macro more
extensively
Change-Id: I23d372834b901a6726e6d6c1061df73ad967882f
Signed-off-by: Dave Wallace <dwallacelf@gmail.com>
-rw-r--r-- | src/vcl/vppcom.c | 1418 | ||||
-rw-r--r-- | src/vcl/vppcom.h | 5 | ||||
-rwxr-xr-x | test/scripts/socket_test.sh | 2 |
3 files changed, 764 insertions, 661 deletions
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index 2e867c7f036..2ccb2b86705 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -66,14 +66,18 @@ typedef enum typedef enum { - STATE_START, - STATE_CONNECT, - STATE_LISTEN, - STATE_ACCEPT, - STATE_DISCONNECT, - STATE_FAILED + STATE_START = 0x01, + STATE_CONNECT = 0x02, + STATE_LISTEN = 0x04, + STATE_ACCEPT = 0x08, + STATE_CLOSE_ON_EMPTY = 0x10, + STATE_DISCONNECT = 0x20, + STATE_FAILED = 0x40 } session_state_t; +#define SERVER_STATE_OPEN (STATE_ACCEPT|STATE_CLOSE_ON_EMPTY) +#define CLIENT_STATE_OPEN (STATE_CONNECT|STATE_CLOSE_ON_EMPTY) + typedef struct epoll_event vppcom_epoll_event_t; typedef struct @@ -152,7 +156,6 @@ typedef struct vppcom_main_t_ u8 init; u32 debug; u32 *client_session_index_fifo; - volatile u32 bind_session_index; int main_cpu; /* vpe input queue */ @@ -209,11 +212,8 @@ do { \ if (PREDICT_FALSE (rv)) \ { \ clib_spinlock_unlock (&vcm->sessions_lockp); \ - \ - if (VPPCOM_DEBUG > 0) \ - clib_warning ("[%s] ERROR: Invalid ##I (%u)!", \ - getpid (), I); \ - \ + clib_warning ("[%s] ERROR: Invalid ##I (%u)!", \ + getpid (), I); \ goto done; \ } \ } while (0) @@ -272,6 +272,10 @@ vppcom_session_state_str (session_state_t state) st = "STATE_ACCEPT"; break; + case STATE_CLOSE_ON_EMPTY: + st = "STATE_CLOSE_ON_EMPTY"; + break; + case STATE_DISCONNECT: st = "STATE_DISCONNECT"; break; @@ -321,6 +325,8 @@ vppcom_session_table_lookup_listener (u64 listener_handle) { uword *p; u64 handle = listener_handle | (1ULL << 63); + session_t *session; + p = hash_get (vcm->session_index_by_vpp_handles, handle); if (!p) { @@ -336,7 +342,9 @@ vppcom_session_table_lookup_listener (u64 listener_handle) return 0; } - return pool_elt_at_index (vcm->sessions, p[0]); + session = pool_elt_at_index (vcm->sessions, p[0]); + ASSERT (session->is_listen); + return session; } static inline void @@ -434,13 +442,19 @@ vppcom_wait_for_session_state_change (u32 session_index, clib_spinlock_unlock (&vcm->sessions_lockp); return VPPCOM_OK; } + if (session->state == STATE_FAILED) + { + clib_spinlock_unlock (&vcm->sessions_lockp); + return VPPCOM_ECONNREFUSED; + } + clib_spinlock_unlock (&vcm->sessions_lockp); } while (clib_time_now (&vcm->clib_time) < timeout); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] timeout waiting for state %s (%d)", getpid (), - vppcom_session_state_str (state), state); + clib_warning ("[%d] timeout waiting for state 0x%x (%s)", getpid (), + state, vppcom_session_state_str (state)); return VPPCOM_ETIMEDOUT; } @@ -638,46 +652,10 @@ static void vl_api_disconnect_session_reply_t_handler (vl_api_disconnect_session_reply_t * mp) { - uword *p; - u32 session_index = ~0; - - p = hash_get (vcm->session_index_by_vpp_handles, mp->handle); - if (p) - { - session_t *session = 0; - int rv; - - session_index = p[0]; - hash_unset (vcm->session_index_by_vpp_handles, mp->handle); - clib_spinlock_lock (&vcm->sessions_lockp); - rv = vppcom_session_at_index (session_index, &session); - if (PREDICT_FALSE (rv)) - { - if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] invalid session, sid %u has been closed!", - getpid (), session_index); - } - else - { - if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u disconnected!", - getpid (), mp->handle, session_index); - - session->state = STATE_DISCONNECT; - } - clib_spinlock_unlock (&vcm->sessions_lockp); - } - else - { - if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] couldn't find session: unknown vpp handle 0x%llx", - getpid (), mp->handle); - } - if (mp->retval) - clib_warning ("[%d] disconnect_session vpp handle 0x%llx, sid %u " - "failed: %U", getpid (), mp->handle, session_index, - format_api_error, ntohl (mp->retval)); + clib_warning ("[%d] vpp handle 0x%llx: disconnect session failed: %U", + getpid (), mp->handle, format_api_error, + ntohl (mp->retval)); } static void @@ -707,57 +685,35 @@ vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp) static void vl_api_disconnect_session_t_handler (vl_api_disconnect_session_t * mp) { - session_t *session = 0; - vl_api_disconnect_session_reply_t *rmp; uword *p; - int rv = 0, rval; p = hash_get (vcm->session_index_by_vpp_handles, mp->handle); - if (VPPCOM_DEBUG > 0) + if (p) { - if (!p) - { - clib_warning ("[%d] request to disconnect invalid handle (%u)!", - getpid (), mp->handle); - rv = -11; - goto done; - } - clib_warning ("[%d] disconnecting handle %u sid (%u)!", getpid (), - mp->handle, p[0]); - } + int rv; + session_t *session = 0; + u32 session_index = p[0]; - goto done; + VCL_LOCK_AND_GET_SESSION (session_index, &session); + session->state = STATE_CLOSE_ON_EMPTY; - if (p) - { - clib_spinlock_lock (&vcm->sessions_lockp); - rval = vppcom_session_at_index (p[0], &session); - if (PREDICT_FALSE (rval)) - { - if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] invalid session, sid (%u) has been closed!", - getpid (), p[0]); - } - else - pool_put (vcm->sessions, session); + if (VPPCOM_DEBUG > 1) + clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + "setting state to %d (%s)", + getpid (), mp->handle, session_index, session->state, + vppcom_session_state_str (session->state)); clib_spinlock_unlock (&vcm->sessions_lockp); - hash_unset (vcm->session_index_by_vpp_handles, mp->handle); + return; + + done: + if (VPPCOM_DEBUG > 1) + clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + "session lookup failed!", + getpid (), mp->handle, session_index); } else - { - clib_warning ("[%d] couldn't find session: unknown vpp handle 0x%llx", - getpid (), mp->handle); - rv = -11; - } - -done: - rmp = vl_msg_api_alloc (sizeof (*rmp)); - memset (rmp, 0, sizeof (*rmp)); - - rmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION_REPLY); - rmp->retval = htonl (rv); - rmp->handle = mp->handle; - vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp); + clib_warning ("[%d] vpp handle 0x%llx: session lookup by " + "handle failed!", getpid (), mp->handle); } static void @@ -776,20 +732,32 @@ vl_api_reset_session_t_handler (vl_api_reset_session_t * mp) rval = vppcom_session_at_index (p[0], &session); if (PREDICT_FALSE (rval)) { - if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] invalid session, sid (%u) has been closed!", - getpid (), p[0]); + rv = VNET_API_ERROR_INVALID_VALUE_2; + clib_warning ("[%d] ERROR: sid %u: session lookup failed! " + "returning %d %U", + getpid (), p[0], rv, format_api_error, rv); } else - pool_put (vcm->sessions, session); + { + /* TBD: should this disconnect immediately and + * flush the fifos? + */ + session->state = STATE_CLOSE_ON_EMPTY; + + if (VPPCOM_DEBUG > 1) + clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + "state set to %d (%s)!", getpid (), + mp->handle, p[0], session->state, + vppcom_session_state_str (session->state)); + } clib_spinlock_unlock (&vcm->sessions_lockp); - hash_unset (vcm->session_index_by_vpp_handles, mp->handle); } else { - clib_warning ("[%d] couldn't find session: unknown vpp handle 0x%llx", - getpid (), mp->handle); - rv = -11; + rv = VNET_API_ERROR_INVALID_VALUE; + clib_warning ("[%d] ERROR: vpp handle 0x%llx: session lookup " + "failed! returning %d %U", + getpid (), mp->handle, rv, format_api_error, rv); } rmp = vl_msg_api_alloc (sizeof (*rmp)); @@ -809,24 +777,25 @@ vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp) u8 is_cut_thru = 0; int rv; + session_index = mp->context; if (mp->retval) { - clib_warning ("[%d] connect failed: %U", getpid (), format_api_error, + clib_warning ("[%d] ERROR: sid %u: connect failed! %U", + getpid (), session_index, format_api_error, ntohl (mp->retval)); return; } - session_index = mp->context; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] session_index = %d 0x%08x", getpid (), - session_index, session_index); + clib_warning ("[%d] sid %u: got a connect reply!", + getpid (), session_index); clib_spinlock_lock (&vcm->sessions_lockp); if (pool_is_free_index (vcm->sessions, session_index)) { clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] invalid session, sid %d is closed!", + clib_warning ("[%d] sid %d: session lookup failed!", getpid (), session_index); return; } @@ -905,10 +874,6 @@ vppcom_send_connect_sock (session_t * session, u32 session_index) cmp->client_index = vcm->my_client_index; cmp->context = session_index; - if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] session_index = %d 0x%08x", - getpid (), session_index, session_index); - cmp->vrf = session->vrf; cmp->is_ip4 = session->peer_addr.is_ip4; clib_memcpy (cmp->ip, &session->peer_addr.ip46, sizeof (cmp->ip)); @@ -919,16 +884,38 @@ vppcom_send_connect_sock (session_t * session, u32 session_index) } static inline void -vppcom_send_disconnect (session_t * session) +vppcom_send_disconnect_session_reply (u64 vpp_handle, u32 session_index, + int rv) +{ + vl_api_disconnect_session_reply_t *rmp; + + if (VPPCOM_DEBUG > 1) + clib_warning ("[%d] vpp handle 0x%llx, sid %u: sending disconnect msg", + getpid (), vpp_handle, session_index); + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + memset (rmp, 0, sizeof (*rmp)); + + rmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION_REPLY); + rmp->retval = htonl (rv); + rmp->handle = vpp_handle; + vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp); +} + +static inline void +vppcom_send_disconnect_session (u64 vpp_handle, u32 session_index) { vl_api_disconnect_session_t *dmp; - /* Assumes caller as acquired the spinlock: vcm->sessions_lockp */ + if (VPPCOM_DEBUG > 1) + clib_warning ("[%d] vpp handle 0x%llx, sid %u: sending disconnect msg", + getpid (), vpp_handle, session_index); + dmp = vl_msg_api_alloc (sizeof (*dmp)); memset (dmp, 0, sizeof (*dmp)); dmp->_vl_msg_id = |