-segment_manager_t *
-app_worker_get_local_segment_manager (app_worker_t * app_worker)
-{
- return segment_manager_get (app_worker->local_segment_manager);
-}
-
-segment_manager_t *
-app_worker_get_local_segment_manager_w_session (app_worker_t * app_wrk,
- local_session_t * ls)
-{
- session_t *listener;
- if (application_local_session_listener_has_transport (ls))
- {
- listener = listen_session_get (ls->listener_index);
- return app_worker_get_listen_segment_manager (app_wrk, listener);
- }
- return segment_manager_get (app_wrk->local_segment_manager);
-}
-
-int
-app_worker_local_session_cleanup (app_worker_t * client_wrk,
- app_worker_t * server_wrk,
- local_session_t * ls)
-{
- svm_fifo_segment_private_t *seg;
- session_t *listener;
- segment_manager_t *sm;
- u64 client_key;
- u8 has_transport;
-
- /* Retrieve listener transport type as it is the one that decides where
- * the fifos are allocated */
- has_transport = application_local_session_listener_has_transport (ls);
- if (!has_transport)
- sm = app_worker_get_local_segment_manager_w_session (server_wrk, ls);
- else
- {
- listener = listen_session_get (ls->listener_index);
- sm = app_worker_get_listen_segment_manager (server_wrk, listener);
- }
-
- seg = segment_manager_get_segment (sm, ls->svm_segment_index);
- if (client_wrk)
- {
- client_key = application_client_local_connect_key (ls);
- hash_unset (client_wrk->local_connects, client_key);
- }
-
- if (!has_transport)
- {
- application_t *server = application_get (server_wrk->app_index);
- u64 segment_handle = segment_manager_segment_handle (sm, seg);
- server->cb_fns.del_segment_callback (server_wrk->api_client_index,
- segment_handle);
- if (client_wrk)
- {
- application_t *client = application_get (client_wrk->app_index);
- client->cb_fns.del_segment_callback (client_wrk->api_client_index,
- segment_handle);
- }
- segment_manager_del_segment (sm, seg);
- }
-
- app_worker_local_session_free (server_wrk, ls);
-
- return 0;
-}
-
-static void
-application_local_session_fix_eventds (svm_msg_q_t * sq, svm_msg_q_t * cq)
-{
- int fd;
-
- /*
- * segment manager initializes only the producer eventds, since vpp is
- * typically the producer. But for local sessions, we also pass to the
- * apps the mqs they listen on for events from peer apps, so they are also
- * consumer fds.
- */
- fd = svm_msg_q_get_producer_eventfd (sq);
- svm_msg_q_set_consumer_eventfd (sq, fd);
- fd = svm_msg_q_get_producer_eventfd (cq);
- svm_msg_q_set_consumer_eventfd (cq, fd);
-}
-
-int
-app_worker_local_session_connect (app_worker_t * client_wrk,
- app_worker_t * server_wrk,
- local_session_t * ll, u32 opaque)
-{
- u32 seg_size, evt_q_sz, evt_q_elts, margin = 16 << 10;
- u32 round_rx_fifo_sz, round_tx_fifo_sz, sm_index;
- segment_manager_properties_t *props, *cprops;
- int rv, has_transport, seg_index;
- svm_fifo_segment_private_t *seg;
- application_t *server, *client;
- segment_manager_t *sm;
- local_session_t *ls;
- svm_msg_q_t *sq, *cq;
- u64 segment_handle;
-
- ls = app_worker_local_session_alloc (server_wrk);
- server = application_get (server_wrk->app_index);
- client = application_get (client_wrk->app_index);
-
- props = application_segment_manager_properties (server);
- cprops = application_segment_manager_properties (client);
- evt_q_elts = props->evt_q_size + cprops->evt_q_size;
- evt_q_sz = segment_manager_evt_q_expected_size (evt_q_elts);
- round_rx_fifo_sz = 1 << max_log2 (props->rx_fifo_size);
- round_tx_fifo_sz = 1 << max_log2 (props->tx_fifo_size);
- seg_size = round_rx_fifo_sz + round_tx_fifo_sz + evt_q_sz + margin;
-
- has_transport = session_has_transport ((session_t *) ll);
- if (!has_transport)
- {
- /* Local sessions don't have backing transport */
- ls->port = ll->port;
- sm = app_worker_get_local_segment_manager (server_wrk);
- }
- else
- {
- session_t *sl = (session_t *) ll;
- transport_connection_t *tc;
- tc = listen_session_get_transport (sl);
- ls->port = tc->lcl_port;
- sm = app_worker_get_listen_segment_manager (server_wrk, sl);
- }
-
- seg_index = segment_manager_add_segment (sm, seg_size);
- if (seg_index < 0)
- {
- clib_warning ("failed to add new cut-through segment");
- return seg_index;
- }
- seg = segment_manager_get_segment_w_lock (sm, seg_index);
- sq = segment_manager_alloc_queue (seg, props);
- cq = segment_manager_alloc_queue (seg, cprops);
-
- if (props->use_mq_eventfd)
- application_local_session_fix_eventds (sq, cq);
-
- ls->server_evt_q = pointer_to_uword (sq);
- ls->client_evt_q = pointer_to_uword (cq);
- rv = segment_manager_try_alloc_fifos (seg, props->rx_fifo_size,
- props->tx_fifo_size,
- &ls->rx_fifo, &ls->tx_fifo);
- if (rv)
- {
- clib_warning ("failed to add fifos in cut-through segment");
- segment_manager_segment_reader_unlock (sm);
- goto failed;
- }
- sm_index = segment_manager_index (sm);
- ls->rx_fifo->ct_session_index = ls->session_index;
- ls->tx_fifo->ct_session_index = ls->session_index;
- ls->rx_fifo->segment_manager = sm_index;
- ls->tx_fifo->segment_manager = sm_index;
- ls->rx_fifo->segment_index = seg_index;
- ls->tx_fifo->segment_index = seg_index;
- ls->svm_segment_index = seg_index;
- ls->listener_index = ll->session_index;
- ls->client_wrk_index = client_wrk->wrk_index;
- ls->client_opaque = opaque;
- ls->listener_session_type = ll->session_type;
- ls->session_state = SESSION_STATE_READY;
-
- segment_handle = segment_manager_segment_handle (sm, seg);
- if ((rv = server->cb_fns.add_segment_callback (server_wrk->api_client_index,
- segment_handle)))
- {
- clib_warning ("failed to notify server of new segment");
- segment_manager_segment_reader_unlock (sm);
- goto failed;
- }
- segment_manager_segment_reader_unlock (sm);
- if ((rv = server->cb_fns.session_accept_callback ((session_t *) ls)))
- {
- clib_warning ("failed to send accept cut-through notify to server");
- goto failed;
- }
- if (server->flags & APP_OPTIONS_FLAGS_IS_BUILTIN)
- app_worker_local_session_connect_notify (ls);
-
- return 0;
-
-failed:
- if (!has_transport)
- segment_manager_del_segment (sm, seg);
- return rv;
-}
-
-int
-app_worker_local_session_connect_notify (local_session_t * ls)
-{
- svm_fifo_segment_private_t *seg;
- app_worker_t *client_wrk, *server_wrk;
- segment_manager_t *sm;
- application_t *client;
- int rv, is_fail = 0;
- u64 segment_handle;
- u64 client_key;
-
- client_wrk = app_worker_get (ls->client_wrk_index);
- server_wrk = app_worker_get (ls->app_wrk_index);
- client = application_get (client_wrk->app_index);
-
- sm = app_worker_get_local_segment_manager_w_session (server_wrk, ls);
- seg = segment_manager_get_segment_w_lock (sm, ls->svm_segment_index);
- segment_handle = segment_manager_segment_handle (sm, seg);
- if ((rv = client->cb_fns.add_segment_callback (client_wrk->api_client_index,
- segment_handle)))
- {
- clib_warning ("failed to notify client %u of new segment",
- ls->client_wrk_index);
- segment_manager_segment_reader_unlock (sm);
- app_worker_local_session_disconnect (ls->client_wrk_index, ls);
- is_fail = 1;
- }
- else
- {
- segment_manager_segment_reader_unlock (sm);
- }
-
- client->cb_fns.session_connected_callback (client_wrk->wrk_index,
- ls->client_opaque,
- (session_t *) ls, is_fail);
-
- client_key = application_client_local_connect_key (ls);
- hash_set (client_wrk->local_connects, client_key, client_key);
- return 0;
-}
-
-int
-app_worker_local_session_disconnect (u32 app_index, local_session_t * ls)
-{
- app_worker_t *client_wrk, *server_wrk;
- u8 is_server = 0, is_client = 0;
- application_t *app;
-
- app = application_get_if_valid (app_index);
- if (!app)
- return 0;
-
- client_wrk = app_worker_get_if_valid (ls->client_wrk_index);
- server_wrk = app_worker_get (ls->app_wrk_index);
-
- if (server_wrk->app_index == app_index)
- is_server = 1;
- else if (client_wrk && client_wrk->app_index == app_index)
- is_client = 1;
-
- if (!is_server && !is_client)
- {
- clib_warning ("app %u is neither client nor server for session 0x%lx",
- app_index, application_local_session_handle (ls));
- return VNET_API_ERROR_INVALID_VALUE;
- }
-
- if (ls->session_state == SESSION_STATE_CLOSED)
- return app_worker_local_session_cleanup (client_wrk, server_wrk, ls);
-
- if (app_index == ls->client_wrk_index)
- {
- mq_send_local_session_disconnected_cb (ls->app_wrk_index, ls);
- }
- else
- {
- if (!client_wrk)
- {
- return app_worker_local_session_cleanup (client_wrk, server_wrk,
- ls);
- }
- else if (ls->session_state < SESSION_STATE_READY)
- {
- application_t *client = application_get (client_wrk->app_index);
- client->cb_fns.session_connected_callback (client_wrk->wrk_index,
- ls->client_opaque,
- (session_t *) ls,
- 1 /* is_fail */ );
- ls->session_state = SESSION_STATE_CLOSED;
- return app_worker_local_session_cleanup (client_wrk, server_wrk,
- ls);
- }
- else
- {
- mq_send_local_session_disconnected_cb (client_wrk->wrk_index, ls);
- }
- }
-
- ls->session_state = SESSION_STATE_CLOSED;
-
- return 0;
-}
-
-int
-app_worker_local_session_disconnect_w_index (u32 app_wrk_index, u32 ls_index)
-{
- app_worker_t *app_wrk;
- local_session_t *ls;
- app_wrk = app_worker_get (app_wrk_index);
- ls = app_worker_get_local_session (app_wrk, ls_index);
- return app_worker_local_session_disconnect (app_wrk_index, ls);
-}
-