X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvcl%2Fvppcom.c;h=3b265d29ab85e54845ff9e449af9c2341f91b0ed;hb=1d84abc93ed0f41ee7ced184e57ab9b6241c6eba;hp=0e81749224e915e4659c1dedc6cf32c3e2c1083f;hpb=8ccc6b350703d3390633636d2b1c2f578f37cb21;p=vpp.git diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index 0e81749224e..3b265d29ab8 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -289,10 +289,17 @@ vcl_session_transport_attr (vcl_worker_t *wrk, vcl_session_t *s, u8 is_get, f64 timeout; ASSERT (!wrk->session_attr_op); + mq = s->vpp_evt_q; + if (PREDICT_FALSE (!mq)) + { + /* FIXME: attribute should be stored and sent once session is + * bound/connected to vpp */ + return 0; + } + wrk->session_attr_op = 1; wrk->session_attr_op_rv = -1; - mq = s->vpp_evt_q; app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_TRANSPORT_ATTR); mp = (session_transport_attr_msg_t *) app_evt->evt->data; memset (mp, 0, sizeof (*mp)); @@ -404,6 +411,7 @@ vcl_session_connected_handler (vcl_worker_t * wrk, format_session_error, mp->retval); session->session_state = VCL_STATE_DETACHED; session->vpp_handle = VCL_INVALID_SESSION_HANDLE; + session->vpp_error = mp->retval; return session_index; } @@ -508,6 +516,8 @@ vcl_session_reset_handler (vcl_worker_t * wrk, if (session->session_state != VCL_STATE_CLOSED) session->session_state = VCL_STATE_DISCONNECT; + + session->flags |= (VCL_SESSION_F_RD_SHUTDOWN | VCL_SESSION_F_WR_SHUTDOWN); VDBG (0, "session %u [0x%llx]: reset", sid, reset_msg->handle); return sid; } @@ -790,7 +800,8 @@ vppcom_session_disconnect (u32 session_handle) if (session->listener_index != VCL_INVALID_SESSION_INDEX) { listen_session = vcl_session_get (wrk, session->listener_index); - listen_session->n_accepted_sessions--; + if (listen_session) + listen_session->n_accepted_sessions--; } return VPPCOM_OK; @@ -1058,6 +1069,7 @@ vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e) { s->flags |= VCL_SESSION_F_PENDING_DISCONNECT; s->session_state = VCL_STATE_DISCONNECT; + s->flags |= (VCL_SESSION_F_RD_SHUTDOWN | VCL_SESSION_F_WR_SHUTDOWN); vec_add2 (wrk->unhandled_evts_vector, ecpy, 1); *ecpy = *e; ecpy->postponed = 1; @@ -1256,13 +1268,56 @@ vcl_api_attach (void) return vcl_bapi_attach (); } +int +vcl_is_first_reattach_to_execute () +{ + if (vcm->reattach_count == 0) + return 1; + + return 0; +} + +void +vcl_set_reattach_counter () +{ + ++vcm->reattach_count; + + if (vcm->reattach_count == vec_len (vcm->workers)) + vcm->reattach_count = 0; +} + +/** + * Reattach vcl to vpp after it has previously been disconnected. + * + * The logic should be: + * - first worker to hit `vcl_api_retry_attach` should attach to vpp, + * to reproduce the `vcl_api_attach` in `vppcom_app_create`. + * - the rest of the workers should `reproduce vcl_worker_register_with_vpp` + * from `vppcom_worker_register` since they were already allocated. + */ + static void vcl_api_retry_attach (vcl_worker_t *wrk) { vcl_session_t *s; - if (vcl_api_attach ()) - return; + clib_spinlock_lock (&vcm->workers_lock); + if (vcl_is_first_reattach_to_execute ()) + { + if (vcl_api_attach ()) + { + clib_spinlock_unlock (&vcm->workers_lock); + return; + } + vcl_set_reattach_counter (); + clib_spinlock_unlock (&vcm->workers_lock); + } + else + { + vcl_set_reattach_counter (); + clib_spinlock_unlock (&vcm->workers_lock); + vcl_worker_register_with_vpp (); + } /* Treat listeners as configuration that needs to be re-added to vpp */ pool_foreach (s, wrk->sessions) @@ -1286,6 +1341,9 @@ vcl_api_handle_disconnect (vcl_worker_t *wrk) static void vcl_api_detach (vcl_worker_t * wrk) { + if (wrk->api_client_handle == ~0) + return; + vcl_send_app_detach (wrk); if (vcm->cfg.vpp_app_socket_api) @@ -1328,7 +1386,10 @@ vppcom_app_create (const char *app_name) vcl_worker_alloc_and_init (); if ((rv = vcl_api_attach ())) - return rv; + { + vppcom_app_destroy (); + return rv; + } VDBG (0, "app_name '%s', my_client_index %d (0x%x)", app_name, vcm->workers[0].api_client_handle, vcm->workers[0].api_client_handle); @@ -1358,6 +1419,7 @@ vppcom_app_destroy (void) vcl_api_detach (current_wrk); vcl_worker_cleanup (current_wrk, 0 /* notify vpp */ ); + vcl_set_worker_index (~0); vcl_elog_stop (vcm); @@ -1383,6 +1445,7 @@ vppcom_session_create (u8 proto, u8 is_nonblocking) session->session_state = VCL_STATE_CLOSED; session->vpp_handle = ~0; session->is_dgram = vcl_proto_is_dgram (proto); + session->vpp_error = SESSION_E_NONE; if (is_nonblocking) vcl_session_set_attr (session, VCL_SESS_ATTR_NONBLOCK); @@ -2164,8 +2227,8 @@ vcl_fifo_is_writeable (svm_fifo_t * f, u32 len, u8 is_dgram) } always_inline int -vppcom_session_write_inline (vcl_worker_t * wrk, vcl_session_t * s, void *buf, - size_t n, u8 is_flush, u8 is_dgram) +vppcom_session_write_inline (vcl_worker_t *wrk, vcl_session_t *s, void *buf, + size_t n, u16 gso_size, u8 is_flush, u8 is_dgram) { int n_write, is_nonblocking; session_evt_type_t et; @@ -2230,9 +2293,9 @@ vppcom_session_write_inline (vcl_worker_t * wrk, vcl_session_t * s, void *buf, et = SESSION_IO_EVT_TX_FLUSH; if (is_dgram) - n_write = app_send_dgram_raw (tx_fifo, &s->transport, - s->vpp_evt_q, buf, n, et, - 0 /* do_evt */ , SVM_Q_WAIT); + n_write = + app_send_dgram_raw_gso (tx_fifo, &s->transport, s->vpp_evt_q, buf, n, + gso_size, et, 0 /* do_evt */, SVM_Q_WAIT); else n_write = app_send_stream_raw (tx_fifo, s->vpp_evt_q, buf, n, et, 0 /* do_evt */ , SVM_Q_WAIT); @@ -2261,8 +2324,8 @@ vppcom_session_write (uint32_t session_handle, void *buf, size_t n) if (PREDICT_FALSE (!s)) return VPPCOM_EBADFD; - return vppcom_session_write_inline (wrk, s, buf, n, - 0 /* is_flush */ , s->is_dgram ? 1 : 0); + return vppcom_session_write_inline (wrk, s, buf, n, 0, 0 /* is_flush */, + s->is_dgram ? 1 : 0); } int @@ -2275,8 +2338,8 @@ vppcom_session_write_msg (uint32_t session_handle, void *buf, size_t n) if (PREDICT_FALSE (!s)) return VPPCOM_EBADFD; - return vppcom_session_write_inline (wrk, s, buf, n, - 1 /* is_flush */ , s->is_dgram ? 1 : 0); + return vppcom_session_write_inline (wrk, s, buf, n, 0, 1 /* is_flush */, + s->is_dgram ? 1 : 0); } #define vcl_fifo_rx_evt_valid_or_break(_s) \ @@ -3035,6 +3098,10 @@ vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e, /* Generate EPOLLOUT because there's no connected event */ if (!(EPOLLOUT & session_events)) break; + /* We didn't have a fifo when the event was added */ + svm_fifo_add_want_deq_ntf ( + (vcl_session_is_ct (s) ? s->ct_tx_fifo : s->tx_fifo), + SVM_FIFO_WANT_DEQ_NOTIF_IF_FULL); add_event = 1; events[*num_ev].events = EPOLLOUT; session_evt_data = s->vep.ev.data.u64; @@ -3101,7 +3168,16 @@ vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e, } session_events = s->vep.ev.events; add_event = 1; - events[*num_ev].events = EPOLLHUP | EPOLLRDHUP; + events[*num_ev].events = EPOLLERR | EPOLLHUP; + if ((EPOLLRDHUP & session_events) && + (s->flags & VCL_SESSION_F_RD_SHUTDOWN)) + { + events[*num_ev].events |= EPOLLRDHUP; + } + if ((EPOLLIN & session_events) && (s->flags & VCL_SESSION_F_RD_SHUTDOWN)) + { + events[*num_ev].events |= EPOLLIN; + } session_evt_data = s->vep.ev.data.u64; break; case SESSION_CTRL_EVT_UNLISTEN_REPLY: @@ -3936,7 +4012,6 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op, VDBG (2, "VPPCOM_ATTR_GET_TCP_USER_MSS: %d, buflen %d", *(int *) buffer, *buflen); break; - case VPPCOM_ATTR_SET_TCP_USER_MSS: if (!(buffer && buflen && (*buflen == sizeof (u32)))) { @@ -4079,6 +4154,7 @@ vppcom_session_sendto (uint32_t session_handle, void *buffer, { vcl_worker_t *wrk = vcl_worker_get_current (); vcl_session_t *s; + u16 gso_size = 0; s = vcl_session_get_w_handle (wrk, session_handle); if (PREDICT_FALSE (!s)) @@ -4093,6 +4169,12 @@ vppcom_session_sendto (uint32_t session_handle, void *buffer, s->transport.rmt_port = ep->port; vcl_ip_copy_from_ep (&s->transport.rmt_ip, ep); + vppcom_endpt_tlv_t *p_app_data = &ep->app_data; + + if (p_app_data && (p_app_data->data_type == VCL_UDP_SEGMENT)) + { + gso_size = p_app_data->value; + } /* Session not connected/bound in vpp. Create it by 'connecting' it */ if (PREDICT_FALSE (s->session_state == VCL_STATE_CLOSED)) { @@ -4116,7 +4198,7 @@ vppcom_session_sendto (uint32_t session_handle, void *buffer, VDBG (2, "handling flags 0x%u (%d) not implemented yet.", flags, flags); } - return (vppcom_session_write_inline (wrk, s, buffer, buflen, 1, + return (vppcom_session_write_inline (wrk, s, buffer, buflen, gso_size, 1, s->is_dgram ? 1 : 0)); } @@ -4405,6 +4487,10 @@ vppcom_retval_str (int retval) st = "VPPCOM_ETIMEDOUT"; break; + case VPPCOM_EADDRINUSE: + st = "VPPCOM_EADDRINUSE"; + break; + default: st = "UNKNOWN_STATE"; break; @@ -4431,6 +4517,43 @@ vppcom_del_cert_key_pair (uint32_t ckpair_index) return vcl_bapi_del_cert_key_pair (ckpair_index); } +int +vppcom_session_get_error (uint32_t session_handle) +{ + vcl_worker_t *wrk = vcl_worker_get_current (); + vcl_session_t *session = 0; + + session = vcl_session_get_w_handle (wrk, session_handle); + if (!session) + return VPPCOM_EBADFD; + + if (PREDICT_FALSE (session->flags & VCL_SESSION_F_IS_VEP)) + { + VWRN ("epoll session %u! will not have connect", session->session_index); + return VPPCOM_EBADFD; + } + + if (session->vpp_error == SESSION_E_PORTINUSE) + return VPPCOM_EADDRINUSE; + else if (session->vpp_error == SESSION_E_REFUSED) + return VPPCOM_ECONNREFUSED; + else if (session->vpp_error != SESSION_E_NONE) + return VPPCOM_EFAULT; + else + return VPPCOM_OK; +} + +int +vppcom_worker_is_detached (void) +{ + vcl_worker_t *wrk = vcl_worker_get_current (); + + if (!vcm->cfg.use_mq_eventfd) + return VPPCOM_ENOTSUP; + + return wrk->api_client_handle == ~0; +} + /* * fd.io coding-style-patch-verification: ON *