session: allow builtin apps to register names

Change-Id: I4b428e170436671b329657283cf7653befc85c9f
Signed-off-by: Florin Coras <fcoras@cisco.com>
diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c
index 14169fa..0db52fe 100644
--- a/src/vnet/session/application.c
+++ b/src/vnet/session/application.c
@@ -28,6 +28,11 @@
  */
 static uword *app_by_api_client_index;
 
+/**
+ * Hash table of builtin apps by name
+ */
+static uword *app_by_name;
+
 static u8 *
 app_get_name_from_reg_index (application_t * app)
 {
@@ -43,6 +48,14 @@
   return app_name;
 }
 
+static u8 *
+app_get_name (application_t * app)
+{
+  if (!app->name)
+    return app_get_name_from_reg_index (app);
+  return app->name;
+}
+
 u32
 application_session_table (application_t * app, u8 fib_proto)
 {
@@ -104,13 +117,19 @@
 static void
 application_table_add (application_t * app)
 {
-  hash_set (app_by_api_client_index, app->api_client_index, app->index);
+  if (app->api_client_index != APP_INVALID_INDEX)
+    hash_set (app_by_api_client_index, app->api_client_index, app->index);
+  else if (app->name)
+    hash_set_mem (app_by_name, app->name, app->index);
 }
 
 static void
 application_table_del (application_t * app)
 {
-  hash_unset (app_by_api_client_index, app->api_client_index);
+  if (app->api_client_index != APP_INVALID_INDEX)
+    hash_unset (app_by_api_client_index, app->api_client_index);
+  else if (app->name)
+    hash_unset_mem (app_by_name, app->name);
 }
 
 application_t *
@@ -125,6 +144,17 @@
 }
 
 application_t *
+application_lookup_name (const u8 * name)
+{
+  uword *p;
+  p = hash_get_mem (app_by_name, name);
+  if (p)
+    return application_get (p[0]);
+
+  return 0;
+}
+
+application_t *
 application_new ()
 {
   application_t *app;
@@ -213,6 +243,7 @@
   vec_free (app->tls_key);
 
   application_table_del (app);
+  vec_free (app->name);
   pool_put (app_pool, app);
 }
 
@@ -257,8 +288,8 @@
 }
 
 int
-application_init (application_t * app, u32 api_client_index, u64 * options,
-		  session_cb_vft_t * cb_fns)
+application_init (application_t * app, u32 api_client_index, u8 * app_name,
+		  u64 * options, session_cb_vft_t * cb_fns)
 {
   ssvm_segment_type_t seg_type = SSVM_SEGMENT_MEMFD;
   u32 first_seg_size, prealloc_fifo_pairs;
@@ -328,6 +359,7 @@
   app->local_connects = hash_create (0, sizeof (u64));
   app->proxied_transports = options[APP_OPTIONS_PROXY_TRANSPORT];
   app->event_queue = segment_manager_event_queue (sm);
+  app->name = vec_dup (app_name);
 
   /* If no scope enabled, default to global */
   if (!application_has_global_scope (app)
@@ -1380,21 +1412,19 @@
 		    "API Client", "Namespace", "Add seg size", "Rx fifo size",
 		    "Tx fifo size");
       else
-	s =
-	  format (s, "%-10s%-20s%-15s%-40s", "Index", "Name", "API Client",
-		  "Namespace");
+	s = format (s, "%-10s%-20s%-15s%-40s", "Index", "Name", "API Client",
+		    "Namespace");
       return s;
     }
 
-  app_name = app_get_name_from_reg_index (app);
+  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, "%-10d%-20s%-15d%-15d%-15d%-15d%-15d", app->index, app_name,
-	      app->api_client_index, app->ns_index,
-	      props->add_segment_size,
-	      props->rx_fifo_size, props->tx_fifo_size);
+    s = format (s, "%-10d%-20s%-15d%-15d%-15d%-15d%-15d", app->index,
+		app_name, app->api_client_index, app->ns_index,
+		props->add_segment_size, props->rx_fifo_size,
+		props->tx_fifo_size);
   else
     s = format (s, "%-10d%-20s%-15d%-40s", app->index, app_name,
 		app->api_client_index, app_ns_name);
diff --git a/src/vnet/session/application.h b/src/vnet/session/application.h
index 4050cb4..9f3fc12 100644
--- a/src/vnet/session/application.h
+++ b/src/vnet/session/application.h
@@ -59,6 +59,9 @@
   /** Flags */
   u32 flags;
 
+  /** Name registered by builtin apps */
+  u8 *name;
+
   /*
    * Binary API interface to external app
    */
