+ s = format (s, "%-40s%-25s%=10s", "Connection", "App", "Wrk");
+
+ return s;
+ }
+
+ app_name = application_name_from_index (app_wrk->app_index);
+ listener = listen_session_get_from_handle (handle);
+ str = format (0, "%U", format_stream_session, listener, verbose);
+
+ if (verbose)
+ {
+ char buf[32];
+ sprintf (buf, "%u(%u)", app_wrk->wrk_map_index, app_wrk->wrk_index);
+ s = format (s, "%-40s%-25s%=10s%-15u%-15u%-10u", str, app_name,
+ buf, app_wrk->api_client_index, handle, sm_index);
+ }
+ else
+ s = format (s, "%-40s%-25s%=10u", str, app_name, app_wrk->wrk_map_index);
+
+ return s;
+}
+
+static void
+application_format_listeners (application_t * app, int verbose)
+{
+ vlib_main_t *vm = vlib_get_main ();
+ app_worker_map_t *wrk_map;
+ app_worker_t *app_wrk;
+ u32 sm_index;
+ u64 handle;
+
+ if (!app)
+ {
+ vlib_cli_output (vm, "%U", format_app_worker_listener, 0 /* header */ ,
+ 0, 0, verbose);
+ return;
+ }
+
+ /* *INDENT-OFF* */
+ pool_foreach (wrk_map, app->worker_maps, ({
+ app_wrk = app_worker_get (wrk_map->wrk_index);
+ if (hash_elts (app_wrk->listeners_table) == 0)
+ continue;
+ hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
+ vlib_cli_output (vm, "%U", format_app_worker_listener, app_wrk,
+ handle, sm_index, verbose);
+ }));
+ }));
+ /* *INDENT-ON* */
+}
+
+static void
+app_worker_format_connects (app_worker_t * app_wrk, int verbose)
+{
+ svm_fifo_segment_private_t *fifo_segment;
+ vlib_main_t *vm = vlib_get_main ();
+ segment_manager_t *sm;
+ const u8 *app_name;
+ u8 *s = 0;
+
+ /* Header */
+ if (!app_wrk)
+ {
+ if (verbose)
+ vlib_cli_output (vm, "%-40s%-20s%-15s%-10s", "Connection", "App",
+ "API Client", "SegManager");
+ else
+ vlib_cli_output (vm, "%-40s%-20s", "Connection", "App");
+ return;
+ }
+
+ if (app_wrk->connects_seg_manager == (u32) ~ 0)
+ return;
+
+ app_name = application_name_from_index (app_wrk->app_index);
+
+ /* Across all fifo segments */
+ sm = segment_manager_get (app_wrk->connects_seg_manager);
+
+ /* *INDENT-OFF* */
+ segment_manager_foreach_segment_w_lock (fifo_segment, sm, ({
+ svm_fifo_t *fifo;
+ u8 *str;
+
+ fifo = svm_fifo_segment_get_fifo_list (fifo_segment);
+ while (fifo)
+ {
+ u32 session_index, thread_index;
+ stream_session_t *session;
+
+ session_index = fifo->master_session_index;
+ thread_index = fifo->master_thread_index;
+
+ session = session_get (session_index, thread_index);
+ str = format (0, "%U", format_stream_session, session, verbose);
+
+ if (verbose)
+ s = format (s, "%-40s%-20s%-15u%-10u", str, app_name,
+ app_wrk->api_client_index, app_wrk->connects_seg_manager);
+ else
+ s = format (s, "%-40s%-20s", str, app_name);
+
+ vlib_cli_output (vm, "%v", s);
+ vec_reset_length (s);
+ vec_free (str);
+
+ fifo = fifo->next;
+ }
+ vec_free (s);
+ }));
+ /* *INDENT-ON* */
+
+}
+
+static void
+application_format_connects (application_t * app, int verbose)
+{
+ app_worker_map_t *wrk_map;
+ app_worker_t *app_wrk;
+
+ if (!app)
+ {
+ app_worker_format_connects (0, verbose);
+ return;
+ }
+
+ /* *INDENT-OFF* */
+ pool_foreach (wrk_map, app->worker_maps, ({
+ app_wrk = app_worker_get (wrk_map->wrk_index);
+ app_worker_format_connects (app_wrk, verbose);
+ }));
+ /* *INDENT-ON* */
+}
+
+static void
+app_worker_format_local_sessions (app_worker_t * app_wrk, int verbose)
+{
+ vlib_main_t *vm = vlib_get_main ();
+ local_session_t *ls;
+ transport_proto_t tp;
+ u8 *conn = 0;
+
+ /* Header */
+ if (app_wrk == 0)
+ {
+ vlib_cli_output (vm, "%-40s%-15s%-20s", "Connection", "ServerApp",
+ "ClientApp");
+ return;
+ }
+
+ if (!pool_elts (app_wrk->local_sessions)
+ && !pool_elts (app_wrk->local_connects))
+ return;
+
+ /* *INDENT-OFF* */
+ pool_foreach (ls, app_wrk->local_sessions, ({
+ tp = session_type_transport_proto(ls->listener_session_type);
+ conn = format (0, "[L][%U] *:%u", format_transport_proto_short, tp,
+ ls->port);
+ vlib_cli_output (vm, "%-40v%-15u%-20u", conn, ls->app_wrk_index,
+ ls->client_wrk_index);
+ vec_reset_length (conn);
+ }));
+ /* *INDENT-ON* */
+
+ vec_free (conn);
+}
+
+static void
+application_format_local_sessions (application_t * app, int verbose)
+{
+ vlib_main_t *vm = vlib_get_main ();
+ app_worker_map_t *wrk_map;
+ app_worker_t *app_wrk;
+ transport_proto_t tp;
+ local_session_t *ls;
+ u8 *conn = 0;
+
+ if (!app)
+ {
+ app_worker_format_local_sessions (0, verbose);
+ return;
+ }
+
+ /*
+ * Format local listeners
+ */
+
+ /* *INDENT-OFF* */
+ pool_foreach (ls, app->local_listen_sessions, ({
+ tp = session_type_transport_proto (ls->listener_session_type);
+ conn = format (0, "[L][%U] *:%u", format_transport_proto_short, tp,
+ ls->port);
+ vlib_cli_output (vm, "%-40v%-15u%-20s", conn, ls->app_wrk_index, "*");
+ vec_reset_length (conn);
+ }));
+ /* *INDENT-ON* */
+
+ /*
+ * Format local accepted/connected sessions
+ */
+ /* *INDENT-OFF* */
+ pool_foreach (wrk_map, app->worker_maps, ({
+ app_wrk = app_worker_get (wrk_map->wrk_index);
+ app_worker_format_local_sessions (app_wrk, verbose);
+ }));
+ /* *INDENT-ON* */
+}
+
+static void
+app_worker_format_local_connects (app_worker_t * app, int verbose)
+{
+ vlib_main_t *vm = vlib_get_main ();
+ u32 app_wrk_index, session_index;
+ app_worker_t *server_wrk;
+ local_session_t *ls;
+ uword client_key;
+ u64 value;
+
+ /* Header */
+ if (app == 0)
+ {
+ if (verbose)
+ vlib_cli_output (vm, "%-40s%-15s%-20s%-10s", "Connection", "App",
+ "Peer App", "SegManager");
+ else
+ vlib_cli_output (vm, "%-40s%-15s%-20s", "Connection", "App",
+ "Peer App");
+ return;
+ }
+
+ if (!app->local_connects)
+ return;
+
+ /* *INDENT-OFF* */
+ hash_foreach (client_key, value, app->local_connects, ({
+ application_client_local_connect_key_parse (client_key, &app_wrk_index,
+ &session_index);
+ server_wrk = app_worker_get (app_wrk_index);
+ ls = application_get_local_session (server_wrk, session_index);
+ vlib_cli_output (vm, "%-40s%-15s%-20s", "TODO", ls->app_wrk_index,
+ ls->client_wrk_index);
+ }));
+ /* *INDENT-ON* */
+}
+
+static void
+application_format_local_connects (application_t * app, int verbose)
+{
+ app_worker_map_t *wrk_map;
+ app_worker_t *app_wrk;
+
+ if (!app)
+ {
+ app_worker_format_local_connects (0, verbose);
+ return;
+ }
+
+ /* *INDENT-OFF* */
+ pool_foreach (wrk_map, app->worker_maps, ({
+ app_wrk = app_worker_get (wrk_map->wrk_index);
+ app_worker_format_local_connects (app_wrk, verbose);
+ }));
+ /* *INDENT-ON* */
+}
+
+u8 *
+format_application_worker (u8 * s, va_list * args)
+{
+ app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
+ u32 indent = 1;
+
+ s = format (s, "%U wrk-index %u app-index %u map-index %u "
+ "api-client-index %d\n", format_white_space, indent,
+ app_wrk->wrk_index, app_wrk->app_index, app_wrk->wrk_map_index,
+ app_wrk->api_client_index);
+ return s;
+}
+
+u8 *
+format_application (u8 * s, va_list * args)
+{
+ application_t *app = va_arg (*args, application_t *);
+ CLIB_UNUSED (int verbose) = va_arg (*args, int);
+ segment_manager_properties_t *props;
+ const u8 *app_ns_name, *app_name;
+ app_worker_map_t *wrk_map;
+ app_worker_t *app_wrk;
+
+ if (app == 0)
+ {
+ if (!verbose)
+ s = format (s, "%-10s%-20s%-40s", "Index", "Name", "Namespace");
+ return s;
+ }
+
+ app_name = app_get_name (app);
+ app_ns_name = app_namespace_id_from_index (app->ns_index);
+ props = application_segment_manager_properties (app);
+ if (!verbose)
+ {
+ s = format (s, "%-10u%-20s%-40s", app->app_index, app_name,
+ app_ns_name);
+ return s;
+ }
+
+ s = format (s, "app-name %s app-index %u ns-index %u seg-size %U\n",
+ app_name, app->app_index, app->ns_index,
+ format_memory_size, props->add_segment_size);
+ s = format (s, "rx-fifo-size %U tx-fifo-size %U workers:\n",
+ format_memory_size, props->rx_fifo_size,
+ format_memory_size, props->tx_fifo_size);
+
+ /* *INDENT-OFF* */
+ pool_foreach (wrk_map, app->worker_maps, ({
+ app_wrk = app_worker_get (wrk_map->wrk_index);
+ s = format (s, "%U", format_application_worker, app_wrk);
+ }));
+ /* *INDENT-ON* */
+
+ return s;
+}
+
+void
+application_format_all_listeners (vlib_main_t * vm, int do_local, int verbose)
+{
+ application_t *app;
+
+ if (!pool_elts (app_main.app_pool))
+ {
+ vlib_cli_output (vm, "No active server bindings");
+ return;
+ }
+
+ if (do_local)
+ {
+ application_format_local_sessions (0, verbose);
+ /* *INDENT-OFF* */
+ pool_foreach (app, app_main.app_pool, ({
+ application_format_local_sessions (app, verbose);
+ }));
+ /* *INDENT-ON* */
+ }
+ else
+ {
+ application_format_listeners (0, verbose);
+
+ /* *INDENT-OFF* */
+ pool_foreach (app, app_main.app_pool, ({
+ application_format_listeners (app, verbose);
+ }));
+ /* *INDENT-ON* */
+ }
+}
+
+void
+application_format_all_clients (vlib_main_t * vm, int do_local, int verbose)
+{
+ application_t *app;
+
+ if (!pool_elts (app_main.app_pool))
+ {
+ vlib_cli_output (vm, "No active apps");
+ return;
+ }
+
+ if (do_local)
+ {
+ application_format_local_connects (0, verbose);
+
+ /* *INDENT-OFF* */
+ pool_foreach (app, app_main.app_pool, ({
+ application_format_local_connects (app, verbose);
+ }));
+ /* *INDENT-ON* */
+ }
+ else
+ {
+ application_format_connects (0, verbose);
+
+ /* *INDENT-OFF* */
+ pool_foreach (app, app_main.app_pool, ({
+ application_format_connects (app, verbose);
+ }));
+ /* *INDENT-ON* */
+ }
+}
+
+static clib_error_t *
+show_app_command_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ int do_server = 0, do_client = 0, do_local = 0;
+ application_t *app;
+ u32 app_index = ~0;
+ int verbose = 0;
+
+ session_cli_return_if_not_enabled ();
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "server"))
+ do_server = 1;
+ else if (unformat (input, "client"))
+ do_client = 1;
+ else if (unformat (input, "local"))
+ do_local = 1;
+ else if (unformat (input, "%u", &app_index))
+ ;
+ else if (unformat (input, "verbose"))
+ verbose = 1;
+ else
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ }
+
+ if (do_server)
+ {
+ application_format_all_listeners (vm, do_local, verbose);
+ return 0;
+ }
+
+ if (do_client)
+ {
+ application_format_all_clients (vm, do_local, verbose);
+ return 0;
+ }
+
+ if (app_index != ~0)
+ {
+ app = application_get (app_index);
+ if (!app)
+ return clib_error_return (0, "No app with index %u", app_index);
+
+ vlib_cli_output (vm, "%U", format_application, app, /* verbose */ 1);
+ return 0;