X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvcl%2Fvppcom.c;h=a8273997a6342c65084e94c822b60f4de124dec8;hb=669f4e3416282ef022e6c59d09656b0563e5aae6;hp=d449fb91d44cdc500c5f6491694a8c865e8a83dc;hpb=028eaf075ad884063e229476f5733d3eea4af82c;p=vpp.git diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index d449fb91d44..a8273997a63 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -197,6 +197,99 @@ format_ip46_address (u8 * s, va_list * args) * VPPCOM Utility Functions */ +static void +vcl_send_session_listen (vcl_worker_t * wrk, vcl_session_t * s) +{ + app_session_evt_t _app_evt, *app_evt = &_app_evt; + session_listen_msg_t *mp; + svm_msg_q_t *mq; + + mq = vcl_worker_ctrl_mq (wrk); + app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_LISTEN); + mp = (session_listen_msg_t *) app_evt->evt->data; + memset (mp, 0, sizeof (*mp)); + mp->client_index = wrk->my_client_index; + mp->context = s->session_index; + mp->wrk_index = wrk->vpp_wrk_index; + mp->is_ip4 = s->transport.is_ip4; + clib_memcpy_fast (&mp->ip, &s->transport.lcl_ip, sizeof (mp->ip)); + mp->port = s->transport.lcl_port; + mp->proto = s->session_type; + app_send_ctrl_evt_to_vpp (mq, app_evt); +} + +static void +vcl_send_session_connect (vcl_worker_t * wrk, vcl_session_t * s) +{ + app_session_evt_t _app_evt, *app_evt = &_app_evt; + session_connect_msg_t *mp; + svm_msg_q_t *mq; + + mq = vcl_worker_ctrl_mq (wrk); + app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_CONNECT); + mp = (session_connect_msg_t *) app_evt->evt->data; + memset (mp, 0, sizeof (*mp)); + mp->client_index = wrk->my_client_index; + mp->context = s->session_index; + mp->wrk_index = wrk->vpp_wrk_index; + mp->is_ip4 = s->transport.is_ip4; + mp->parent_handle = s->parent_handle; + clib_memcpy_fast (&mp->ip, &s->transport.rmt_ip, sizeof (mp->ip)); + clib_memcpy_fast (&mp->lcl_ip, &s->transport.lcl_ip, sizeof (mp->lcl_ip)); + mp->port = s->transport.rmt_port; + mp->proto = s->session_type; + app_send_ctrl_evt_to_vpp (mq, app_evt); +} + +void +vcl_send_session_unlisten (vcl_worker_t * wrk, vcl_session_t * s) +{ + app_session_evt_t _app_evt, *app_evt = &_app_evt; + session_unlisten_msg_t *mp; + svm_msg_q_t *mq; + + mq = vcl_worker_ctrl_mq (wrk); + app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_UNLISTEN); + mp = (session_unlisten_msg_t *) app_evt->evt->data; + memset (mp, 0, sizeof (*mp)); + mp->client_index = wrk->my_client_index; + mp->wrk_index = wrk->vpp_wrk_index; + mp->handle = s->vpp_handle; + mp->context = wrk->wrk_index; + app_send_ctrl_evt_to_vpp (mq, app_evt); +} + +static void +vcl_send_session_disconnect (vcl_worker_t * wrk, vcl_session_t * s) +{ + app_session_evt_t _app_evt, *app_evt = &_app_evt; + session_disconnect_msg_t *mp; + svm_msg_q_t *mq; + + /* Send to thread that owns the session */ + mq = s->vpp_evt_q; + app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_DISCONNECT); + mp = (session_disconnect_msg_t *) app_evt->evt->data; + memset (mp, 0, sizeof (*mp)); + mp->client_index = wrk->my_client_index; + mp->handle = s->vpp_handle; + app_send_ctrl_evt_to_vpp (mq, app_evt); +} + +static void +vcl_send_app_detach (vcl_worker_t * wrk) +{ + app_session_evt_t _app_evt, *app_evt = &_app_evt; + session_app_detach_msg_t *mp; + svm_msg_q_t *mq; + + mq = vcl_worker_ctrl_mq (wrk); + app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_APP_DETACH); + mp = (session_app_detach_msg_t *) app_evt->evt->data; + memset (mp, 0, sizeof (*mp)); + mp->client_index = wrk->my_client_index; + app_send_ctrl_evt_to_vpp (mq, app_evt); +} static void vcl_send_session_accepted_reply (svm_msg_q_t * mq, u32 context, @@ -356,19 +449,23 @@ vcl_session_connected_handler (vcl_worker_t * wrk, { VDBG (0, "ERROR: session index %u: connect failed! %U", session_index, format_api_error, ntohl (mp->retval)); - session->session_state = STATE_FAILED; + session->session_state = STATE_FAILED | STATE_DISCONNECT; session->vpp_handle = mp->handle; return session_index; } + session->vpp_handle = mp->handle; + session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address, + svm_msg_q_t *); rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *); tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *); if (vcl_wait_for_segment (mp->segment_handle)) { VDBG (0, "segment for session %u couldn't be mounted!", session->session_index); - session->session_state = STATE_FAILED; - return VCL_INVALID_SESSION_INDEX; + session->session_state = STATE_FAILED | STATE_DISCONNECT; + vcl_send_session_disconnect (wrk, session); + return session_index; } rx_fifo->client_session_index = session_index; @@ -376,8 +473,6 @@ vcl_session_connected_handler (vcl_worker_t * wrk, rx_fifo->client_thread_index = vcl_get_worker_index (); tx_fifo->client_thread_index = vcl_get_worker_index (); - session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address, - svm_msg_q_t *); vpp_wrk_index = tx_fifo->master_thread_index; vec_validate (wrk->vpp_event_queues, vpp_wrk_index); wrk->vpp_event_queues[vpp_wrk_index] = session->vpp_evt_q; @@ -390,14 +485,14 @@ vcl_session_connected_handler (vcl_worker_t * wrk, { VDBG (0, "ct segment for session %u couldn't be mounted!", session->session_index); - session->session_state = STATE_FAILED; - return VCL_INVALID_SESSION_INDEX; + session->session_state = STATE_FAILED | STATE_DISCONNECT; + vcl_send_session_disconnect (wrk, session); + return session_index; } } session->rx_fifo = rx_fifo; session->tx_fifo = tx_fifo; - session->vpp_handle = mp->handle; session->vpp_thread_index = rx_fifo->master_thread_index; session->transport.is_ip4 = mp->lcl.is_ip4; clib_memcpy_fast (&session->transport.lcl_ip, &mp->lcl.ip, @@ -827,7 +922,6 @@ vppcom_session_unbind (u32 session_handle) session_accepted_msg_t *accepted_msg; vcl_session_t *session = 0; vcl_session_msg_t *evt; - u64 vpp_handle; session = vcl_session_get_w_handle (wrk, session_handle); if (!session) @@ -845,14 +939,14 @@ vppcom_session_unbind (u32 session_handle) } clib_fifo_free (session->accept_evts_fifo); - vpp_handle = session->vpp_handle; - session->vpp_handle = ~0; - session->session_state = STATE_DISCONNECT; + vcl_send_session_unlisten (wrk, session); VDBG (1, "session %u [0x%llx]: sending unbind!", session->session_index, - vpp_handle); + session->vpp_handle); vcl_evt (VCL_EVT_UNBIND, session); - vppcom_send_unbind_sock (wrk, vpp_handle); + + session->vpp_handle = ~0; + session->session_state = STATE_DISCONNECT; return VPPCOM_OK; } @@ -894,7 +988,7 @@ vppcom_session_disconnect (u32 session_handle) { VDBG (1, "session %u [0x%llx]: sending disconnect...", session->session_index, vpp_handle); - vppcom_send_disconnect_session (vpp_handle); + vcl_send_session_disconnect (wrk, session); } if (session->listener_index != VCL_INVALID_SESSION_INDEX) @@ -922,7 +1016,7 @@ vppcom_app_exit (void) vcl_set_worker_index (~0); vcl_elog_stop (vcm); if (vec_len (vcm->workers) == 1) - vl_client_disconnect_from_vlib (); + vppcom_disconnect_from_vpp (); else vl_client_send_disconnect (1 /* vpp should cleanup */ ); } @@ -1005,7 +1099,7 @@ vppcom_app_destroy (void) if (pool_elts (vcm->workers) == 1) { - vppcom_app_send_detach (); + vcl_send_app_detach (vcl_worker_get_current ()); orig_app_timeout = vcm->cfg.app_timeout; vcm->cfg.app_timeout = 2.0; rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED); @@ -1220,7 +1314,7 @@ vppcom_session_listen (uint32_t listen_sh, uint32_t q_len) /* * Send listen request to vpp and wait for reply */ - vppcom_send_bind_sock (listen_session); + vcl_send_session_listen (wrk, listen_session); rv = vppcom_wait_for_session_state_change (listen_session->session_index, STATE_LISTEN, vcm->cfg.session_timeout); @@ -1256,7 +1350,8 @@ vppcom_session_tls_add_cert (uint32_t session_handle, char *cert, * Send listen request to vpp and wait for reply */ vppcom_send_application_tls_cert_add (session, cert, cert_len); - + vcm->app_state = STATE_APP_ADDING_TLS_DATA; + vcl_wait_for_app_state_change (STATE_APP_READY); return VPPCOM_OK; } @@ -1276,14 +1371,10 @@ vppcom_session_tls_add_key (uint32_t session_handle, char *key, if (key_len == 0 || key_len == ~0) return VPPCOM_EBADFD; - /* - * Send listen request to vpp and wait for reply - */ vppcom_send_application_tls_key_add (session, key, key_len); - + vcm->app_state = STATE_APP_ADDING_TLS_DATA; + vcl_wait_for_app_state_change (STATE_APP_READY); return VPPCOM_OK; - - } static int @@ -1449,6 +1540,25 @@ handle: return vcl_session_handle (client_session); } +static void +vcl_ip_copy_from_ep (ip46_address_t * ip, vppcom_endpt_t * ep) +{ + if (ep->is_ip4) + clib_memcpy_fast (&ip->ip4, ep->ip, sizeof (ip4_address_t)); + else + clib_memcpy_fast (&ip->ip6, ep->ip, sizeof (ip6_address_t)); +} + +void +vcl_ip_copy_to_ep (ip46_address_t * ip, vppcom_endpt_t * ep, u8 is_ip4) +{ + ep->is_ip4 = is_ip4; + if (is_ip4) + clib_memcpy_fast (ep->ip, &ip->ip4, sizeof (ip4_address_t)); + else + clib_memcpy_fast (ep->ip, &ip->ip6, sizeof (ip6_address_t)); +} + int vppcom_session_connect (uint32_t session_handle, vppcom_endpt_t * server_ep) { @@ -1484,12 +1594,7 @@ 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_fast (&session->transport.rmt_ip.ip4, server_ep->ip, - sizeof (ip4_address_t)); - else - clib_memcpy_fast (&session->transport.rmt_ip.ip6, server_ep->ip, - sizeof (ip6_address_t)); + vcl_ip_copy_from_ep (&session->transport.rmt_ip, server_ep); session->transport.rmt_port = server_ep->port; session->parent_handle = VCL_INVALID_SESSION_HANDLE; @@ -1502,10 +1607,14 @@ vppcom_session_connect (uint32_t session_handle, vppcom_endpt_t * server_ep) clib_net_to_host_u16 (session->transport.rmt_port), vppcom_proto_str (session->session_type)); + vcl_send_session_connect (wrk, session); + + if (VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK)) + return VPPCOM_EINPROGRESS; + /* - * Send connect request and wait for reply from vpp + * Wait for reply from vpp if blocking */ - vppcom_send_connect_sock (session); rv = vppcom_wait_for_session_state_change (session_index, STATE_CONNECT, vcm->cfg.session_timeout); @@ -1564,7 +1673,7 @@ vppcom_session_stream_connect (uint32_t session_handle, /* * Send connect request and wait for reply from vpp */ - vppcom_send_connect_sock (session); + vcl_send_session_connect (wrk, session); rv = vppcom_wait_for_session_state_change (session_index, STATE_CONNECT, vcm->cfg.session_timeout); @@ -1945,7 +2054,14 @@ vcl_select_handle_mq_event (vcl_worker_t * wrk, session_event_t * e, break; case SESSION_CTRL_EVT_CONNECTED: connected_msg = (session_connected_msg_t *) e->data; - vcl_session_connected_handler (wrk, connected_msg); + sid = vcl_session_connected_handler (wrk, connected_msg); + if (sid == VCL_INVALID_SESSION_INDEX) + break; + if (sid < n_bits && write_map) + { + clib_bitmap_set_no_check ((uword *) write_map, sid, 1); + *bits_set += 1; + } break; case SESSION_CTRL_EVT_DISCONNECTED: disconnected_msg = (session_disconnected_msg_t *) e->data; @@ -2187,75 +2303,75 @@ check_mq: } static inline void -vep_verify_epoll_chain (vcl_worker_t * wrk, u32 vep_idx) +vep_verify_epoll_chain (vcl_worker_t * wrk, u32 vep_handle) { vcl_session_t *session; vppcom_epoll_t *vep; - u32 sid = vep_idx; + u32 sh = vep_handle; if (VPPCOM_DEBUG <= 2) return; - session = vcl_session_get (wrk, vep_idx); + session = vcl_session_get_w_handle (wrk, vep_handle); if (PREDICT_FALSE (!session)) { - VDBG (0, "ERROR: Invalid vep_idx (%u)!", vep_idx); + VDBG (0, "ERROR: Invalid vep_sh (%u)!", vep_handle); goto done; } if (PREDICT_FALSE (!session->is_vep)) { - VDBG (0, "ERROR: vep_idx (%u) is not a vep!", vep_idx); + VDBG (0, "ERROR: vep_sh (%u) is not a vep!", vep_handle); goto done; } vep = &session->vep; - VDBG (0, "vep_idx (%u): Dumping epoll chain\n" + VDBG (0, "vep_sh (%u): Dumping epoll chain\n" "{\n" " is_vep = %u\n" " is_vep_session = %u\n" - " next_sid = 0x%x (%u)\n" - "}\n", vep_idx, session->is_vep, session->is_vep_session, + " next_sh = 0x%x (%u)\n" + "}\n", vep_handle, session->is_vep, session->is_vep_session, vep->next_sh, vep->next_sh); - for (sid = vep->next_sh; sid != ~0; sid = vep->next_sh) + for (sh = vep->next_sh; sh != ~0; sh = vep->next_sh) { - session = vcl_session_get (wrk, sid); + session = vcl_session_get_w_handle (wrk, sh); if (PREDICT_FALSE (!session)) { - VDBG (0, "ERROR: Invalid sid (%u)!", sid); + VDBG (0, "ERROR: Invalid sh (%u)!", sh); goto done; } if (PREDICT_FALSE (session->is_vep)) { - VDBG (0, "ERROR: sid (%u) is a vep!", vep_idx); + VDBG (0, "ERROR: sh (%u) is a vep!", vep_handle); } else if (PREDICT_FALSE (!session->is_vep_session)) { - VDBG (0, "ERROR: session (%u) is not a vep session!", sid); + VDBG (0, "ERROR: sh (%u) is not a vep session handle!", sh); goto done; } vep = &session->vep; - if (PREDICT_FALSE (vep->vep_sh != vep_idx)) - VDBG (0, "ERROR: session (%u) vep_idx (%u) != vep_idx (%u)!", - sid, session->vep.vep_sh, vep_idx); + if (PREDICT_FALSE (vep->vep_sh != vep_handle)) + VDBG (0, "ERROR: session (%u) vep_sh (%u) != vep_sh (%u)!", + sh, session->vep.vep_sh, vep_handle); if (session->is_vep_session) { - VDBG (0, "vep_idx[%u]: sid 0x%x (%u)\n" + VDBG (0, "vep_sh[%u]: sh 0x%x (%u)\n" "{\n" - " next_sid = 0x%x (%u)\n" - " prev_sid = 0x%x (%u)\n" - " vep_idx = 0x%x (%u)\n" + " next_sh = 0x%x (%u)\n" + " prev_sh = 0x%x (%u)\n" + " vep_sh = 0x%x (%u)\n" " ev.events = 0x%x\n" " ev.data.u64 = 0x%llx\n" " et_mask = 0x%x\n" "}\n", - vep_idx, sid, sid, vep->next_sh, vep->next_sh, vep->prev_sh, + vep_handle, sh, sh, vep->next_sh, vep->next_sh, vep->prev_sh, vep->prev_sh, vep->vep_sh, vep->vep_sh, vep->ev.events, vep->ev.data.u64, vep->et_mask); } } done: - VDBG (0, "vep_idx (%u): Dump complete!\n", vep_idx); + VDBG (0, "vep_sh (%u): Dump complete!\n", vep_handle); } int @@ -2520,6 +2636,8 @@ vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e, add_event = 1; events[*num_ev].events |= EPOLLOUT; session_evt_data = session->vep.ev.data.u64; + if (session->session_state & STATE_FAILED) + events[*num_ev].events |= EPOLLHUP; break; case SESSION_CTRL_EVT_DISCONNECTED: disconnected_msg = (session_disconnected_msg_t *) e->data; @@ -2829,6 +2947,24 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op, rv = VPPCOM_EINVAL; break; + case VPPCOM_ATTR_SET_LCL_ADDR: + if (PREDICT_TRUE (buffer && buflen && + (*buflen >= sizeof (*ep)) && ep->ip)) + { + session->transport.is_ip4 = ep->is_ip4; + session->transport.lcl_port = ep->port; + vcl_ip_copy_from_ep (&session->transport.lcl_ip, ep); + *buflen = sizeof (*ep); + VDBG (1, "VPPCOM_ATTR_SET_LCL_ADDR: sh %u, is_ip4 = %u, addr = %U" + " port %d", session_handle, ep->is_ip4, format_ip46_address, + &session->transport.lcl_ip, + ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6, + clib_net_to_host_u16 (ep->port)); + } + else + rv = VPPCOM_EINVAL; + break; + case VPPCOM_ATTR_GET_LIBC_EPFD: rv = session->libc_epfd; VDBG (2, "VPPCOM_ATTR_GET_LIBC_EPFD: libc_epfd %d", rv);