@@ -136,11 +139,12 @@
 
 application_t *application_new ();
 int application_init (application_t * app, u32 api_client_index,
-		      u64 * options, session_cb_vft_t * cb_fns);
+		      u8 * name, u64 * options, session_cb_vft_t * cb_fns);
 void application_del (application_t * app);
 application_t *application_get (u32 index);
 application_t *application_get_if_valid (u32 index);
 application_t *application_lookup (u32 api_client_index);
+application_t *application_lookup_name (const u8 * name);
 u32 application_get_index (application_t * app);
 
 int application_start_listen (application_t * app,
diff --git a/src/vnet/session/application_interface.c b/src/vnet/session/application_interface.c
index f069b28..ecdbe16 100644
--- a/src/vnet/session/application_interface.c
+++ b/src/vnet/session/application_interface.c
@@ -453,10 +453,17 @@
   u64 secret;
   int rv;
 
-  app = application_lookup (a->api_client_index);
+  if (a->api_client_index != APP_INVALID_INDEX)
+    app = application_lookup (a->api_client_index);
+  else if (a->name)
+    app = application_lookup_name (a->name);
+  else
+    return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
+				   "api index or name must be provided");
+
   if (app)
-    return clib_error_return_code (0, VNET_API_ERROR_APP_ALREADY_ATTACHED,
-				   0, "app already attached");
+    return clib_error_return_code (0, VNET_API_ERROR_APP_ALREADY_ATTACHED, 0,
+				   "app already attached");
 
   secret = a->options[APP_OPTIONS_NAMESPACE_SECRET];
   if ((rv = session_validate_namespace (a->namespace_id, secret,
@@ -464,7 +471,7 @@
     return clib_error_return_code (0, rv, 0, "namespace validation: %d", rv);
   a->options[APP_OPTIONS_NAMESPACE] = app_ns_index;
   app = application_new ();
-  if ((rv = application_init (app, a->api_client_index, a->options,
+  if ((rv = application_init (app, a->api_client_index, a->name, a->options,
 			      a->session_cb_vft)))
     return clib_error_return_code (0, rv, 0, "app init: %d", rv);
 
diff --git a/src/vnet/session/application_interface.h b/src/vnet/session/application_interface.h
index f72a461..5dc237f 100644
--- a/src/vnet/session/application_interface.h
+++ b/src/vnet/session/application_interface.h
@@ -28,6 +28,9 @@
   /** Binary API client index */
   u32 api_client_index;
 
+  /** Application name. Used by builtin apps */
+  u8 *name;
+
   /** Application and segment manager options */
   u64 *options;
 
diff --git a/src/vnet/session/session_test.c b/src/vnet/session/session_test.c
index ceac703..248b4d7 100644
--- a/src/vnet/session/session_test.c
+++ b/src/vnet/session/session_test.c
@@ -159,11 +159,13 @@
     .options = options,
     .namespace_id = 0,
     .session_cb_vft = &dummy_session_cbs,
+    .name = format (0, "session_test"),
   };
 
   error = vnet_application_attach (&attach_args);
   SESSION_TEST ((error == 0), "app attached");
   server_index = attach_args.app_index;
+  vec_free (attach_args.name);
 
   server_sep.is_ip4 = 1;
   vnet_bind_args_t bind_args = {
@@ -236,6 +238,7 @@
     .options = options,
     .namespace_id = 0,
     .session_cb_vft = &dummy_session_cbs,
+    .name = format (0, "session_test"),
   };
 
   vnet_bind_args_t bind_args = {
@@ -524,6 +527,7 @@
   /*
    * Cleanup
    */
+  vec_free (attach_args.name);
   vec_free (ns_id);
   session_delete_loopback (sw_if_index);
   return 0;
@@ -838,6 +842,7 @@
     .options = options,
     .namespace_id = 0,
     .session_cb_vft = &dummy_session_cbs,
+    .name = format (0, "session_test"),
   };
 
   vnet_bind_args_t bind_args = {
@@ -1356,6 +1361,7 @@
   vnet_application_detach (&detach_args);
 
   vec_free (ns_id);
+  vec_free (attach_args.name);
   return 0;
 }
 
@@ -1426,6 +1432,7 @@
     .options = options,
     .namespace_id = 0,
     .session_cb_vft = &dummy_session_cbs,
+    .name = format (0, "session_test"),
   };
 
   attach_args.api_client_index = dummy_server_api_index;
@@ -1481,6 +1488,7 @@
 		"local session endpoint lookup should not work after detach");
   if (verbose)
     unformat_free (&tmp_input);
+  vec_free (attach_args.name);
   return 0;
 }