+
+ 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* */
+ }
+ }
+