summaryrefslogtreecommitdiffstats
path: root/src/vnet/session/application.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/session/application.c')
-rw-r--r--src/vnet/session/application.c111
1 files changed, 92 insertions, 19 deletions
diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c
index 1d7b3ad1125..72c57688e42 100644
--- a/src/vnet/session/application.c
+++ b/src/vnet/session/application.c
@@ -112,11 +112,11 @@ app_get_name_from_reg_index (application_t * app)
return app_name;
}
-static u8 *
+static const u8 *
app_get_name (application_t * app)
{
if (!app->name)
- return app_get_name_from_reg_index (app);
+ app->name = app_get_name_from_reg_index (app);
return app->name;
}
@@ -174,18 +174,27 @@ application_api_queue_is_full (application_t * app)
}
/**
- * Returns app name
- *
- * Since the name is not stored per app, we generate it on the fly. It is
- * the caller's responsibility to free the vector
+ * Returns app name for app-index
*/
-u8 *
+const u8 *
application_name_from_index (u32 app_index)
{
application_t *app = application_get (app_index);
if (!app)
return 0;
- return app_get_name_from_reg_index (app);
+ return app_get_name (app);
+}
+
+static void
+application_api_table_add (u32 app_index, u32 api_client_index)
+{
+ hash_set (app_main.app_by_api_client_index, api_client_index, app_index);
+}
+
+static void
+application_api_table_del (u32 api_client_index)
+{
+ hash_unset (app_main.app_by_api_client_index, api_client_index);
}
static void
@@ -213,7 +222,7 @@ application_lookup (u32 api_client_index)
uword *p;
p = hash_get (app_main.app_by_api_client_index, api_client_index);
if (p)
- return application_get (p[0]);
+ return application_get_if_valid (p[0]);
return 0;
}
@@ -440,6 +449,50 @@ application_free (application_t * app)
pool_put (app_main.app_pool, app);
}
+void
+application_detach_process (application_t * app, u32 api_client_index)
+{
+ vnet_app_worker_add_del_args_t _args = { 0 }, *args = &_args;
+ app_worker_map_t *wrk_map;
+ u32 *wrks = 0, *wrk_index;
+ app_worker_t *app_wrk;
+
+ if (api_client_index == ~0)
+ {
+ application_free (app);
+ return;
+ }
+
+ APP_DBG ("Detaching for app %v index %u api client index %u", app->name,
+ app->app_index, app->api_client_index);
+
+ /* *INDENT-OFF* */
+ pool_foreach (wrk_map, app->worker_maps, ({
+ app_wrk = app_worker_get (wrk_map->wrk_index);
+ if (app_wrk->api_index == api_client_index)
+ vec_add1 (wrks, app_wrk->wrk_index);
+ }));
+ /* *INDENT-ON* */
+
+ if (!vec_len (wrks))
+ {
+ clib_warning ("no workers for app %u api_index %u", app->app_index,
+ api_client_index);
+ return;
+ }
+
+ args->app_index = app->app_index;
+ args->api_index = api_client_index;
+ vec_foreach (wrk_index, wrks)
+ {
+ app_wrk = app_worker_get (wrk_index[0]);
+ args->wrk_index = app_wrk->wrk_map_index;
+ args->is_add = 0;
+ vnet_app_worker_add_del (args);
+ }
+ vec_free (wrks);
+}
+
app_worker_t *
application_get_worker (application_t * app, u32 wrk_map_index)
{
@@ -456,6 +509,12 @@ application_get_default_worker (application_t * app)
return application_get_worker (app, 0);
}
+u32
+application_n_workers (application_t * app)
+{
+ return pool_elts (app->worker_maps);
+}
+
app_worker_t *
application_listener_select_worker (stream_session_t * ls, u8 is_local)
{
@@ -609,6 +668,7 @@ app_worker_alloc_and_init (application_t * app, app_worker_t ** wrk)
app_wrk->listeners_table = hash_create (0, sizeof (u64));
app_wrk->event_queue = segment_manager_event_queue (sm);
app_wrk->app_is_builtin = application_is_builtin (app);
+ app_wrk->api_index = app->api_client_index;
/*
* Segment manager for local sessions
@@ -815,7 +875,8 @@ application_stop_listen (u32 app_index, u32 app_wrk_index,
app_listener = app_listener_get (app, listener->listener_db_index);
if (!clib_bitmap_get (app_listener->workers, app_wrk_index))
{
- clib_warning ("worker not listening on handle %lu", handle);
+ clib_warning ("worker %u not listening on handle %lu", app_wrk_index,
+ handle);
return 0;
}
@@ -899,6 +960,15 @@ vnet_app_worker_add_del (vnet_app_worker_add_del_args_t * a)
{
if ((rv = app_worker_alloc_and_init (app, &app_wrk)))
return clib_error_return_code (0, rv, 0, "app wrk init: %d", rv);
+
+ /* Map worker api index to the app */
+ if (a->api_index != app->api_client_index
+ && app->api_client_index != APP_INVALID_INDEX)
+ {
+ app_wrk->api_index = a->api_index;
+ application_api_table_add (app->app_index, a->api_index);
+ }
+
sm = segment_manager_get (app_wrk->first_segment_manager);
fs = segment_manager_get_segment_w_lock (sm, 0);
a->segment = &fs->ssvm;
@@ -914,11 +984,15 @@ vnet_app_worker_add_del (vnet_app_worker_add_del_args_t * a)
"App %u does not have worker %u",
app->app_index, a->wrk_index);
app_wrk = app_worker_get (wrk_map->wrk_index);
- app_worker_map_free (app, wrk_map);
if (!app_wrk)
return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
"No worker %u", a->wrk_index);
+ if (app->api_client_index != app_wrk->api_index)
+ application_api_table_del (app_wrk->api_index);
app_worker_free (app_wrk);
+ app_worker_map_free (app, wrk_map);
+ if (application_n_workers (app) == 0)
+ application_free (app);
}
return 0;
}
@@ -1916,7 +1990,8 @@ format_app_worker_listener (u8 * s, va_list * args)
int verbose = va_arg (*args, int);
stream_session_t *listener;
application_t *app;
- u8 *app_name, *str;
+ const u8 *app_name;
+ u8 *str;
if (!app_wrk)
{
@@ -1930,7 +2005,7 @@ format_app_worker_listener (u8 * s, va_list * args)
}
app = application_get (app_wrk->app_index);
- app_name = app_get_name_from_reg_index (app);
+ app_name = app_get_name (app);
listener = listen_session_get_from_handle (handle);
str = format (0, "%U", format_stream_session, listener, verbose);
@@ -1944,7 +2019,6 @@ format_app_worker_listener (u8 * s, va_list * args)
else
s = format (s, "%-40s%-25s%=10u", str, app_name, app_wrk->wrk_map_index);
- vec_free (app_name);
return s;
}
@@ -1983,8 +2057,9 @@ 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;
- u8 *app_name, *s = 0;
+ const u8 *app_name;
application_t *app;
+ u8 *s = 0;
/* Header */
if (!app_wrk)
@@ -2001,7 +2076,7 @@ app_worker_format_connects (app_worker_t * app_wrk, int verbose)
if (app_wrk->connects_seg_manager == (u32) ~ 0)
return;
- app_name = app_get_name_from_reg_index (app);
+ app_name = app_get_name (app);
/* Across all fifo segments */
sm = segment_manager_get (app_wrk->connects_seg_manager);
@@ -2039,7 +2114,6 @@ app_worker_format_connects (app_worker_t * app_wrk, int verbose)
}));
/* *INDENT-ON* */
- vec_free (app_name);
}
static void
@@ -2200,8 +2274,7 @@ 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;
- u8 *app_name;
+ const u8 *app_ns_name, *app_name;
if (app == 0)
{