- if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] detaching from VPP, my_client_index %d (0x%x)",
- getpid (), vcm->my_client_index, vcm->my_client_index);
-
- if (VPPCOM_DEBUG > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "app_detach:C:%d",
- .format_args = "i4",
- };
-
- struct
- {
- u32 data;
- } *ed;
- ed = ELOG_TRACK_DATA (&vcm->elog_main, e, vcm->elog_track);
- ed->data = vcm->my_client_index;
- /* *INDENT-ON* */
- }
-
- vppcom_app_detach ();
- rv = vppcom_wait_for_app_state_change (STATE_APP_ENABLED);
- if (PREDICT_FALSE (rv))
- {
- if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] application detach timed out! returning %d (%s)",
- getpid (), rv, vppcom_retval_str (rv));
- }
-
- /* Finished with logging before client gets reset to ~0 */
- if (VPPCOM_DEBUG > 0)
- write_elog ();
-
- vl_client_disconnect_from_vlib ();
- vcm->my_client_index = ~0;
- vcm->app_state = STATE_APP_START;
-}
-
-int
-vppcom_session_create (u32 vrf, u8 proto, u8 is_nonblocking)
-{
- session_t *session;
- u32 session_index;
-
- clib_spinlock_lock (&vcm->sessions_lockp);
- pool_get (vcm->sessions, session);
- memset (session, 0, sizeof (*session));
- session_index = session - vcm->sessions;
-
- session->vrf = vrf;
- session->proto = proto;
- session->state = STATE_START;
- session->is_nonblocking = is_nonblocking ? 1 : 0;
- session->vpp_handle = ~0;
- clib_spinlock_unlock (&vcm->sessions_lockp);
-
- if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] sid %u", getpid (), session_index);
-
- if (VPPCOM_DEBUG > 0)
- {
- session->elog_track.name =
- (char *) format (0, "C:%d:S:%d%c", vcm->my_client_index,
- session_index, 0);
- elog_track_register (&vcm->elog_main, &session->elog_track);
-
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "session_create:vrf:%d proto:%d state:%d is_nonblocking:%d",
- .format_args = "i4i4i4i4",
- };
-
- struct
- {
- u32 data[4];
- } *ed;
-
- ed = ELOG_TRACK_DATA (&vcm->elog_main, e, session->elog_track);
- ed->data[0] = session->vrf;
- ed->data[1] = session->proto;
- ed->data[2] = session->state;
- ed->data[3] = session->is_nonblocking;
- /* *INDENT-ON* */
- }
-
- return (int) session_index;
-}
-
-int
-vppcom_session_close (uint32_t session_index)
-{
- session_t *session = 0;
- int rv;
- u8 is_listen;
- u8 is_vep;
- u8 is_vep_session;
- u32 next_sid;
- u32 vep_idx;
- u64 vpp_handle;
- uword *p;
- session_state_t state;
-
- VCL_LOCK_AND_GET_SESSION (session_index, &session);
- is_listen = session->is_listen;
- is_vep = session->is_vep;
- is_vep_session = session->is_vep_session;
- next_sid = session->vep.next_sid;
- vep_idx = session->vep.vep_idx;
- state = session->state;
- vpp_handle = session->vpp_handle;
- clib_spinlock_unlock (&vcm->sessions_lockp);
-
- if (VPPCOM_DEBUG > 0)
- {
- if (is_vep)
- clib_warning ("[%d] vep_idx %u / sid %u: closing epoll session...",
- getpid (), session_index, session_index);
- else
- clib_warning ("[%d] vpp handle 0x%llx, sid %d: closing session...",
- getpid (), vpp_handle, session_index);
- }
-
- if (is_vep)
- {
- while (next_sid != ~0)
- {
- rv = vppcom_epoll_ctl (session_index, EPOLL_CTL_DEL, next_sid, 0);
- if ((VPPCOM_DEBUG > 0) && PREDICT_FALSE (rv < 0))
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL "
- "vep_idx %u failed! rv %d (%s)", getpid (),
- vpp_handle, next_sid, vep_idx,
- rv, vppcom_retval_str (rv));
-
- VCL_LOCK_AND_GET_SESSION (session_index, &session);
- next_sid = session->vep.next_sid;
- clib_spinlock_unlock (&vcm->sessions_lockp);
- }
- }
- else
- {
- if (is_vep_session)
- {
- rv = vppcom_epoll_ctl (vep_idx, EPOLL_CTL_DEL, session_index, 0);
- if ((VPPCOM_DEBUG > 0) && (rv < 0))
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL "
- "vep_idx %u failed! rv %d (%s)",
- getpid (), vpp_handle, session_index,
- vep_idx, rv, vppcom_retval_str (rv));
- }
-
- if (is_listen)
- {
- if (state == STATE_LISTEN)
- {
- rv = vppcom_session_unbind (session_index);
- if (PREDICT_FALSE (rv < 0))
- {
- if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: "
- "listener unbind failed! rv %d (%s)",
- getpid (), vpp_handle, session_index,
- rv, vppcom_retval_str (rv));
- }
- }
- }
-
- else if (state & (CLIENT_STATE_OPEN | SERVER_STATE_OPEN))
- {
- rv = vppcom_session_disconnect (session_index);
- if (PREDICT_FALSE (rv < 0))
- clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: "
- "session disconnect failed! rv %d (%s)",
- getpid (), vpp_handle, session_index,
- rv, vppcom_retval_str (rv));
- }
- }
-
- VCL_LOCK_AND_GET_SESSION (session_index, &session);
- vpp_handle = session->vpp_handle;
- if (vpp_handle != ~0)
- {
- p = hash_get (vcm->session_index_by_vpp_handles, vpp_handle);
- if (p)
- hash_unset (vcm->session_index_by_vpp_handles, vpp_handle);
- }
- pool_put_index (vcm->sessions, session_index);
- clib_spinlock_unlock (&vcm->sessions_lockp);
-
- if (VPPCOM_DEBUG > 0)
- {
- if (is_vep)
- clib_warning ("[%d] vep_idx %u / sid %u: epoll session removed.",
- getpid (), session_index, session_index);
- else
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: session removed.",
- getpid (), vpp_handle, session_index);
- }
-done:
-
- if (VPPCOM_DEBUG > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "session_close:rv:%d",
- .format_args = "i4",
- };
-
- struct
- {
- u32 data;
- } *ed;
-
- ed = ELOG_TRACK_DATA (&vcm->elog_main, e, session->elog_track);
- ed->data = rv;
- /* *INDENT-ON* */
- }
-
- return rv;
-}
-
-int
-vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep)
-{
- session_t *session = 0;
- int rv;
-
- if (!ep || !ep->ip)
- return VPPCOM_EINVAL;
-
- VCL_LOCK_AND_GET_SESSION (session_index, &session);
-
- if (session->is_vep)
- {
- clib_spinlock_unlock (&vcm->sessions_lockp);
- clib_warning ("[%d] ERROR: sid %u: cannot bind to an epoll session!",
- getpid (), session_index);
- rv = VPPCOM_EBADFD;
- goto done;
- }
-
- session->vrf = ep->vrf;
- session->lcl_addr.is_ip4 = ep->is_ip4;
- session->lcl_addr.ip46 = to_ip46 (!ep->is_ip4, ep->ip);
- session->lcl_port = ep->port;
-
- if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] sid %u: binding to local %s address %U "
- "port %u, proto %s", getpid (), session_index,
- session->lcl_addr.is_ip4 ? "IPv4" : "IPv6",
- format_ip46_address, &session->lcl_addr.ip46,
- session->lcl_addr.is_ip4,
- clib_net_to_host_u16 (session->lcl_port),
- session->proto ? "UDP" : "TCP");
-
- if (VPPCOM_DEBUG > 0)
- {
- if (session->lcl_addr.is_ip4)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "bind local:%s:%d.%d.%d.%d:%d ",
- .format_args = "t1i1i1i1i1i2",
- .n_enum_strings = 2,
- .enum_strings = {"TCP", "UDP",},
- };
-
- CLIB_PACKED (struct {
- u8 proto;
- u8 addr[4];
- u16 port;
- }) * ed;
-
- ed = ELOG_TRACK_DATA (&vcm->elog_main, e, session->elog_track);
- ed->proto = session->proto;
- ed->addr[0] = session->lcl_addr.ip46.ip4.as_u8[0];
- ed->addr[1] = session->lcl_addr.ip46.ip4.as_u8[1];
- ed->addr[2] = session->lcl_addr.ip46.ip4.as_u8[2];
- ed->addr[3] = session->lcl_addr.ip46.ip4.as_u8[3];
- ed->port = clib_net_to_host_u16 (session->lcl_port);
- /* *INDENT-ON* */
- }
- }
-
- clib_spinlock_unlock (&vcm->sessions_lockp);
-done:
- return rv;
-}
-
-int
-vppcom_session_listen (uint32_t listen_session_index, uint32_t q_len)
-{
- session_t *listen_session = 0;
- u64 listen_vpp_handle;
- int rv, retval;
-
- VCL_LOCK_AND_GET_SESSION (listen_session_index, &listen_session);
-
- if (listen_session->is_vep)
- {
- clib_spinlock_unlock (&vcm->sessions_lockp);
- clib_warning ("[%d] ERROR: sid %u: cannot listen on an "
- "epoll session!", getpid (), listen_session_index);
- rv = VPPCOM_EBADFD;
- goto done;
- }
-
- listen_vpp_handle = listen_session->vpp_handle;
- if (listen_session->is_listen)
- {
- clib_spinlock_unlock (&vcm->sessions_lockp);
- if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: "
- "already in listen state!",
- getpid (), listen_vpp_handle, listen_session_index);
- rv = VPPCOM_OK;
- goto done;
- }
-
- if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: sending bind request...",
- getpid (), listen_vpp_handle, listen_session_index);
-
- vppcom_send_bind_sock (listen_session, listen_session_index);
- clib_spinlock_unlock (&vcm->sessions_lockp);
- retval =
- vppcom_wait_for_session_state_change (listen_session_index, STATE_LISTEN,
- vcm->cfg.session_timeout);
-
- VCL_LOCK_AND_GET_SESSION (listen_session_index, &listen_session);
- if (PREDICT_FALSE (retval))
- {
- if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: bind failed! "
- "returning %d (%s)", getpid (),
- listen_session->vpp_handle, listen_session_index,
- retval, vppcom_retval_str (retval));
- clib_spinlock_unlock (&vcm->sessions_lockp);
- rv = retval;
- goto done;
- }
-
- clib_fifo_validate (vcm->client_session_index_fifo, q_len);
- clib_spinlock_unlock (&vcm->sessions_lockp);
-done:
- return rv;
-}
-
-int
-vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep,
- uint32_t flags, double wait_for_time)
-{
- session_t *listen_session = 0;
- session_t *client_session = 0;
- u32 client_session_index = ~0;
- int rv;
- f64 wait_for;
- char *cut_thru_str;
- u64 listen_vpp_handle;
-
- VCL_LOCK_AND_GET_SESSION (listen_session_index, &listen_session);
-
- if (listen_session->is_vep)
- {
- clib_spinlock_unlock (&vcm->sessions_lockp);
- clib_warning ("[%d] ERROR: sid %u: cannot accept on an "
- "epoll session!", getpid (), listen_session_index);
- rv = VPPCOM_EBADFD;
- goto done;
- }
-
- listen_vpp_handle = listen_session->vpp_handle;
- if (listen_session->state != STATE_LISTEN)
- {
- clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: "
- "not in listen state! state 0x%x (%s)", getpid (),
- listen_vpp_handle, listen_session_index,
- listen_session->state,
- vppcom_session_state_str (listen_session->state));
- clib_spinlock_unlock (&vcm->sessions_lockp);
- rv = VPPCOM_EBADFD;
- goto done;
- }
- wait_for = ((listen_session->is_nonblocking) ? 0 :
- (wait_for_time < 0) ? vcm->cfg.accept_timeout : wait_for_time);
-
- clib_spinlock_unlock (&vcm->sessions_lockp);
-
- while (1)
- {
- rv = vppcom_wait_for_client_session_index (wait_for);
- if (rv)
- {
- if ((VPPCOM_DEBUG > 0))
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: accept failed! "
- "returning %d (%s)", getpid (),
- listen_vpp_handle, listen_session_index,
- rv, vppcom_retval_str (rv));
- if ((wait_for == 0) || (wait_for_time > 0))
- goto done;
- }
- else
- break;
- }
-
- clib_spinlock_lock (&vcm->sessions_lockp);
- clib_fifo_sub1 (vcm->client_session_index_fifo, client_session_index);
- rv = vppcom_session_at_index (client_session_index, &client_session);
- if (PREDICT_FALSE (rv))
- {
- rv = VPPCOM_ECONNABORTED;
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: client sid %u "
- "lookup failed! returning %d (%s)", getpid (),
- listen_vpp_handle, listen_session_index,
- client_session_index, rv, vppcom_retval_str (rv));
- goto done;
- }
-
- client_session->is_nonblocking = (flags & O_NONBLOCK) ? 1 : 0;
- if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: Got a client request! "
- "vpp handle 0x%llx, sid %u, flags %d, is_nonblocking %u",
- getpid (), listen_vpp_handle, listen_session_index,
- client_session->vpp_handle, client_session_index,
- flags, client_session->is_nonblocking);
-
- ep->vrf = client_session->vrf;
- ep->is_cut_thru = client_session->is_cut_thru;
- ep->is_ip4 = client_session->peer_addr.is_ip4;
- ep->port = client_session->peer_port;
- if (client_session->peer_addr.is_ip4)
- clib_memcpy (ep->ip, &client_session->peer_addr.ip46.ip4,
- sizeof (ip4_address_t));
- else
- clib_memcpy (ep->ip, &client_session->peer_addr.ip46.ip6,
- sizeof (ip6_address_t));
-
- if (client_session->is_server && client_session->is_cut_thru)
- {
- static svm_fifo_segment_create_args_t _a;
- svm_fifo_segment_create_args_t *a = &_a;
- svm_fifo_segment_private_t *seg;
-
- cut_thru_str = " cut-thru ";
-
- /* Create the segment */
- memset (a, 0, sizeof (*a));
- a->segment_name = (char *)
- format ((u8 *) a->segment_name, "%d:segment%d%c",
- getpid (), vcm->unique_segment_index++, 0);
- a->segment_size = vcm->cfg.segment_size;
- a->preallocated_fifo_pairs = vcm->cfg.preallocated_fifo_pairs;
- a->rx_fifo_size = vcm->cfg.rx_fifo_size;
- a->tx_fifo_size = vcm->cfg.tx_fifo_size;
-
- rv = svm_fifo_segment_create (a);
- if (PREDICT_FALSE (rv))
- {
- clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: "
- "client sid %u svm_fifo_segment_create ('%s') "
- "failed! rv %d", getpid (), listen_vpp_handle,
- listen_session_index, client_session_index,
- a->segment_name, rv);
- vec_reset_length (a->new_segment_indices);
- rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
- vppcom_send_connect_session_reply (client_session,
- client_session_index,
- client_session->vpp_handle,
- client_session->client_context,
- rv);
- clib_spinlock_unlock (&vcm->sessions_lockp);
- rv = VPPCOM_ENOMEM;
- goto done;
- }
-
- client_session->segment_name = vec_dup ((u8 *) a->segment_name);
- client_session->sm_seg_index = a->new_segment_indices[0];
- vec_free (a->new_segment_indices);
-
- seg = svm_fifo_segment_get_segment (client_session->sm_seg_index);
- client_session->server_rx_fifo =
- svm_fifo_segment_alloc_fifo (seg, vcm->cfg.rx_fifo_size,
- FIFO_SEGMENT_RX_FREELIST);
- if (PREDICT_FALSE (!client_session->server_rx_fifo))
- {
- svm_fifo_segment_delete (seg);
- clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: "
- "client sid %u rx fifo alloc failed! "
- "size %ld (0x%lx)", getpid (), listen_vpp_handle,
- listen_session_index, client_session_index,
- vcm->cfg.rx_fifo_size, vcm->cfg.rx_fifo_size);
- rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
- vppcom_send_connect_session_reply (client_session,
- client_session_index,
- client_session->vpp_handle,
- client_session->client_context,
- rv);
- clib_spinlock_unlock (&vcm->sessions_lockp);
- rv = VPPCOM_ENOMEM;
- goto done;
- }
- client_session->server_rx_fifo->master_session_index =
- client_session_index;
-
- client_session->server_tx_fifo =
- svm_fifo_segment_alloc_fifo (seg, vcm->cfg.tx_fifo_size,
- FIFO_SEGMENT_TX_FREELIST);
- if (PREDICT_FALSE (!client_session->server_tx_fifo))
- {
- svm_fifo_segment_delete (seg);
- clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: "
- "client sid %u tx fifo alloc failed! "
- "size %ld (0x%lx)", getpid (), listen_vpp_handle,
- listen_session_index, client_session_index,
- vcm->cfg.tx_fifo_size, vcm->cfg.tx_fifo_size);
- rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
- vppcom_send_connect_session_reply (client_session,
- client_session_index,
- client_session->vpp_handle,
- client_session->client_context,
- rv);
- clib_spinlock_unlock (&vcm->sessions_lockp);
- rv = VPPCOM_ENOMEM;
- goto done;
- }
- client_session->server_tx_fifo->master_session_index =
- client_session_index;
-
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: client sid %u "
- "created segment '%s', rx_fifo %p, tx_fifo %p",
- getpid (), listen_vpp_handle, listen_session_index,
- client_session_index, client_session->segment_name,
- client_session->server_rx_fifo,
- client_session->server_tx_fifo);
-
-#ifdef CUT_THRU_EVENT_QUEUE /* TBD */
- {
- void *oldheap;
- ssvm_shared_header_t *sh = seg->ssvm.sh;
-
- ssvm_lock_non_recursive (sh, 1);
- oldheap = ssvm_push_heap (sh);
- event_q = client_session->vpp_event_queue =
- svm_queue_init (vcm->cfg.event_queue_size,
- sizeof (session_fifo_event_t),
- getpid (), 0 /* signal not sent */ );
- ssvm_pop_heap (oldheap);
- ssvm_unlock_non_recursive (sh);
- }
-#endif
- vppcom_send_connect_session_reply (client_session,
- client_session_index,
- client_session->vpp_handle,
- client_session->client_context,
- 0 /* retval OK */ );
- }
- else
- {
- cut_thru_str = " ";
- vppcom_send_accept_session_reply (client_session->vpp_handle,
- client_session->client_context,
- 0 /* retval OK */ );
- }
-
- if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: accepted vpp handle "
- "0x%llx, sid %u%sconnection to local %s address "
- "%U port %u", getpid (), listen_vpp_handle,
- listen_session_index, client_session->vpp_handle,
- client_session_index, cut_thru_str,
- client_session->lcl_addr.is_ip4 ? "IPv4" : "IPv6",
- format_ip46_address, &client_session->lcl_addr.ip46,
- client_session->lcl_addr.is_ip4,
- clib_net_to_host_u16 (client_session->lcl_port));
-
- if (VPPCOM_DEBUG > 0)
- {
- client_session->elog_track.name =
- (char *) format (0, "C:%d:S:%d%c", vcm->my_client_index,
- client_session_index, 0);
- elog_track_register (&vcm->elog_main, &client_session->elog_track);
-
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "accept cut-thru: listen_handle:%x from_handle:%x",
- .format_args = "i8i8",
- };
-
- struct
- {
- u64 handle[2];
- } *ed;
-
- ed = ELOG_TRACK_DATA (&vcm->elog_main, e, client_session->elog_track);
- ed->handle[0] = listen_vpp_handle;
- ed->handle[1] = client_session->vpp_handle;
- /* *INDENT-ON* */
-
- if (client_session->lcl_addr.is_ip4)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e2) =
- {
- .format = "accept cut-thru: S:%d %d.%d.%d.%d:%d ",
- .format_args = "i4i1i1i1i1i2",
- };
-
- CLIB_PACKED (struct {
- u32 session;
- u8 addr[4];
- u16 port;
- }) * ed2;
-
- ed2 =
- ELOG_TRACK_DATA (&vcm->elog_main, e2, client_session->elog_track);
- ed2->session = client_session_index;
- ed2->addr[0] = client_session->lcl_addr.ip46.ip4.as_u8[0];
- ed2->addr[1] = client_session->lcl_addr.ip46.ip4.as_u8[1];
- ed2->addr[2] = client_session->lcl_addr.ip46.ip4.as_u8[2];
- ed2->addr[3] = client_session->lcl_addr.ip46.ip4.as_u8[3];
- ed2->port = clib_net_to_host_u16 (client_session->lcl_port);
- /* *INDENT-ON* */
- }
- }
-
- clib_spinlock_unlock (&vcm->sessions_lockp);
- rv = (int) client_session_index;
-done:
- return rv;