X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvcl%2Fvppcom.c;h=34b663b98318757a5c8b716043f5a3409c229c9a;hb=d85de68ec3f72888099172fffd45a90a43018155;hp=f20167226e8c23a9b68475cf3da620090a2882aa;hpb=c1f5a4336036e3f2d1f6746f39ce610312254272;p=vpp.git diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index f20167226e8..34b663b9831 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -22,46 +22,26 @@ __thread uword __vcl_worker_index = ~0; -static u8 not_ready; -void -sigsegv_signal (int signum) +static int +vcl_wait_for_segment (u64 segment_handle) { - not_ready = 1; -} + vcl_worker_t *wrk = vcl_worker_get_current (); + u32 wait_for_seconds = 10, segment_index; + f64 timeout; -static void -vcl_wait_for_memory (void *mem) -{ - u8 __clib_unused test; - if (vcm->mounting_segment) - { - while (vcm->mounting_segment) - ; - return; - } - if (1 || vcm->debug) - { - usleep (1e5); - return; - } - if (signal (SIGSEGV, sigsegv_signal)) - { - perror ("signal()"); - return; - } - not_ready = 0; + if (segment_handle == VCL_INVALID_SEGMENT_HANDLE) + return 1; -again: - test = *(u8 *) mem; - if (not_ready) + timeout = clib_time_now (&wrk->clib_time) + wait_for_seconds; + while (clib_time_now (&wrk->clib_time) < timeout) { - not_ready = 0; - usleep (1); - goto again; + segment_index = vcl_segment_table_lookup (segment_handle); + if (segment_index != VCL_INVALID_SEGMENT_INDEX) + return 0; + usleep (10); } - - signal (SIGSEGV, SIG_DFL); + return 1; } const char * @@ -281,7 +261,12 @@ vcl_session_accepted_handler (vcl_worker_t * wrk, session_accepted_msg_t * mp) svm_msg_q_t *); session->our_evt_q = uword_to_pointer (mp->server_event_queue_address, svm_msg_q_t *); - vcl_wait_for_memory (session->vpp_evt_q); + if (vcl_wait_for_segment (mp->segment_handle)) + { + clib_warning ("segment for session %u couldn't be mounted!", + session->session_index); + return VCL_INVALID_SESSION_INDEX; + } rx_fifo->master_session_index = session->session_index; tx_fifo->master_session_index = session->session_index; rx_fifo->master_thread_index = vcl_get_worker_index (); @@ -360,7 +345,13 @@ vcl_session_connected_handler (vcl_worker_t * wrk, rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *); tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *); - vcl_wait_for_memory (rx_fifo); + if (vcl_wait_for_segment (mp->segment_handle)) + { + clib_warning ("segment for session %u couldn't be mounted!", + session->session_index); + return VCL_INVALID_SESSION_INDEX; + } + rx_fifo->client_session_index = session_index; tx_fifo->client_session_index = session_index; rx_fifo->client_thread_index = vcl_get_worker_index (); @@ -423,7 +414,7 @@ vcl_session_reset_handler (vcl_worker_t * wrk, session->session_state = STATE_CLOSE_ON_EMPTY; VDBG (0, "reset handle 0x%llx, sid %u ", reset_msg->handle, sid); vcl_send_session_reset_reply (vcl_session_vpp_evt_q (wrk, session), - vcm->my_client_index, reset_msg->handle, 0); + wrk->my_client_index, reset_msg->handle, 0); return sid; } @@ -436,8 +427,8 @@ vcl_session_bound_handler (vcl_worker_t * wrk, session_bound_msg_t * mp) session = vcl_session_get (wrk, sid); if (mp->retval) { - VDBG (0, "VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: bind failed: %U", - getpid (), mp->handle, sid, format_api_error, ntohl (mp->retval)); + VERR ("vpp handle 0x%llx, sid %u: bind failed: %U", mp->handle, sid, + format_api_error, mp->retval); if (session) { session->session_state = STATE_FAILED; @@ -673,7 +664,7 @@ vppcom_session_disconnect (u32 session_handle) if (state & STATE_CLOSE_ON_EMPTY) { vpp_evt_q = vcl_session_vpp_evt_q (wrk, session); - vcl_send_session_disconnected_reply (vpp_evt_q, vcm->my_client_index, + vcl_send_session_disconnected_reply (vpp_evt_q, wrk->my_client_index, vpp_handle, 0); VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending disconnect " "REPLY...", getpid (), vpp_handle, session_handle); @@ -691,12 +682,14 @@ vppcom_session_disconnect (u32 session_handle) static void vcl_cleanup_bapi (void) { + socket_client_main_t *scm = &socket_client_main; 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; + scm->socket_fd = 0; vl_client_api_unmap (); } @@ -705,14 +698,22 @@ void vcl_app_fork_child_handler (void) { u8 *child_name; - int rv; - - vcm->current_pid = getpid (); - vcl_set_worker_index (0); + int rv, parent_wrk; VDBG (0, "initializing forked child"); - child_name = format (0, "%v-child-%u%c", vcm->app_name, getpid (), 0); + /* + * Allocate worker + */ + parent_wrk = vcl_get_worker_index (); + vcl_set_worker_index (~0); + if (!vcl_worker_alloc_and_init ()) + VERR ("couldn't allocate new worker"); + + /* + * Attach to binary api + */ + 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; @@ -724,14 +725,23 @@ vcl_app_fork_child_handler (void) 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; - } + /* + * Register worker with vpp and share sessions + */ + vcl_worker_register_with_vpp (); + vcl_worker_share_sessions (parent_wrk); + VDBG (0, "forked child main worker initialized"); + vcm->forking = 0; +} + +void +vcl_app_fork_parent_handler (void) +{ + vcm->forking = 1; + + while (vcm->forking) + ; } /* @@ -743,56 +753,60 @@ vppcom_app_create (char *app_name) vppcom_cfg_t *vcl_cfg = &vcm->cfg; int rv; - if (!vcm->is_init) + if (vcm->is_init) { - vcm->is_init = 1; - vppcom_cfg (&vcm->cfg); - 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); + clib_warning ("already initialized"); + return -1; } - if (vcm->my_client_index == ~0) - { - /* API hookup and connect to VPP */ - vppcom_api_hookup (); - vcl_elog_init (vcm); - vcm->app_state = STATE_APP_START; - rv = vppcom_connect_to_vpp (app_name); - if (rv) - { - VERR ("couldn't connect to VPP!"); - return rv; - } - VDBG (0, "sending session enable"); - rv = vppcom_app_session_enable (); - if (rv) - { - VERR ("vppcom_app_session_enable() failed!"); - return rv; - } + vcm->is_init = 1; + vppcom_cfg (&vcm->cfg); + vcl_cfg = &vcm->cfg; - VDBG (0, "sending app attach"); - rv = vppcom_app_attach (); - if (rv) - { - VERR ("vppcom_app_attach() failed!"); - return rv; - } + vcm->main_cpu = pthread_self (); + vcm->main_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_alloc (vcm->workers, vcl_cfg->max_workers); + clib_spinlock_init (&vcm->workers_lock); + clib_rwlock_init (&vcm->segment_table_lock); + pthread_atfork (NULL, vcl_app_fork_parent_handler, + vcl_app_fork_child_handler); + + /* Allocate default worker */ + vcl_worker_alloc_and_init (); + + /* API hookup and connect to VPP */ + vppcom_api_hookup (); + vcl_elog_init (vcm); + vcm->app_state = STATE_APP_START; + rv = vppcom_connect_to_vpp (app_name); + if (rv) + { + VERR ("couldn't connect to VPP!"); + return rv; + } + VDBG (0, "sending session enable"); + rv = vppcom_app_session_enable (); + if (rv) + { + VERR ("vppcom_app_session_enable() failed!"); + return rv; + } - VDBG (0, "app_name '%s', my_client_index %d (0x%x)", - app_name, vcm->my_client_index, vcm->my_client_index); + VDBG (0, "sending app attach"); + rv = vppcom_app_attach (); + if (rv) + { + VERR ("vppcom_app_attach() failed!"); + return rv; } + VDBG (0, "app_name '%s', my_client_index %d (0x%x)", app_name, + vcm->workers[0].my_client_index, vcm->workers[0].my_client_index); + return VPPCOM_OK; } @@ -802,27 +816,27 @@ vppcom_app_destroy (void) int rv; f64 orig_app_timeout; - if (vcm->my_client_index == ~0) - return; - - 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 (); - orig_app_timeout = vcm->cfg.app_timeout; - vcm->cfg.app_timeout = 2.0; - rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED); - vcm->cfg.app_timeout = orig_app_timeout; - if (PREDICT_FALSE (rv)) - VDBG (0, "application detach timed out! returning %d (%s)", - rv, vppcom_retval_str (rv)); + if (vec_len (vcm->workers) == 1) + { + vppcom_app_send_detach (); + orig_app_timeout = vcm->cfg.app_timeout; + vcm->cfg.app_timeout = 2.0; + rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED); + vcm->cfg.app_timeout = orig_app_timeout; + if (PREDICT_FALSE (rv)) + VDBG (0, "application detach timed out! returning %d (%s)", rv, + vppcom_retval_str (rv)); + } + else + { + vcl_worker_cleanup (); + } 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; } int @@ -853,8 +867,8 @@ int vppcom_session_close (uint32_t session_handle) { vcl_worker_t *wrk = vcl_worker_get_current (); + u8 is_vep, do_disconnect = 1; vcl_session_t *session = 0; - u8 is_vep, is_vep_session; session_state_t state; u32 next_sh, vep_sh; int rv = VPPCOM_OK; @@ -864,24 +878,17 @@ vppcom_session_close (uint32_t session_handle) if (!session) return VPPCOM_EBADFD; + if (session->shared_index != ~0) + do_disconnect = vcl_worker_unshare_session (wrk, session); + is_vep = session->is_vep; - is_vep_session = session->is_vep_session; next_sh = session->vep.next_sh; vep_sh = session->vep.vep_sh; state = session->session_state; vpp_handle = session->vpp_handle; - if (VPPCOM_DEBUG > 0) - { - if (is_vep) - clib_warning ("VCL<%d>: vep_idx %u / sid %u: " - "closing epoll session...", - getpid (), session_handle, session_handle); - else - clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %d: " - "closing session...", - getpid (), vpp_handle, session_handle); - } + VDBG (0, "Closing session handle %u vpp handle %u", session_handle, + vpp_handle); if (is_vep) { @@ -889,34 +896,34 @@ vppcom_session_close (uint32_t session_handle) { rv = vppcom_epoll_ctl (session_handle, EPOLL_CTL_DEL, next_sh, 0); if (PREDICT_FALSE (rv < 0)) - VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL " - "vep_idx %u failed! rv %d (%s)", - getpid (), vpp_handle, next_sh, vep_sh, - rv, vppcom_retval_str (rv)); + VDBG (0, "vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL vep_idx %u" + " failed! rv %d (%s)", vpp_handle, next_sh, vep_sh, rv, + vppcom_retval_str (rv)); next_sh = session->vep.next_sh; } } else { - if (is_vep_session) + if (session->is_vep_session) { rv = vppcom_epoll_ctl (vep_sh, EPOLL_CTL_DEL, session_handle, 0); if (rv < 0) - VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL " - "vep_idx %u failed! rv %d (%s)", - getpid (), vpp_handle, session_handle, - vep_sh, rv, vppcom_retval_str (rv)); + VDBG (0, "vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL vep_idx %u " + "failed! rv %d (%s)", vpp_handle, session_handle, vep_sh, + rv, vppcom_retval_str (rv)); } + if (!do_disconnect) + goto cleanup; + if (state & STATE_LISTEN) { rv = vppcom_session_unbind (session_handle); if (PREDICT_FALSE (rv < 0)) - VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: listener unbind " - "failed! rv %d (%s)", - getpid (), vpp_handle, session_handle, - rv, vppcom_retval_str (rv)); + VDBG (0, "vpp handle 0x%llx, sid %u: listener unbind failed! " + "rv %d (%s)", vpp_handle, session_handle, rv, + vppcom_retval_str (rv)); } else if (state & STATE_OPEN) { @@ -929,6 +936,8 @@ vppcom_session_close (uint32_t session_handle) } } +cleanup: + if (vcl_session_is_ct (session)) { vcl_cut_through_registration_t *ctr; @@ -952,15 +961,8 @@ vppcom_session_close (uint32_t session_handle) } vcl_session_free (wrk, session); - if (VPPCOM_DEBUG > 0) - { - if (is_vep) - clib_warning ("VCL<%d>: vep_idx %u / sid %u: epoll session removed.", - getpid (), session_handle, session_handle); - else - clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: session removed.", - getpid (), vpp_handle, session_handle); - } + VDBG (0, "session handle %u vpp handle %u removed", session_handle, + vpp_handle); vcl_evt (VCL_EVT_CLOSE, session, rv); @@ -1986,9 +1988,9 @@ vppcom_select (unsigned long n_bits, unsigned long *read_map, clib_bitmap_foreach (sid, wrk->wr_bitmap, ({ if (!(session = vcl_session_get (wrk, sid))) { - VDBG (0, "VCL<%d>: session %d specified in write_map is closed.", - getpid (), sid); - return VPPCOM_EBADFD; + if (except_map && sid < minbits) + clib_bitmap_set_no_check (except_map, sid, 1); + continue; } rv = svm_fifo_is_full (session->tx_fifo); @@ -2006,9 +2008,9 @@ check_rd: clib_bitmap_foreach (sid, wrk->rd_bitmap, ({ if (!(session = vcl_session_get (wrk, sid))) { - VDBG (0, "VCL<%d>: session %d specified in write_map is closed.", - getpid (), sid); - return VPPCOM_EBADFD; + if (except_map && sid < minbits) + clib_bitmap_set_no_check (except_map, sid, 1); + continue; } rv = vppcom_session_read_ready (session); @@ -3150,6 +3152,10 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op, rv = VPPCOM_EINVAL; break; + case VPPCOM_ATTR_GET_REFCNT: + rv = vcl_session_get_refcnt (session); + break; + default: rv = VPPCOM_EINVAL; break; @@ -3352,12 +3358,31 @@ vppcom_session_index (uint32_t session_handle) return session_handle & 0xFFFFFF; } +int +vppcom_session_handle (uint32_t session_index) +{ + return (vcl_get_worker_index () << 24) | session_index; +} + int vppcom_worker_register (void) { - if (vcl_worker_alloc_and_init ()) - return VPPCOM_OK; - return VPPCOM_EEXIST; + if (!vcl_worker_alloc_and_init ()) + return VPPCOM_EEXIST; + + if (vcl_worker_set_bapi ()) + return VPPCOM_EEXIST; + + if (vcl_worker_register_with_vpp ()) + return VPPCOM_EEXIST; + + return VPPCOM_OK; +} + +int +vppcom_worker_index (void) +{ + return vcl_get_worker_index (); } /*