X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvcl%2Fvppcom.c;h=a0bbae170f8e46be41d570ac63bc6faa4b9b3ae0;hb=8ae63db02066a2b5ac18a89fd63dc0dd2a811ab3;hp=d9cc885bb0e1c77e0d63ef8302f616d7b86c1ada;hpb=5cca669fc723371f6692e4b88136728bf7353b92;p=vpp.git diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index d9cc885bb0e..a0bbae170f8 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -351,6 +351,11 @@ vcl_session_accepted_handler (vcl_worker_t * wrk, session_accepted_msg_t * mp, session->vpp_handle = mp->handle; session->session_state = VCL_STATE_READY; + if (mp->rmt.is_ip4) + { + session->original_dst_ip4 = mp->original_dst_ip4; + session->original_dst_port = mp->original_dst_port; + } session->transport.rmt_port = mp->rmt.port; session->transport.is_ip4 = mp->rmt.is_ip4; clib_memcpy_fast (&session->transport.rmt_ip, &mp->rmt.ip, @@ -508,9 +513,9 @@ vcl_session_reset_handler (vcl_worker_t * wrk, } /* Caught a reset before actually accepting the session */ - if (session->session_state == VCL_STATE_LISTEN) + if (session->session_state == VCL_STATE_LISTEN || + session->session_state == VCL_STATE_LISTEN_NO_MQ) { - if (!vcl_flag_accepted_session (session, reset_msg->handle, VCL_ACCEPTED_F_RESET)) VDBG (0, "session was not accepted!"); @@ -540,6 +545,7 @@ vcl_session_bound_handler (vcl_worker_t * wrk, session_bound_msg_t * mp) { session->session_state = VCL_STATE_DETACHED; session->vpp_handle = mp->handle; + session->vpp_error = mp->retval; return sid; } else @@ -701,7 +707,8 @@ 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) + if (session->session_state == VCL_STATE_LISTEN || + session->session_state == VCL_STATE_LISTEN_NO_MQ) { if (!vcl_flag_accepted_session (session, msg->handle, VCL_ACCEPTED_F_CLOSED)) @@ -1048,7 +1055,15 @@ vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e) break; if (s->session_state == VCL_STATE_CLOSED) break; - if (vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK)) + /* We do not postpone for blocking sessions or listen sessions because: + * 1. Blocking sessions are not part of epoll instead they're used in a + * synchronous manner, such as read/write and etc. + * 2. Listen sessions that have not yet been accepted can't change to + * 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_VPP_CLOSING; s->flags |= VCL_SESSION_F_PENDING_DISCONNECT; @@ -1069,7 +1084,15 @@ vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e) break; if (s->session_state == VCL_STATE_CLOSED) break; - if (vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK)) + /* We do not postpone for blocking sessions or listen sessions because: + * 1. Blocking sessions are not part of epoll instead they're used in a + * synchronous manner, such as read/write and etc. + * 2. Listen sessions that have not yet been accepted can't change to + * 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->flags |= VCL_SESSION_F_PENDING_DISCONNECT; s->session_state = VCL_STATE_DISCONNECT; @@ -1139,7 +1162,10 @@ vppcom_wait_for_session_state_change (u32 session_index, } if (session->session_state == VCL_STATE_DETACHED) { - return VPPCOM_ECONNREFUSED; + if (session->vpp_error == SESSION_E_ALREADY_LISTENING) + return VPPCOM_EADDRINUSE; + else + return VPPCOM_ECONNREFUSED; } if (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_NOWAIT, 0)) @@ -1414,12 +1440,10 @@ vppcom_app_destroy (void) current_wrk = vcl_worker_get_current (); - /* *INDENT-OFF* */ pool_foreach (wrk, vcm->workers) { if (current_wrk != wrk) vcl_worker_cleanup (wrk, 0 /* notify vpp */ ); } - /* *INDENT-ON* */ vcl_api_detach (current_wrk); vcl_worker_cleanup (current_wrk, 0 /* notify vpp */ ); @@ -1656,7 +1680,7 @@ vppcom_session_bind (uint32_t session_handle, vppcom_endpt_t * ep) vcl_evt (VCL_EVT_BIND, session); if (session->session_type == VPPCOM_PROTO_UDP) - vppcom_session_listen (session_handle, 10); + return vppcom_session_listen (session_handle, 10); return VPPCOM_OK; } @@ -2030,13 +2054,13 @@ vppcom_session_read_internal (uint32_t session_handle, void *buf, int n, if (svm_fifo_is_empty_cons (rx_fifo)) { + if (is_ct) + svm_fifo_unset_event (s->rx_fifo); + svm_fifo_unset_event (rx_fifo); if (is_nonblocking) { if (vcl_session_is_closing (s)) return vcl_session_closing_error (s); - if (is_ct) - svm_fifo_unset_event (s->rx_fifo); - svm_fifo_unset_event (rx_fifo); return VPPCOM_EWOULDBLOCK; } while (svm_fifo_is_empty_cons (rx_fifo)) @@ -2142,11 +2166,13 @@ vppcom_session_read_segments (uint32_t session_handle, if (svm_fifo_is_empty_cons (rx_fifo)) { + if (is_ct) + svm_fifo_unset_event (s->rx_fifo); + svm_fifo_unset_event (rx_fifo); if (is_nonblocking) { - if (is_ct) - svm_fifo_unset_event (s->rx_fifo); - svm_fifo_unset_event (rx_fifo); + if (vcl_session_is_closing (s)) + return vcl_session_closing_error (s); return VPPCOM_EWOULDBLOCK; } while (svm_fifo_is_empty_cons (rx_fifo)) @@ -2425,10 +2451,24 @@ vcl_select_handle_mq_event (vcl_worker_t * wrk, session_event_t * e, vcl_session_add_want_deq_ntf (s, SVM_FIFO_WANT_DEQ_NOTIF_IF_FULL); break; case SESSION_CTRL_EVT_DISCONNECTED: - disconnected_msg = (session_disconnected_msg_t *) e->data; - s = vcl_session_disconnected_handler (wrk, disconnected_msg); - if (!s) - break; + if (!e->postponed) + { + disconnected_msg = (session_disconnected_msg_t *) e->data; + s = vcl_session_disconnected_handler (wrk, disconnected_msg); + if (!s) + break; + } + else + { + s = vcl_session_get (wrk, e->session_index); + s->flags &= ~VCL_SESSION_F_PENDING_DISCONNECT; + } + if (vcl_session_is_closed (s)) + { + if (s && (s->flags & VCL_SESSION_F_PENDING_FREE)) + vcl_session_free (wrk, s); + break; + } sid = s->session_index; if (sid < n_bits && except_map) { @@ -2437,7 +2477,24 @@ vcl_select_handle_mq_event (vcl_worker_t * wrk, session_event_t * e, } break; case SESSION_CTRL_EVT_RESET: - sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data); + if (!e->postponed) + { + sid = + vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data); + s = vcl_session_get (wrk, sid); + } + else + { + sid = e->session_index; + s = vcl_session_get (wrk, sid); + s->flags &= ~VCL_SESSION_F_PENDING_DISCONNECT; + } + if (vcl_session_is_closed (s)) + { + if (s && (s->flags & VCL_SESSION_F_PENDING_FREE)) + vcl_session_free (wrk, s); + break; + } if (sid < n_bits && except_map) { clib_bitmap_set_no_check ((uword *) except_map, sid, 1); @@ -2771,7 +2828,7 @@ vppcom_epoll_create (void) static void vcl_epoll_ctl_add_unhandled_event (vcl_worker_t *wrk, vcl_session_t *s, - u8 is_epollet, session_evt_type_t evt) + u32 is_epollet, session_evt_type_t evt) { if (!is_epollet) { @@ -3528,7 +3585,19 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op, VDBG (2, "VPPCOM_ATTR_GET_NWRITE: sh %u, nwrite = %d", session_handle, rv); break; - + case VPPCOM_ATTR_GET_NWRITEQ: + if (PREDICT_FALSE (!buffer || !buflen || *buflen != sizeof (int))) + { + rv = VPPCOM_EINVAL; + break; + } + if (!session->tx_fifo || session->session_state == VCL_STATE_DETACHED) + { + rv = VPPCOM_EINVAL; + break; + } + *(int *) buffer = svm_fifo_max_dequeue (session->tx_fifo); + break; case VPPCOM_ATTR_GET_FLAGS: if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*flags)))) { @@ -3611,6 +3680,33 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op, rv = VPPCOM_EINVAL; break; + case VPPCOM_ATTR_GET_ORIGINAL_DST: + if (!session->transport.is_ip4) + { + /* now original dst only support ipv4*/ + rv = VPPCOM_EAFNOSUPPORT; + break; + } + if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*ep)) && + ep->ip)) + { + ep->is_ip4 = session->transport.is_ip4; + ep->port = session->original_dst_port; + clib_memcpy_fast (ep->ip, &session->original_dst_ip4, + sizeof (ip4_address_t)); + *buflen = sizeof (*ep); + VDBG (1, + "VPPCOM_ATTR_GET_ORIGINAL_DST: sh %u, is_ip4 = %u, addr = %U" + " port %d", + session_handle, ep->is_ip4, vcl_format_ip4_address, + (ip4_address_t *) (&session->original_dst_ip4), + ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6, + clib_net_to_host_u16 (ep->port)); + } + else + rv = VPPCOM_EINVAL; + break; + case VPPCOM_ATTR_SET_LCL_ADDR: if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*ep)) && ep->ip))