X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=blobdiff_plain;f=src%2Fvcl%2Fvppcom.c;h=f20167226e8c23a9b68475cf3da620090a2882aa;hp=3f12b86df42950aa2b392fea0f77b2d7540d3cff;hb=c1f5a43;hpb=58c101adf057fc118ccca6e5cb9d02b43499e56a diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index 3f12b86df42..f20167226e8 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -311,7 +311,8 @@ vcl_session_accepted_handler (vcl_worker_t * wrk, session_accepted_msg_t * mp) session->session_state = STATE_ACCEPT; session->transport.rmt_port = mp->port; session->transport.is_ip4 = mp->is_ip4; - clib_memcpy (&session->transport.rmt_ip, mp->ip, sizeof (ip46_address_t)); + clib_memcpy_fast (&session->transport.rmt_ip, mp->ip, + sizeof (ip46_address_t)); vcl_session_table_add_vpp_handle (wrk, mp->handle, session->session_index); session->transport.lcl_port = listen_session->transport.lcl_port; @@ -389,8 +390,8 @@ vcl_session_connected_handler (vcl_worker_t * wrk, session->tx_fifo = tx_fifo; session->vpp_handle = mp->handle; session->transport.is_ip4 = mp->is_ip4; - clib_memcpy (&session->transport.lcl_ip, mp->lcl_ip, - sizeof (session->transport.lcl_ip)); + clib_memcpy_fast (&session->transport.lcl_ip, mp->lcl_ip, + sizeof (session->transport.lcl_ip)); session->transport.lcl_port = mp->lcl_port; session->session_state = STATE_CONNECT; @@ -454,8 +455,8 @@ vcl_session_bound_handler (vcl_worker_t * wrk, session_bound_msg_t * mp) session->vpp_handle = mp->handle; session->transport.is_ip4 = mp->lcl_is_ip4; - clib_memcpy (&session->transport.lcl_ip, mp->lcl_ip, - sizeof (ip46_address_t)); + clib_memcpy_fast (&session->transport.lcl_ip, mp->lcl_ip, + sizeof (ip46_address_t)); session->transport.lcl_port = mp->lcl_port; vcl_session_table_add_listener (wrk, mp->handle, sid); session->session_state = STATE_LISTEN; @@ -687,6 +688,52 @@ vppcom_session_disconnect (u32 session_handle) return VPPCOM_OK; } +static void +vcl_cleanup_bapi (void) +{ + api_main_t *am = &api_main; + + am->my_client_index = ~0; + am->my_registration = 0; + am->vl_input_queue = 0; + am->msg_index_by_name_and_crc = 0; + + vl_client_api_unmap (); +} + +void +vcl_app_fork_child_handler (void) +{ + u8 *child_name; + int rv; + + vcm->current_pid = getpid (); + vcl_set_worker_index (0); + + VDBG (0, "initializing forked child"); + child_name = format (0, "%v-child-%u%c", vcm->app_name, getpid (), 0); + + vcl_cleanup_bapi (); + vppcom_api_hookup (); + vcm->app_state = STATE_APP_START; + rv = vppcom_connect_to_vpp ((char *) child_name); + vec_free (child_name); + if (rv) + { + VERR ("couldn't connect to VPP!"); + return; + } + + vcm->app_state = STATE_APP_ADDING_WORKER; + vcl_send_app_worker_add_del (1 /* is_add */ ); + if (vcl_wait_for_app_state_change (STATE_APP_READY)) + { + VERR ("failed to add worker to vpp"); + return; + } + VDBG (0, "forked child main worker initialized"); +} + /* * VPPCOM Public API functions */ @@ -703,12 +750,15 @@ vppcom_app_create (char *app_name) vcl_cfg = &vcm->cfg; vcm->main_cpu = pthread_self (); + vcm->main_pid = vcm->current_pid = getpid (); + vcm->app_name = format (0, "%s", app_name); vppcom_init_error_string_table (); svm_fifo_segment_main_init (vcl_cfg->segment_baseva, 20 /* timeout in secs */ ); pool_init_fixed (vcm->workers, vcl_cfg->max_workers); clib_spinlock_init (&vcm->workers_lock); vcl_worker_alloc_and_init (); + pthread_atfork (NULL, NULL, vcl_app_fork_child_handler); } if (vcm->my_client_index == ~0) @@ -720,31 +770,27 @@ vppcom_app_create (char *app_name) rv = vppcom_connect_to_vpp (app_name); if (rv) { - clib_warning ("VCL<%d>: ERROR: couldn't connect to VPP!", - getpid ()); + VERR ("couldn't connect to VPP!"); return rv; } - - VDBG (0, "VCL<%d>: sending session enable", getpid ()); + VDBG (0, "sending session enable"); rv = vppcom_app_session_enable (); if (rv) { - clib_warning ("VCL<%d>: ERROR: vppcom_app_session_enable() " - "failed!", getpid ()); + VERR ("vppcom_app_session_enable() failed!"); return rv; } - VDBG (0, "VCL<%d>: sending app attach", getpid ()); + VDBG (0, "sending app attach"); rv = vppcom_app_attach (); if (rv) { - clib_warning ("VCL<%d>: ERROR: vppcom_app_attach() failed!", - getpid ()); + VERR ("vppcom_app_attach() failed!"); return rv; } - VDBG (0, "VCL<%d>: app_name '%s', my_client_index %d (0x%x)", - getpid (), app_name, vcm->my_client_index, vcm->my_client_index); + VDBG (0, "app_name '%s', my_client_index %d (0x%x)", + app_name, vcm->my_client_index, vcm->my_client_index); } return VPPCOM_OK; @@ -759,8 +805,8 @@ vppcom_app_destroy (void) if (vcm->my_client_index == ~0) return; - VDBG (0, "VCL<%d>: detaching from VPP, my_client_index %d (0x%x)", - getpid (), vcm->my_client_index, vcm->my_client_index); + VDBG (0, "detaching from VPP, my_client_index %d (0x%x)", + vcm->my_client_index, vcm->my_client_index); vcl_evt (VCL_EVT_DETACH, vcm); vppcom_app_send_detach (); @@ -769,11 +815,12 @@ vppcom_app_destroy (void) rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED); vcm->cfg.app_timeout = orig_app_timeout; if (PREDICT_FALSE (rv)) - VDBG (0, "VCL<%d>: application detach timed out! returning %d (%s)", - getpid (), rv, vppcom_retval_str (rv)); + VDBG (0, "application detach timed out! returning %d (%s)", + rv, vppcom_retval_str (rv)); vcl_elog_stop (vcm); vl_client_disconnect_from_vlib (); + vec_free (vcm->app_name); vcm->my_client_index = ~0; vcm->app_state = STATE_APP_START; } @@ -797,7 +844,7 @@ vppcom_session_create (u8 proto, u8 is_nonblocking) vcl_evt (VCL_EVT_CREATE, session, session_type, session->session_state, is_nonblocking, session_index); - VDBG (0, "VCL<%d>: sid %u", getpid (), session->session_index); + VDBG (0, "created sid %u", session->session_index); return vcl_session_handle (session); } @@ -942,11 +989,11 @@ vppcom_session_bind (uint32_t session_handle, vppcom_endpt_t * ep) session->transport.is_ip4 = ep->is_ip4; if (ep->is_ip4) - clib_memcpy (&session->transport.lcl_ip.ip4, ep->ip, - sizeof (ip4_address_t)); + clib_memcpy_fast (&session->transport.lcl_ip.ip4, ep->ip, + sizeof (ip4_address_t)); else - clib_memcpy (&session->transport.lcl_ip.ip6, ep->ip, - sizeof (ip6_address_t)); + clib_memcpy_fast (&session->transport.lcl_ip.ip6, ep->ip, + sizeof (ip6_address_t)); session->transport.lcl_port = ep->port; VDBG (0, "VCL<%d>: sid %u: binding to local %s address %U port %u, " @@ -1091,7 +1138,7 @@ vppcom_session_accept (uint32_t listen_session_handle, vppcom_endpt_t * ep, svm_msg_q_free_msg (wrk->app_event_queue, &msg); continue; } - clib_memcpy (&accepted_msg, e->data, sizeof (accepted_msg)); + clib_memcpy_fast (&accepted_msg, e->data, sizeof (accepted_msg)); svm_msg_q_free_msg (wrk->app_event_queue, &msg); break; } @@ -1118,11 +1165,11 @@ handle: ep->is_ip4 = client_session->transport.is_ip4; ep->port = client_session->transport.rmt_port; if (client_session->transport.is_ip4) - clib_memcpy (ep->ip, &client_session->transport.rmt_ip.ip4, - sizeof (ip4_address_t)); + clib_memcpy_fast (ep->ip, &client_session->transport.rmt_ip.ip4, + sizeof (ip4_address_t)); else - clib_memcpy (ep->ip, &client_session->transport.rmt_ip.ip6, - sizeof (ip6_address_t)); + clib_memcpy_fast (ep->ip, &client_session->transport.rmt_ip.ip6, + sizeof (ip6_address_t)); } if (accepted_msg.server_event_queue_address) @@ -1191,11 +1238,11 @@ vppcom_session_connect (uint32_t session_handle, vppcom_endpt_t * server_ep) session->transport.is_ip4 = server_ep->is_ip4; if (session->transport.is_ip4) - clib_memcpy (&session->transport.rmt_ip.ip4, server_ep->ip, - sizeof (ip4_address_t)); + clib_memcpy_fast (&session->transport.rmt_ip.ip4, server_ep->ip, + sizeof (ip4_address_t)); else - clib_memcpy (&session->transport.rmt_ip.ip6, server_ep->ip, - sizeof (ip6_address_t)); + clib_memcpy_fast (&session->transport.rmt_ip.ip6, server_ep->ip, + sizeof (ip6_address_t)); session->transport.rmt_port = server_ep->port; VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: connecting to server %s %U " @@ -1293,13 +1340,14 @@ vppcom_session_read_internal (uint32_t session_handle, void *buf, int n, is_ct = vcl_session_is_ct (s); mq = is_ct ? s->our_evt_q : wrk->app_event_queue; rx_fifo = s->rx_fifo; + s->has_rx_evt = 0; if (svm_fifo_is_empty (rx_fifo)) { if (is_nonblocking) { svm_fifo_unset_event (rx_fifo); - return VPPCOM_OK; + return VPPCOM_EWOULDBLOCK; } while (svm_fifo_is_empty (rx_fifo)) { @@ -1385,13 +1433,14 @@ vppcom_session_read_segments (uint32_t session_handle, is_ct = vcl_session_is_ct (s); mq = is_ct ? s->our_evt_q : wrk->app_event_queue; rx_fifo = s->rx_fifo; + s->has_rx_evt = 0; if (svm_fifo_is_empty (rx_fifo)) { if (is_nonblocking) { svm_fifo_unset_event (rx_fifo); - return VPPCOM_OK; + return VPPCOM_EWOULDBLOCK; } while (svm_fifo_is_empty (rx_fifo)) { @@ -1479,11 +1528,11 @@ int vppcom_data_segment_copy (void *buf, vppcom_data_segments_t ds, u32 max_bytes) { u32 first_copy = clib_min (ds[0].len, max_bytes); - clib_memcpy (buf, ds[0].data, first_copy); + clib_memcpy_fast (buf, ds[0].data, first_copy); if (first_copy < max_bytes) { - clib_memcpy (buf + first_copy, ds[1].data, - clib_min (ds[1].len, max_bytes - first_copy)); + clib_memcpy_fast (buf + first_copy, ds[1].data, + clib_min (ds[1].len, max_bytes - first_copy)); } return 0; } @@ -1551,7 +1600,8 @@ vppcom_session_write (uint32_t session_handle, void *buf, size_t n) { svm_fifo_set_want_tx_evt (tx_fifo, 1); svm_msg_q_lock (mq); - svm_msg_q_wait (mq); + if (svm_msg_q_is_empty (mq)) + svm_msg_q_wait (mq); svm_msg_q_sub_w_lock (mq, &msg); e = svm_msg_q_msg_data (mq, &msg); @@ -1905,23 +1955,23 @@ vppcom_select (unsigned long n_bits, unsigned long *read_map, if (n_bits && read_map) { clib_bitmap_validate (wrk->rd_bitmap, minbits); - clib_memcpy (wrk->rd_bitmap, read_map, - vec_len (wrk->rd_bitmap) * sizeof (clib_bitmap_t)); + clib_memcpy_fast (wrk->rd_bitmap, read_map, + vec_len (wrk->rd_bitmap) * sizeof (clib_bitmap_t)); memset (read_map, 0, vec_len (wrk->rd_bitmap) * sizeof (clib_bitmap_t)); } if (n_bits && write_map) { clib_bitmap_validate (wrk->wr_bitmap, minbits); - clib_memcpy (wrk->wr_bitmap, write_map, - vec_len (wrk->wr_bitmap) * sizeof (clib_bitmap_t)); + clib_memcpy_fast (wrk->wr_bitmap, write_map, + vec_len (wrk->wr_bitmap) * sizeof (clib_bitmap_t)); memset (write_map, 0, vec_len (wrk->wr_bitmap) * sizeof (clib_bitmap_t)); } if (n_bits && except_map) { clib_bitmap_validate (wrk->ex_bitmap, minbits); - clib_memcpy (wrk->ex_bitmap, except_map, - vec_len (wrk->ex_bitmap) * sizeof (clib_bitmap_t)); + clib_memcpy_fast (wrk->ex_bitmap, except_map, + vec_len (wrk->ex_bitmap) * sizeof (clib_bitmap_t)); memset (except_map, 0, vec_len (wrk->ex_bitmap) * sizeof (clib_bitmap_t)); } @@ -2303,11 +2353,12 @@ vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e, sid = e->fifo->client_session_index; session = vcl_session_get (wrk, sid); session_events = session->vep.ev.events; - if (!(EPOLLIN & session->vep.ev.events)) + if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt) break; add_event = 1; events[*num_ev].events |= EPOLLIN; session_evt_data = session->vep.ev.data.u64; + session->has_rx_evt = 1; break; case FIFO_EVENT_APP_TX: sid = e->fifo->client_session_index; @@ -2324,11 +2375,12 @@ vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e, session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 0); sid = session->session_index; session_events = session->vep.ev.events; - if (!(EPOLLIN & session->vep.ev.events)) + if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt) break; add_event = 1; events[*num_ev].events |= EPOLLIN; session_evt_data = session->vep.ev.data.u64; + session->has_rx_evt = 1; break; case SESSION_IO_EVT_CT_RX: session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 1); @@ -2452,15 +2504,13 @@ handle_dequeued: { msg = vec_elt_at_index (wrk->mq_msg_vector, i); e = svm_msg_q_msg_data (mq, msg); - vcl_epoll_wait_handle_mq_event (wrk, e, events, num_ev); + if (*num_ev < maxevents) + vcl_epoll_wait_handle_mq_event (wrk, e, events, num_ev); + else + vec_add1 (wrk->unhandled_evts_vector, *e); svm_msg_q_free_msg (mq, msg); - if (*num_ev == maxevents) - { - i += 1; - break; - } } - vec_delete (wrk->mq_msg_vector, i, 0); + vec_reset_length (wrk->mq_msg_vector); return *num_ev; } @@ -2508,6 +2558,7 @@ vppcom_epoll_wait_eventfd (vcl_worker_t * wrk, struct epoll_event *events, u64 buf; vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns)); +again: n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events, vec_len (wrk->mq_events), wait_for_time); for (i = 0; i < n_mq_evts; i++) @@ -2516,6 +2567,8 @@ vppcom_epoll_wait_eventfd (vcl_worker_t * wrk, struct epoll_event *events, n_read = read (mqc->mq_fd, &buf, sizeof (buf)); vcl_epoll_wait_handle_mq (wrk, mqc->mq, events, maxevents, 0, &n_evts); } + if (!n_evts && n_mq_evts > 0) + goto again; return (int) n_evts; } @@ -2640,11 +2693,11 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op, ep->is_ip4 = session->transport.is_ip4; ep->port = session->transport.rmt_port; if (session->transport.is_ip4) - clib_memcpy (ep->ip, &session->transport.rmt_ip.ip4, - sizeof (ip4_address_t)); + clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4, + sizeof (ip4_address_t)); else - clib_memcpy (ep->ip, &session->transport.rmt_ip.ip6, - sizeof (ip6_address_t)); + clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6, + sizeof (ip6_address_t)); *buflen = sizeof (*ep); VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_PEER_ADDR: sid %u, is_ip4 = %u, " "addr = %U, port %u", getpid (), @@ -2664,11 +2717,11 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op, ep->is_ip4 = session->transport.is_ip4; ep->port = session->transport.lcl_port; if (session->transport.is_ip4) - clib_memcpy (ep->ip, &session->transport.lcl_ip.ip4, - sizeof (ip4_address_t)); + clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip4, + sizeof (ip4_address_t)); else - clib_memcpy (ep->ip, &session->transport.lcl_ip.ip6, - sizeof (ip6_address_t)); + clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip6, + sizeof (ip6_address_t)); *buflen = sizeof (*ep); VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_LCL_ADDR: sid %u, is_ip4 = %u," " addr = %U port %d", getpid (), @@ -3140,11 +3193,11 @@ vppcom_session_recvfrom (uint32_t session_handle, void *buffer, if (ep) { if (session->transport.is_ip4) - clib_memcpy (ep->ip, &session->transport.rmt_ip.ip4, - sizeof (ip4_address_t)); + clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4, + sizeof (ip4_address_t)); else - clib_memcpy (ep->ip, &session->transport.rmt_ip.ip6, - sizeof (ip6_address_t)); + clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6, + sizeof (ip6_address_t)); } return rv; @@ -3179,6 +3232,8 @@ vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time) vcl_worker_t *wrk = vcl_worker_get_current (); f64 timeout = clib_time_now (&wrk->clib_time) + wait_for_time; u32 i, keep_trying = 1; + svm_msg_q_msg_t msg; + session_event_t *e; int rv, num_ev = 0; VDBG (3, "VCL<%d>: vp %p, nsids %u, wait_for_time %f", @@ -3191,23 +3246,33 @@ vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time) { vcl_session_t *session; - for (i = 0; i < n_sids; i++) + /* Dequeue all events and drop all unhandled io events */ + while (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_NOWAIT, 0) == 0) { - ASSERT (vp[i].revents); + e = svm_msg_q_msg_data (wrk->app_event_queue, &msg); + vcl_handle_mq_event (wrk, e); + svm_msg_q_free_msg (wrk->app_event_queue, &msg); + } + vec_reset_length (wrk->unhandled_evts_vector); + for (i = 0; i < n_sids; i++) + { session = vcl_session_get (wrk, vp[i].sid); if (!session) - continue; + { + vp[i].revents = POLLHUP; + num_ev++; + continue; + } - if (*vp[i].revents) - *vp[i].revents = 0; + vp[i].revents = 0; if (POLLIN & vp[i].events) { rv = vppcom_session_read_ready (session); if (rv > 0) { - *vp[i].revents |= POLLIN; + vp[i].revents |= POLLIN; num_ev++; } else if (rv < 0) @@ -3215,11 +3280,11 @@ vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time) switch (rv) { case VPPCOM_ECONNRESET: - *vp[i].revents = POLLHUP; + vp[i].revents = POLLHUP; break; default: - *vp[i].revents = POLLERR; + vp[i].revents = POLLERR; break; } num_ev++; @@ -3231,7 +3296,7 @@ vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time) rv = vppcom_session_write_ready (session); if (rv > 0) { - *vp[i].revents |= POLLOUT; + vp[i].revents |= POLLOUT; num_ev++; } else if (rv < 0) @@ -3239,11 +3304,11 @@ vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time) switch (rv) { case VPPCOM_ECONNRESET: - *vp[i].revents = POLLHUP; + vp[i].revents = POLLHUP; break; default: - *vp[i].revents = POLLERR; + vp[i].revents = POLLERR; break; } num_ev++; @@ -3252,7 +3317,7 @@ vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time) if (0) // Note "done:" label used by VCL_SESSION_LOCK_AND_GET() { - *vp[i].revents = POLLNVAL; + vp[i].revents = POLLNVAL; num_ev++; } } @@ -3268,7 +3333,7 @@ vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time) { clib_warning ("VCL<%d>: vp[%d].sid %d (0x%x), .events 0x%x, " ".revents 0x%x", getpid (), i, vp[i].sid, vp[i].sid, - vp[i].events, *vp[i].revents); + vp[i].events, vp[i].revents); } } return num_ev;