diff options
Diffstat (limited to 'src/vcl/vppcom.c')
-rw-r--r-- | src/vcl/vppcom.c | 65 |
1 files changed, 46 insertions, 19 deletions
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index 19d58c349b7..1e9c915ce39 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -519,8 +519,7 @@ vcl_session_reset_handler (vcl_worker_t * wrk, } /* Caught a reset before actually accepting the session */ - if (session->session_state == VCL_STATE_LISTEN || - session->session_state == VCL_STATE_LISTEN_NO_MQ) + if (session->session_state == VCL_STATE_LISTEN) { if (!vcl_flag_accepted_session (session, reset_msg->handle, VCL_ACCEPTED_F_RESET)) @@ -712,8 +711,7 @@ vcl_session_disconnected_handler (vcl_worker_t * wrk, return 0; /* Caught a disconnect before actually accepting the session */ - if (session->session_state == VCL_STATE_LISTEN || - session->session_state == VCL_STATE_LISTEN_NO_MQ) + if (session->session_state == VCL_STATE_LISTEN) { if (!vcl_flag_accepted_session (session, msg->handle, VCL_ACCEPTED_F_CLOSED)) @@ -1085,8 +1083,7 @@ vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e) * VPP_CLOSING state instead can been marked as ACCEPTED_F_CLOSED. */ if (vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK) && - !(s->session_state == VCL_STATE_LISTEN || - s->session_state == VCL_STATE_LISTEN_NO_MQ)) + !(s->session_state == VCL_STATE_LISTEN)) { s->session_state = VCL_STATE_VPP_CLOSING; s->flags |= VCL_SESSION_F_PENDING_DISCONNECT; @@ -1114,8 +1111,7 @@ vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e) * DISCONNECT state instead can been marked as ACCEPTED_F_RESET. */ if (vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK) && - !(s->session_state == VCL_STATE_LISTEN || - s->session_state == VCL_STATE_LISTEN_NO_MQ)) + !(s->session_state == VCL_STATE_LISTEN)) { s->flags |= VCL_SESSION_F_PENDING_DISCONNECT; s->session_state = VCL_STATE_DISCONNECT; @@ -1331,6 +1327,12 @@ vppcom_session_unbind (u32 session_handle) } clib_fifo_free (session->accept_evts_fifo); + if (session->flags & VCL_SESSION_F_LISTEN_NO_MQ) + { + vcl_session_free (wrk, session); + return VPPCOM_OK; + } + vcl_send_session_unlisten (wrk, session); VDBG (0, "session %u [0x%llx]: sending unbind!", session->session_index, @@ -1425,10 +1427,11 @@ vcl_api_retry_attach (vcl_worker_t *wrk) { if (s->flags & VCL_SESSION_F_IS_VEP) continue; - if (s->session_state == VCL_STATE_LISTEN_NO_MQ) + if (s->session_state == VCL_STATE_LISTEN) vppcom_session_listen (vcl_session_handle (s), 10); else - VDBG (0, "internal error: unexpected state %d", s->session_state); + VDBG (0, "reattach error: %u unexpected state %d", s->session_index, + s->session_state); } } @@ -1769,12 +1772,20 @@ vppcom_session_listen (uint32_t listen_sh, uint32_t q_len) return VPPCOM_EBADFD; listen_vpp_handle = listen_session->vpp_handle; - if (listen_session->session_state == VCL_STATE_LISTEN) + if (listen_session->session_state == VCL_STATE_LISTEN && + !(listen_session->flags & VCL_SESSION_F_LISTEN_NO_MQ)) + { + VDBG (0, "session %u [0x%llx]: already in listen state!", listen_sh, + listen_vpp_handle); + return VPPCOM_OK; + } + if (PREDICT_FALSE (!wrk->ctrl_mq)) { - VDBG (0, "session %u [0x%llx]: already in listen state!", - listen_sh, listen_vpp_handle); + listen_session->session_state = VCL_STATE_LISTEN; + listen_session->flags |= VCL_SESSION_F_LISTEN_NO_MQ; return VPPCOM_OK; } + listen_session->flags &= ~VCL_SESSION_F_LISTEN_NO_MQ; VDBG (0, "session %u: sending vpp listen request...", listen_sh); @@ -1851,7 +1862,6 @@ again: return VPPCOM_EBADFD; if ((ls->session_state != VCL_STATE_LISTEN) && - (ls->session_state != VCL_STATE_LISTEN_NO_MQ) && (!vcl_session_is_connectable_listener (wrk, ls))) { VDBG (0, "ERROR: session [0x%llx]: not in listen state! state (%s)", @@ -2653,6 +2663,9 @@ vcl_select_handle_mq_event (vcl_worker_t * wrk, session_event_t * e, *bits_set += 1; } break; + case SESSION_CTRL_EVT_BOUND: + vcl_session_bound_handler (wrk, (session_bound_msg_t *) e->data); + break; case SESSION_CTRL_EVT_UNLISTEN_REPLY: vcl_session_unlisten_reply_handler (wrk, e->data); break; @@ -4544,17 +4557,31 @@ vppcom_session_sendto (uint32_t session_handle, void *buffer, if (ep->app_tlvs) vcl_handle_ep_app_tlvs (s, ep); - /* Session not connected/bound in vpp. Create it by 'connecting' it */ + /* Session not connected/bound in vpp. Create it by binding it */ if (PREDICT_FALSE (s->session_state == VCL_STATE_CLOSED)) { u32 session_index = s->session_index; f64 timeout = vcm->cfg.session_timeout; int rv; - vcl_send_session_connect (wrk, s); - rv = vppcom_wait_for_session_state_change (session_index, - VCL_STATE_READY, - timeout); + /* VPP assumes sockets are bound, not ideal, but for now + * connect socket, grab lcl ip:port pair and use it to bind */ + if (s->transport.rmt_port == 0 || + ip46_address_is_zero (&s->transport.lcl_ip)) + { + vcl_send_session_connect (wrk, s); + rv = vppcom_wait_for_session_state_change ( + session_index, VCL_STATE_READY, timeout); + if (rv < 0) + return rv; + vcl_send_session_disconnect (wrk, s); + rv = vppcom_wait_for_session_state_change ( + session_index, VCL_STATE_DETACHED, timeout); + s->session_state = VCL_STATE_CLOSED; + } + vcl_send_session_listen (wrk, s); + rv = vppcom_wait_for_session_state_change ( + session_index, VCL_STATE_LISTEN, timeout); if (rv < 0) return rv; s = vcl_session_get (wrk, session_index); |