X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvcl%2Fvppcom.c;h=46cea2a1884be4a0d8072698fbce58a06b289ce6;hb=f22f4e562e1b922cff036ef628b77fd2d479d015;hp=4b12062215e917d98b81984b71e9f5d8136fbf65;hpb=ddb90a063cb3fa797257d8a632cba8cf2a01a455;p=vpp.git diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index 4b12062215e..46cea2a1884 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -60,8 +60,8 @@ vppcom_session_state_str (vcl_session_state_t state) switch (state) { - case STATE_START: - st = "STATE_START"; + case STATE_CLOSED: + st = "STATE_CLOSED"; break; case STATE_CONNECT: @@ -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; } @@ -679,6 +679,7 @@ vcl_session_accepted (vcl_worker_t * wrk, session_accepted_msg_t * msg) } clib_fifo_add2 (session->accept_evts_fifo, vcl_msg); + vcl_msg->flags = 0; vcl_msg->accepted_msg = *msg; /* Session handle points to listener until fully accepted by app */ vcl_session_table_add_vpp_handle (wrk, msg->handle, session->session_index); @@ -699,6 +700,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,10 +713,39 @@ 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; } +static void +vcl_session_cleanup_handler (vcl_worker_t * wrk, void *data) +{ + session_cleanup_msg_t *msg; + vcl_session_t *session; + + msg = (session_cleanup_msg_t *) data; + session = vcl_session_get_w_vpp_handle (wrk, msg->handle); + if (!session) + { + VDBG (0, "disconnect confirmed for unknown handle 0x%llx", msg->handle); + return; + } + + 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); +} + static void vcl_session_req_worker_update_handler (vcl_worker_t * wrk, void *data) { @@ -845,6 +879,9 @@ vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e) case SESSION_CTRL_EVT_MIGRATED: vcl_session_migrated_handler (wrk, e->data); break; + case SESSION_CTRL_EVT_CLEANUP: + vcl_session_cleanup_handler (wrk, e->data); + break; case SESSION_CTRL_EVT_REQ_WORKER_UPDATE: vcl_session_req_worker_update_handler (wrk, e->data); break; @@ -885,7 +922,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; } @@ -1199,7 +1236,7 @@ vppcom_session_create (u8 proto, u8 is_nonblocking) session = vcl_session_alloc (wrk); session->session_type = proto; - session->session_state = STATE_START; + session->session_state = STATE_CLOSED; session->vpp_handle = ~0; session->is_dgram = vcl_proto_is_dgram (proto); @@ -1244,55 +1281,64 @@ vcl_session_cleanup (vcl_worker_t * wrk, vcl_session_t * session, next_sh = session->vep.next_sh; } + goto cleanup; } - else + + if (session->is_vep_session) { - if (session->is_vep_session) - { - rv = vppcom_epoll_ctl (vep_sh, EPOLL_CTL_DEL, sh, 0); - if (rv < 0) - VDBG (0, "session %u [0x%llx]: EPOLL_CTL_DEL vep_idx %u " - "failed! rv %d (%s)", session->session_index, vpp_handle, - vep_sh, rv, vppcom_retval_str (rv)); - } + rv = vppcom_epoll_ctl (vep_sh, EPOLL_CTL_DEL, sh, 0); + if (rv < 0) + VDBG (0, "session %u [0x%llx]: EPOLL_CTL_DEL vep_idx %u " + "failed! rv %d (%s)", session->session_index, vpp_handle, + vep_sh, rv, vppcom_retval_str (rv)); + } - if (!do_disconnect) - { - VDBG (1, "session %u [0x%llx] disconnect skipped", - session->session_index, vpp_handle); - goto cleanup; - } + if (!do_disconnect) + { + VDBG (1, "session %u [0x%llx] disconnect skipped", + session->session_index, vpp_handle); + goto cleanup; + } - if (state & STATE_LISTEN) - { - rv = vppcom_session_unbind (sh); - if (PREDICT_FALSE (rv < 0)) - VDBG (0, "session %u [0x%llx]: listener unbind failed! " - "rv %d (%s)", session->session_index, vpp_handle, rv, - vppcom_retval_str (rv)); - return rv; - } - else if ((state & STATE_OPEN) - || (vcl_session_is_connectable_listener (wrk, session))) - { - rv = vppcom_session_disconnect (sh); - if (PREDICT_FALSE (rv < 0)) - VDBG (0, "ERROR: session %u [0x%llx]: disconnect failed!" - " rv %d (%s)", session->session_index, vpp_handle, - rv, vppcom_retval_str (rv)); - } - else if (state == STATE_DISCONNECT) - { - svm_msg_q_t *mq = vcl_session_vpp_evt_q (wrk, session); - vcl_send_session_reset_reply (mq, wrk->my_client_index, - session->vpp_handle, 0); - } + if (state & STATE_LISTEN) + { + rv = vppcom_session_unbind (sh); + if (PREDICT_FALSE (rv < 0)) + VDBG (0, "session %u [0x%llx]: listener unbind failed! " + "rv %d (%s)", session->session_index, vpp_handle, rv, + vppcom_retval_str (rv)); + return rv; + } + else if ((state & STATE_OPEN) + || (vcl_session_is_connectable_listener (wrk, session))) + { + rv = vppcom_session_disconnect (sh); + if (PREDICT_FALSE (rv < 0)) + VDBG (0, "ERROR: session %u [0x%llx]: disconnect failed!" + " rv %d (%s)", session->session_index, vpp_handle, + rv, vppcom_retval_str (rv)); + } + else if (state == STATE_DISCONNECT) + { + svm_msg_q_t *mq = vcl_session_vpp_evt_q (wrk, 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; - VDBG (0, "session %u [0x%llx] removed", session->session_index, vpp_handle); + /* Session is removed only after vpp confirms the disconnect */ + return rv; cleanup: vcl_session_table_del_vpp_handle (wrk, vpp_handle); +free_session: vcl_session_free (wrk, session); vcl_evt (VCL_EVT_CLOSE, session, rv); @@ -2163,6 +2209,9 @@ vcl_select_handle_mq_event (vcl_worker_t * wrk, session_event_t * e, case SESSION_CTRL_EVT_MIGRATED: vcl_session_migrated_handler (wrk, e->data); break; + case SESSION_CTRL_EVT_CLEANUP: + vcl_session_cleanup_handler (wrk, e->data); + break; case SESSION_CTRL_EVT_WORKER_UPDATE_REPLY: vcl_session_worker_update_reply_handler (wrk, e->data); break; @@ -2746,7 +2795,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: @@ -2774,6 +2823,9 @@ vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e, case SESSION_CTRL_EVT_MIGRATED: vcl_session_migrated_handler (wrk, e->data); break; + case SESSION_CTRL_EVT_CLEANUP: + vcl_session_cleanup_handler (wrk, e->data); + break; case SESSION_CTRL_EVT_REQ_WORKER_UPDATE: vcl_session_req_worker_update_handler (wrk, e->data); break; @@ -3145,7 +3197,8 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op, /* VPP-TBD */ *(size_t *) buffer = (session->sndbuf_size ? session->sndbuf_size : - session->tx_fifo ? session->tx_fifo->nitems : + session->tx_fifo ? + svm_fifo_size (session->tx_fifo) : vcm->cfg.tx_fifo_size); *buflen = sizeof (u32); @@ -3176,7 +3229,8 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op, /* VPP-TBD */ *(size_t *) buffer = (session->rcvbuf_size ? session->rcvbuf_size : - session->rx_fifo ? session->rx_fifo->nitems : + session->rx_fifo ? + svm_fifo_size (session->rx_fifo) : vcm->cfg.rx_fifo_size); *buflen = sizeof (u32);