session: cleanup application interface
Change-Id: I89d240753b3f3c5e984aa303a7c8fa35fa59bf7f
Signed-off-by: Florin Coras <fcoras@cisco.com>
diff --git a/src/plugins/unittest/session_test.c b/src/plugins/unittest/session_test.c
index 72cc9f8..fb1c54f 100644
--- a/src/plugins/unittest/session_test.c
+++ b/src/plugins/unittest/session_test.c
@@ -161,8 +161,8 @@
{
session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
u64 options[APP_OPTIONS_N_OPTIONS], bind4_handle, bind6_handle;
- clib_error_t *error = 0;
u32 server_index;
+ int error = 0;
clib_memset (options, 0, sizeof (options));
options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
@@ -203,7 +203,7 @@
error = vnet_listen (&bind_args);
SESSION_TEST ((error != 0), "double server bind6 should not work");
- vnet_unbind_args_t unbind_args = {
+ vnet_unlisten_args_t unbind_args = {
.handle = bind4_handle,
.app_index = server_index,
};
@@ -277,8 +277,8 @@
ip4_address_t intf_addr[3];
transport_connection_t *tc;
session_t *s;
- clib_error_t *error;
u8 *appns_id;
+ int error;
/*
* Create the loopbacks
@@ -306,8 +306,7 @@
.is_add = 1
};
error = vnet_app_namespace_add_del (&ns_args);
- SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
- clib_error_get_code (error));
+ SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
/*
* Attach client/server
@@ -424,13 +423,12 @@
session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
session_endpoint_t client_sep = SESSION_ENDPOINT_NULL;
session_endpoint_t intf_sep = SESSION_ENDPOINT_NULL;
- clib_error_t *error = 0;
u8 *ns_id = format (0, "appns1");
app_namespace_t *app_ns;
application_t *server;
session_t *s;
u64 handle;
- int code;
+ int error = 0;
server_sep.is_ip4 = 1;
server_sep.port = dummy_port;
@@ -458,7 +456,7 @@
};
clib_memcpy (&connect_args.sep, &client_sep, sizeof (client_sep));
- vnet_unbind_args_t unbind_args = {
+ vnet_unlisten_args_t unbind_args = {
.handle = bind_args.handle,
.app_index = 0,
};
@@ -487,8 +485,7 @@
.is_add = 1
};
error = vnet_app_namespace_add_del (&ns_args);
- SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
- clib_error_get_code (error));
+ SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
app_ns = app_namespace_get_from_id (ns_id);
SESSION_TEST ((app_ns != 0), "should find ns %v status", ns_id);
@@ -509,9 +506,8 @@
error = vnet_application_attach (&attach_args);
SESSION_TEST ((error != 0), "app attachment should fail");
- code = clib_error_get_code (error);
- SESSION_TEST ((code == VNET_API_ERROR_APP_WRONG_NS_SECRET),
- "code should be wrong ns secret: %d", code);
+ SESSION_TEST ((error == VNET_API_ERROR_APP_WRONG_NS_SECRET),
+ "code should be wrong ns secret: %d", error);
/*
* Attach server with global default scope
@@ -594,15 +590,13 @@
connect_args.app_index = client_index;
error = vnet_connect (&connect_args);
SESSION_TEST ((error != 0), "client connect should return error code");
- code = clib_error_get_code (error);
- SESSION_TEST ((code == VNET_API_ERROR_INVALID_VALUE),
+ SESSION_TEST ((error == VNET_API_ERROR_INVALID_VALUE),
"error code should be invalid value (zero ip)");
SESSION_TEST ((dummy_segment_count == 0),
"shouldn't have received request to map new segment");
connect_args.sep.ip.ip4.as_u8[0] = 127;
error = vnet_connect (&connect_args);
SESSION_TEST ((error == 0), "client connect should not return error code");
- code = clib_error_get_code (error);
SESSION_TEST ((dummy_segment_count == 1),
"should've received request to map new segment");
SESSION_TEST ((dummy_accept == 1), "should've received accept request");
@@ -616,8 +610,7 @@
SESSION_TEST ((error == 0), "client attachment should work");
error = vnet_connect (&connect_args);
SESSION_TEST ((error != 0), "client connect should return error code");
- code = clib_error_get_code (error);
- SESSION_TEST ((code == VNET_API_ERROR_SESSION_CONNECT),
+ SESSION_TEST ((error == VNET_API_ERROR_SESSION_CONNECT),
"error code should be connect (nothing in local scope)");
detach_args.app_index = client_index;
vnet_application_detach (&detach_args);
@@ -679,8 +672,7 @@
vnet_application_attach (&attach_args);
error = vnet_connect (&connect_args);
SESSION_TEST ((error != 0), "client connect should return error code");
- code = clib_error_get_code (error);
- SESSION_TEST ((code == VNET_API_ERROR_SESSION_CONNECT),
+ SESSION_TEST ((error == VNET_API_ERROR_SESSION_CONNECT),
"error code should be connect (not in same ns)");
detach_args.app_index = client_index;
vnet_application_detach (&detach_args);
@@ -701,8 +693,7 @@
*/
ns_args.sw_if_index = sw_if_index;
error = vnet_app_namespace_add_del (&ns_args);
- SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
- clib_error_get_code (error));
+ SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
/*
* Attach server with local and global scope
@@ -751,8 +742,7 @@
u16 lcl_port = 1234, rmt_port = 4321;
u32 action_index = 1, res;
ip4_address_t lcl_lkup, rmt_lkup;
- clib_error_t *error;
- int verbose = 0;
+ int verbose = 0, error;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
@@ -1023,14 +1013,14 @@
u32 dummy_server_api_index = ~0;
transport_connection_t *tc;
u32 dummy_port = 1111;
- clib_error_t *error = 0;
u8 is_filtered = 0, *ns_id = format (0, "appns1");
session_t *listener, *s;
app_namespace_t *default_ns = app_namespace_get_default ();
u32 local_ns_index = default_ns->local_table_index;
- int verbose = 0, rv;
+ int verbose = 0;
app_namespace_t *app_ns;
app_listener_t *al;
+ int error = 0;
u64 handle;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
@@ -1259,8 +1249,7 @@
/* Try connecting */
error = vnet_connect (&connect_args);
SESSION_TEST ((error != 0), "connect should fail");
- rv = clib_error_get_code (error);
- SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED),
+ SESSION_TEST ((error == VNET_API_ERROR_APP_CONNECT_FILTERED),
"connect should be filtered");
sep.ip.ip4.as_u32 -= 1 << 24;
@@ -1491,8 +1480,7 @@
.is_add = 1
};
error = vnet_app_namespace_add_del (&ns_args);
- SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
- clib_error_get_code (error));
+ SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
app_ns = app_namespace_get_from_id (ns_id);
attach_args.namespace_id = ns_id;
@@ -1535,8 +1523,7 @@
error = vnet_connect (&connect_args);
SESSION_TEST ((error != 0), "connect should fail");
- rv = clib_error_get_code (error);
- SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED),
+ SESSION_TEST ((error == VNET_API_ERROR_APP_CONNECT_FILTERED),
"connect should be filtered");
/*
@@ -1549,8 +1536,7 @@
connect_args.app_index = server_index;
error = vnet_connect (&connect_args);
SESSION_TEST ((error != 0), "connect should fail");
- rv = clib_error_get_code (error);
- SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED),
+ SESSION_TEST ((error == VNET_API_ERROR_APP_CONNECT_FILTERED),
"connect should be filtered");
args.table_args.is_add = 0;
@@ -1589,13 +1575,12 @@
unformat_input_t tmp_input;
u32 server_index, app_index;
u32 dummy_server_api_index = ~0, sw_if_index = 0;
- clib_error_t *error = 0;
u8 is_filtered = 0;
session_t *s;
transport_connection_t *tc;
u16 lcl_port = 1234, rmt_port = 4321;
app_namespace_t *app_ns;
- int verbose = 0;
+ int verbose = 0, error = 0;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
diff --git a/src/vnet/session-apps/echo_client.c b/src/vnet/session-apps/echo_client.c
index c39f787..8b7788f 100644
--- a/src/vnet/session-apps/echo_client.c
+++ b/src/vnet/session-apps/echo_client.c
@@ -511,7 +511,7 @@
echo_client_main_t *ecm = &echo_client_main;
vnet_app_attach_args_t _a, *a = &_a;
u64 options[16];
- clib_error_t *error = 0;
+ int rv;
clib_memset (a, 0, sizeof (*a));
clib_memset (options, 0, sizeof (options));
@@ -541,8 +541,8 @@
a->options = options;
a->namespace_id = appns_id;
- if ((error = vnet_application_attach (a)))
- return error;
+ if ((rv = vnet_application_attach (a)))
+ return clib_error_return (0, "attach returned %d", rv);
ecm->app_index = a->app_index;
return 0;
@@ -592,8 +592,7 @@
{
echo_client_main_t *ecm = &echo_client_main;
vnet_connect_args_t _a, *a = &_a;
- clib_error_t *error = 0;
- int i;
+ int i, rv;
clib_memset (a, 0, sizeof (*a));
for (i = 0; i < n_clients; i++)
@@ -602,8 +601,8 @@
a->api_context = i;
a->app_index = ecm->app_index;
- if ((error = vnet_connect_uri (a)))
- return error;
+ if ((rv = vnet_connect_uri (a)))
+ return clib_error_return (0, "connect returned: %d", rv);
/* Crude pacing for call setups */
if ((i % 4) == 0)
diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c
index 763ab35..e629215 100644
--- a/src/vnet/session/application.c
+++ b/src/vnet/session/application.c
@@ -20,6 +20,13 @@
static app_main_t app_main;
+#define app_interface_check_thread_and_barrier(_fn, _arg) \
+ if (PREDICT_FALSE (!vlib_thread_is_main_w_barrier ())) \
+ { \
+ vlib_rpc_call_main_thread (_fn, (u8 *) _arg, sizeof(*_arg)); \
+ return 0; \
+ }
+
static void
application_local_listener_session_endpoint (local_session_t * ll,
session_endpoint_t * sep)
@@ -415,7 +422,7 @@
return 0;
}
-application_t *
+static application_t *
application_alloc (void)
{
application_t *app;
@@ -482,7 +489,7 @@
return 1;
}
-int
+static int
application_alloc_and_init (app_init_args_t * a)
{
ssvm_segment_type_t seg_type = SSVM_SEGMENT_MEMFD;
@@ -567,7 +574,7 @@
return 0;
}
-void
+static void
application_free (application_t * app)
{
app_worker_map_t *wrk_map;
@@ -624,7 +631,7 @@
pool_put (app_main.app_pool, app);
}
-void
+static void
application_detach_process (application_t * app, u32 api_client_index)
{
vnet_app_worker_add_del_args_t _args = { 0 }, *args = &_args;
@@ -748,6 +755,438 @@
}
int
+vnet_app_worker_add_del (vnet_app_worker_add_del_args_t * a)
+{
+ svm_fifo_segment_private_t *fs;
+ app_worker_map_t *wrk_map;
+ app_worker_t *app_wrk;
+ segment_manager_t *sm;
+ application_t *app;
+ int rv;
+
+ app = application_get (a->app_index);
+ if (!app)
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ if (a->is_add)
+ {
+ if ((rv = application_alloc_worker_and_init (app, &app_wrk)))
+ return rv;
+
+ /* Map worker api index to the app */
+ app_wrk->api_client_index = a->api_client_index;
+ application_api_table_add (app->app_index, a->api_client_index);
+
+ sm = segment_manager_get (app_wrk->first_segment_manager);
+ fs = segment_manager_get_segment_w_lock (sm, 0);
+ a->segment = &fs->ssvm;
+ a->segment_handle = segment_manager_segment_handle (sm, fs);
+ segment_manager_segment_reader_unlock (sm);
+ a->evt_q = app_wrk->event_queue;
+ a->wrk_map_index = app_wrk->wrk_map_index;
+ }
+ else
+ {
+ wrk_map = app_worker_map_get (app, a->wrk_map_index);
+ if (!wrk_map)
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ app_wrk = app_worker_get (wrk_map->wrk_index);
+ if (!app_wrk)
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ application_api_table_del (app_wrk->api_client_index);
+ app_worker_free (app_wrk);
+ app_worker_map_free (app, wrk_map);
+ if (application_n_workers (app) == 0)
+ application_free (app);
+ }
+ return 0;
+}
+
+static int
+app_validate_namespace (u8 * namespace_id, u64 secret, u32 * app_ns_index)
+{
+ app_namespace_t *app_ns;
+ if (vec_len (namespace_id) == 0)
+ {
+ /* Use default namespace */
+ *app_ns_index = 0;
+ return 0;
+ }
+
+ *app_ns_index = app_namespace_index_from_id (namespace_id);
+ if (*app_ns_index == APP_NAMESPACE_INVALID_INDEX)
+ return VNET_API_ERROR_APP_INVALID_NS;
+ app_ns = app_namespace_get (*app_ns_index);
+ if (!app_ns)
+ return VNET_API_ERROR_APP_INVALID_NS;
+ if (app_ns->ns_secret != secret)
+ return VNET_API_ERROR_APP_WRONG_NS_SECRET;
+ return 0;
+}
+
+static u8 *
+app_name_from_api_index (u32 api_client_index)
+{
+ vl_api_registration_t *regp;
+ regp = vl_api_client_index_to_registration (api_client_index);
+ if (regp)
+ return format (0, "%s%c", regp->name, 0);
+
+ clib_warning ("api client index %u does not have an api registration!",
+ api_client_index);
+ return format (0, "unknown%c", 0);
+}
+
+/**
+ * Attach application to vpp
+ *
+ * Allocates a vpp app, i.e., a structure that keeps back pointers
+ * to external app and a segment manager for shared memory fifo based
+ * communication with the external app.
+ */
+int
+vnet_application_attach (vnet_app_attach_args_t * a)
+{
+ svm_fifo_segment_private_t *fs;
+ application_t *app = 0;
+ app_worker_t *app_wrk;
+ segment_manager_t *sm;
+ u32 app_ns_index = 0;
+ u8 *app_name = 0;
+ u64 secret;
+ int rv;
+
+ 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 VNET_API_ERROR_INVALID_VALUE;
+
+ if (app)
+ return VNET_API_ERROR_APP_ALREADY_ATTACHED;
+
+ if (a->api_client_index != APP_INVALID_INDEX)
+ {
+ app_name = app_name_from_api_index (a->api_client_index);
+ a->name = app_name;
+ }
+
+ secret = a->options[APP_OPTIONS_NAMESPACE_SECRET];
+ if ((rv = app_validate_namespace (a->namespace_id, secret, &app_ns_index)))
+ return rv;
+ a->options[APP_OPTIONS_NAMESPACE] = app_ns_index;
+
+ if ((rv = application_alloc_and_init ((app_init_args_t *) a)))
+ return rv;
+
+ app = application_get (a->app_index);
+ if ((rv = application_alloc_worker_and_init (app, &app_wrk)))
+ return rv;
+
+ a->app_evt_q = app_wrk->event_queue;
+ app_wrk->api_client_index = a->api_client_index;
+ sm = segment_manager_get (app_wrk->first_segment_manager);
+ fs = segment_manager_get_segment_w_lock (sm, 0);
+
+ if (application_is_proxy (app))
+ application_setup_proxy (app);
+
+ ASSERT (vec_len (fs->ssvm.name) <= 128);
+ a->segment = &fs->ssvm;
+ a->segment_handle = segment_manager_segment_handle (sm, fs);
+
+ segment_manager_segment_reader_unlock (sm);
+ vec_free (app_name);
+ return 0;
+}
+
+/**
+ * Detach application from vpp
+ */
+int
+vnet_application_detach (vnet_app_detach_args_t * a)
+{
+ application_t *app;
+
+ app = application_get_if_valid (a->app_index);
+ if (!app)
+ {
+ clib_warning ("app not attached");
+ return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
+ }
+
+ app_interface_check_thread_and_barrier (vnet_application_detach, a);
+ application_detach_process (app, a->api_client_index);
+ return 0;
+}
+
+
+static u8
+session_endpoint_in_ns (session_endpoint_t * sep)
+{
+ u8 is_lep = session_endpoint_is_local (sep);
+ if (!is_lep && sep->sw_if_index != ENDPOINT_INVALID_INDEX
+ && !ip_interface_has_address (sep->sw_if_index, &sep->ip, sep->is_ip4))
+ {
+ clib_warning ("sw_if_index %u not configured with ip %U",
+ sep->sw_if_index, format_ip46_address, &sep->ip,
+ sep->is_ip4);
+ return 0;
+ }
+ return (is_lep || ip_is_local (sep->fib_index, &sep->ip, sep->is_ip4));
+}
+
+static void
+session_endpoint_update_for_app (session_endpoint_cfg_t * sep,
+ application_t * app, u8 is_connect)
+{
+ app_namespace_t *app_ns;
+ u32 ns_index, fib_index;
+
+ ns_index = app->ns_index;
+
+ /* App is a transport proto, so fetch the calling app's ns */
+ if (app->flags & APP_OPTIONS_FLAGS_IS_TRANSPORT_APP)
+ {
+ app_worker_t *owner_wrk;
+ application_t *owner_app;
+
+ owner_wrk = app_worker_get (sep->app_wrk_index);
+ owner_app = application_get (owner_wrk->app_index);
+ ns_index = owner_app->ns_index;
+ }
+ app_ns = app_namespace_get (ns_index);
+ if (!app_ns)
+ return;
+
+ /* Ask transport and network to bind to/connect using local interface
+ * that "supports" app's namespace. This will fix our local connection
+ * endpoint.
+ */
+
+ /* If in default namespace and user requested a fib index use it */
+ if (ns_index == 0 && sep->fib_index != ENDPOINT_INVALID_INDEX)
+ fib_index = sep->fib_index;
+ else
+ fib_index = sep->is_ip4 ? app_ns->ip4_fib_index : app_ns->ip6_fib_index;
+ sep->peer.fib_index = fib_index;
+ sep->fib_index = fib_index;
+
+ if (!is_connect)
+ {
+ sep->sw_if_index = app_ns->sw_if_index;
+ }
+ else
+ {
+ if (app_ns->sw_if_index != APP_NAMESPACE_INVALID_INDEX
+ && sep->peer.sw_if_index != ENDPOINT_INVALID_INDEX
+ && sep->peer.sw_if_index != app_ns->sw_if_index)
+ clib_warning ("Local sw_if_index different from app ns sw_if_index");
+
+ sep->peer.sw_if_index = app_ns->sw_if_index;
+ }
+}
+
+int
+vnet_listen (vnet_listen_args_t * a)
+{
+ app_listener_t *app_listener;
+ app_worker_t *app_wrk;
+ application_t *app;
+ int rv;
+
+ app = application_get_if_valid (a->app_index);
+ if (!app)
+ return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
+
+ app_wrk = application_get_worker (app, a->wrk_map_index);
+ if (!app_wrk)
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ a->sep_ext.app_wrk_index = app_wrk->wrk_index;
+
+ session_endpoint_update_for_app (&a->sep_ext, app, 0 /* is_connect */ );
+ if (!session_endpoint_in_ns (&a->sep))
+ return VNET_API_ERROR_INVALID_VALUE_2;
+
+ /*
+ * Check if we already have an app listener
+ */
+ app_listener = app_listener_lookup (app, &a->sep_ext);
+ if (app_listener)
+ {
+ if (app_listener->app_index != app->app_index)
+ return VNET_API_ERROR_ADDRESS_IN_USE;
+ if (app_worker_start_listen (app_wrk, app_listener))
+ return -1;
+ a->handle = app_listener_handle (app_listener);
+ return 0;
+ }
+
+ /*
+ * Create new app listener
+ */
+ if ((rv = app_listener_alloc_and_init (app, &a->sep_ext, &app_listener)))
+ return rv;
+
+ if ((rv = app_worker_start_listen (app_wrk, app_listener)))
+ {
+ app_listener_cleanup (app_listener);
+ return rv;
+ }
+
+ a->handle = app_listener_handle (app_listener);
+ return 0;
+}
+
+int
+vnet_connect (vnet_connect_args_t * a)
+{
+ app_worker_t *server_wrk, *client_wrk;
+ application_t *client;
+ local_session_t *ll;
+ app_listener_t *al;
+ u32 table_index;
+ session_t *ls;
+ u8 fib_proto;
+ u64 lh;
+
+ if (session_endpoint_is_zero (&a->sep))
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ client = application_get (a->app_index);
+ session_endpoint_update_for_app (&a->sep_ext, client, 1 /* is_connect */ );
+ client_wrk = application_get_worker (client, a->wrk_map_index);
+
+ /*
+ * First check the local scope for locally attached destinations.
+ * If we have local scope, we pass *all* connects through it since we may
+ * have special policy rules even for non-local destinations, think proxy.
+ */
+ if (application_has_local_scope (client))
+ {
+ table_index = application_local_session_table (client);
+ lh = session_lookup_local_endpoint (table_index, &a->sep);
+ if (lh == SESSION_DROP_HANDLE)
+ return VNET_API_ERROR_APP_CONNECT_FILTERED;
+
+ if (lh == SESSION_INVALID_HANDLE)
+ goto global_scope;
+
+ ll = application_get_local_listener_w_handle (lh);
+ al = app_listener_get_w_session ((session_t *) ll);
+
+ /*
+ * Break loop if rule in local table points to connecting app. This
+ * can happen if client is a generic proxy. Route connect through
+ * global table instead.
+ */
+ if (al->app_index == a->app_index)
+ goto global_scope;
+
+ server_wrk = app_listener_select_worker (al);
+ return app_worker_local_session_connect (client_wrk, server_wrk, ll,
+ a->api_context);
+ }
+
+ /*
+ * If nothing found, check the global scope for locally attached
+ * destinations. Make sure first that we're allowed to.
+ */
+
+global_scope:
+ if (session_endpoint_is_local (&a->sep))
+ return VNET_API_ERROR_SESSION_CONNECT;
+
+ if (!application_has_global_scope (client))
+ return VNET_API_ERROR_APP_CONNECT_SCOPE;
+
+ fib_proto = session_endpoint_fib_proto (&a->sep);
+ table_index = application_session_table (client, fib_proto);
+ ls = session_lookup_listener (table_index, &a->sep);
+ if (ls)
+ {
+ al = app_listener_get_w_session (ls);
+ server_wrk = app_listener_select_worker (al);
+ ll = (local_session_t *) ls;
+ return app_worker_local_session_connect (client_wrk, server_wrk, ll,
+ a->api_context);
+ }
+
+ /*
+ * Not connecting to a local server, propagate to transport
+ */
+ if (app_worker_connect_session (client_wrk, &a->sep, a->api_context))
+ return VNET_API_ERROR_SESSION_CONNECT;
+ return 0;
+}
+
+int
+vnet_unlisten (vnet_unlisten_args_t * a)
+{
+ app_worker_t *app_wrk;
+ app_listener_t *al;
+ application_t *app;
+
+ if (!(app = application_get_if_valid (a->app_index)))
+ return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
+
+ al = app_listener_get_w_handle (a->handle);
+ if (al->app_index != app->app_index)
+ {
+ clib_warning ("app doesn't own handle %llu!", a->handle);
+ return -1;
+ }
+
+ app_wrk = application_get_worker (app, a->wrk_map_index);
+ if (!app_wrk)
+ {
+ clib_warning ("no app %u worker %u", app->app_index, a->wrk_map_index);
+ return -1;
+ }
+
+ return app_worker_stop_listen (app_wrk, al);
+}
+
+int
+vnet_disconnect_session (vnet_disconnect_args_t * a)
+{
+ if (session_handle_is_local (a->handle))
+ {
+ local_session_t *ls;
+
+ /* Disconnect reply came to worker 1 not main thread */
+ app_interface_check_thread_and_barrier (vnet_disconnect_session, a);
+
+ if (!(ls = app_worker_get_local_session_from_handle (a->handle)))
+ return 0;
+
+ return app_worker_local_session_disconnect (a->app_index, ls);
+ }
+ else
+ {
+ app_worker_t *app_wrk;
+ session_t *s;
+
+ s = session_get_from_handle_if_valid (a->handle);
+ if (!s)
+ return VNET_API_ERROR_INVALID_VALUE;
+ app_wrk = app_worker_get (s->app_wrk_index);
+ if (app_wrk->app_index != a->app_index)
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ /* We're peeking into another's thread pool. Make sure */
+ ASSERT (s->session_index == session_index_from_handle (a->handle));
+
+ session_close (s);
+ }
+ return 0;
+}
+
+int
application_change_listener_owner (session_t * s, app_worker_t * app_wrk)
{
app_worker_t *old_wrk = app_worker_get (s->app_wrk_index);
@@ -781,58 +1220,6 @@
return 0;
}
-clib_error_t *
-vnet_app_worker_add_del (vnet_app_worker_add_del_args_t * a)
-{
- svm_fifo_segment_private_t *fs;
- app_worker_map_t *wrk_map;
- app_worker_t *app_wrk;
- segment_manager_t *sm;
- application_t *app;
- int rv;
-
- app = application_get (a->app_index);
- if (!app)
- return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
- "App %u does not exist", a->app_index);
-
- if (a->is_add)
- {
- if ((rv = application_alloc_worker_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 */
- app_wrk->api_client_index = a->api_client_index;
- application_api_table_add (app->app_index, a->api_client_index);
-
- sm = segment_manager_get (app_wrk->first_segment_manager);
- fs = segment_manager_get_segment_w_lock (sm, 0);
- a->segment = &fs->ssvm;
- a->segment_handle = segment_manager_segment_handle (sm, fs);
- segment_manager_segment_reader_unlock (sm);
- a->evt_q = app_wrk->event_queue;
- a->wrk_map_index = app_wrk->wrk_map_index;
- }
- else
- {
- wrk_map = app_worker_map_get (app, a->wrk_map_index);
- if (!wrk_map)
- return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
- "App %u does not have worker %u",
- app->app_index, a->wrk_map_index);
- app_wrk = app_worker_get (wrk_map->wrk_index);
- if (!app_wrk)
- return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
- "No worker %u", a->wrk_map_index);
- application_api_table_del (app_wrk->api_client_index);
- app_worker_free (app_wrk);
- app_worker_map_free (app, wrk_map);
- if (application_n_workers (app) == 0)
- application_free (app);
- }
- return 0;
-}
-
int
application_is_proxy (application_t * app)
{
diff --git a/src/vnet/session/application.h b/src/vnet/session/application.h
index d641263..0eaca8b 100644
--- a/src/vnet/session/application.h
+++ b/src/vnet/session/application.h
@@ -16,9 +16,10 @@
#ifndef SRC_VNET_SESSION_APPLICATION_H_
#define SRC_VNET_SESSION_APPLICATION_H_
+#include <vnet/session/application_interface.h>
+#include <vnet/session/application_namespace.h>
#include <vnet/session/session_types.h>
#include <vnet/session/segment_manager.h>
-#include <vnet/session/application_namespace.h>
#define APP_DEBUG 0
@@ -28,35 +29,6 @@
#define APP_DBG(_fmt, _args...)
#endif
-typedef struct _stream_session_cb_vft
-{
- /** Notify server of new segment */
- int (*add_segment_callback) (u32 api_client_index, u64 segment_handle);
-
- /** Notify server of new segment */
- int (*del_segment_callback) (u32 api_client_index, u64 segment_handle);
-
- /** Notify server of newly accepted session */
- int (*session_accept_callback) (session_t * new_session);
-
- /** Connection request callback */
- int (*session_connected_callback) (u32 app_wrk_index, u32 opaque,
- session_t * s, u8 code);
-
- /** Notify app that session is closing */
- void (*session_disconnect_callback) (session_t * s);
-
- /** Notify app that session was reset */
- void (*session_reset_callback) (session_t * s);
-
- /** Direct RX callback for built-in application */
- int (*builtin_app_rx_callback) (session_t * session);
-
- /** Direct TX callback for built-in application */
- int (*builtin_app_tx_callback) (session_t * session);
-
-} session_cb_vft_t;
-
typedef struct app_worker_
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
@@ -188,14 +160,6 @@
uword *app_by_name;
} app_main_t;
-#define foreach_app_init_args \
- _(u32, api_client_index) \
- _(u8 *, name) \
- _(u64 *, options) \
- _(u8 *, namespace_id) \
- _(session_cb_vft_t *, session_cb_vft) \
- _(u32, app_index) \
-
typedef struct app_init_args_
{
#define _(_type, _name) _type _name;
@@ -231,10 +195,6 @@
app_worker_t *app_listener_select_worker (app_listener_t * al);
session_t *app_listener_get_session (app_listener_t * al);
-application_t *application_alloc (void);
-int application_alloc_and_init (app_init_args_t * args);
-void application_free (application_t * app);
-void application_detach_process (application_t * app, u32 api_client_index);
application_t *application_get (u32 index);
application_t *application_get_if_valid (u32 index);
application_t *application_lookup (u32 api_client_index);
@@ -296,7 +256,7 @@
u8 *format_app_worker (u8 * s, va_list * args);
u8 *format_app_worker_listener (u8 * s, va_list * args);
void app_worker_format_connects (app_worker_t * app_wrk, int verbose);
-clib_error_t *vnet_app_worker_add_del (vnet_app_worker_add_del_args_t * a);
+int vnet_app_worker_add_del (vnet_app_worker_add_del_args_t * a);
/*
* Local session
diff --git a/src/vnet/session/application_interface.c b/src/vnet/session/application_interface.c
index 500bb48..ae00292 100644
--- a/src/vnet/session/application_interface.c
+++ b/src/vnet/session/application_interface.c
@@ -13,267 +13,13 @@
* limitations under the License.
*/
#include <vnet/session/application_interface.h>
+#include <vnet/session/application.h>
#include <vnet/session/session.h>
-#include <vlibmemory/api.h>
/** @file
VPP's application/session API bind/unbind/connect/disconnect calls
*/
-#define app_interface_check_thread_and_barrier(_fn, _arg) \
- if (PREDICT_FALSE (!vlib_thread_is_main_w_barrier ())) \
- { \
- vlib_rpc_call_main_thread (_fn, (u8 *) _arg, sizeof(*_arg)); \
- return 0; \
- }
-
-u8
-session_endpoint_in_ns (session_endpoint_t * sep)
-{
- u8 is_lep = session_endpoint_is_local (sep);
- if (!is_lep && sep->sw_if_index != ENDPOINT_INVALID_INDEX
- && !ip_interface_has_address (sep->sw_if_index, &sep->ip, sep->is_ip4))
- {
- clib_warning ("sw_if_index %u not configured with ip %U",
- sep->sw_if_index, format_ip46_address, &sep->ip,
- sep->is_ip4);
- return 0;
- }
- return (is_lep || ip_is_local (sep->fib_index, &sep->ip, sep->is_ip4));
-}
-
-int
-api_parse_session_handle (u64 handle, u32 * session_index, u32 * thread_index)
-{
- session_manager_main_t *smm = vnet_get_session_manager_main ();
- session_t *pool;
-
- *thread_index = handle & 0xFFFFFFFF;
- *session_index = handle >> 32;
-
- if (*thread_index >= vec_len (smm->wrk))
- return VNET_API_ERROR_INVALID_VALUE;
-
- pool = smm->wrk[*thread_index].sessions;
-
- if (pool_is_free_index (pool, *session_index))
- return VNET_API_ERROR_INVALID_VALUE_2;
-
- return 0;
-}
-
-static void
-session_endpoint_update_for_app (session_endpoint_cfg_t * sep,
- application_t * app, u8 is_connect)
-{
- app_namespace_t *app_ns;
- u32 ns_index, fib_index;
-
- ns_index = app->ns_index;
-
- /* App is a transport proto, so fetch the calling app's ns */
- if (app->flags & APP_OPTIONS_FLAGS_IS_TRANSPORT_APP)
- {
- app_worker_t *owner_wrk;
- application_t *owner_app;
-
- owner_wrk = app_worker_get (sep->app_wrk_index);
- owner_app = application_get (owner_wrk->app_index);
- ns_index = owner_app->ns_index;
- }
- app_ns = app_namespace_get (ns_index);
- if (!app_ns)
- return;
-
- /* Ask transport and network to bind to/connect using local interface
- * that "supports" app's namespace. This will fix our local connection
- * endpoint.
- */
-
- /* If in default namespace and user requested a fib index use it */
- if (ns_index == 0 && sep->fib_index != ENDPOINT_INVALID_INDEX)
- fib_index = sep->fib_index;
- else
- fib_index = sep->is_ip4 ? app_ns->ip4_fib_index : app_ns->ip6_fib_index;
- sep->peer.fib_index = fib_index;
- sep->fib_index = fib_index;
-
- if (!is_connect)
- {
- sep->sw_if_index = app_ns->sw_if_index;
- }
- else
- {
- if (app_ns->sw_if_index != APP_NAMESPACE_INVALID_INDEX
- && sep->peer.sw_if_index != ENDPOINT_INVALID_INDEX
- && sep->peer.sw_if_index != app_ns->sw_if_index)
- clib_warning ("Local sw_if_index different from app ns sw_if_index");
-
- sep->peer.sw_if_index = app_ns->sw_if_index;
- }
-}
-
-static inline int
-vnet_listen_inline (vnet_listen_args_t * a)
-{
- app_listener_t *app_listener;
- app_worker_t *app_wrk;
- application_t *app;
- int rv;
-
- app = application_get_if_valid (a->app_index);
- if (!app)
- return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
-
- app_wrk = application_get_worker (app, a->wrk_map_index);
- if (!app_wrk)
- return VNET_API_ERROR_INVALID_VALUE;
-
- a->sep_ext.app_wrk_index = app_wrk->wrk_index;
-
- session_endpoint_update_for_app (&a->sep_ext, app, 0 /* is_connect */ );
- if (!session_endpoint_in_ns (&a->sep))
- return VNET_API_ERROR_INVALID_VALUE_2;
-
- /*
- * Check if we already have an app listener
- */
- app_listener = app_listener_lookup (app, &a->sep_ext);
- if (app_listener)
- {
- if (app_listener->app_index != app->app_index)
- return VNET_API_ERROR_ADDRESS_IN_USE;
- if (app_worker_start_listen (app_wrk, app_listener))
- return -1;
- a->handle = app_listener_handle (app_listener);
- return 0;
- }
-
- /*
- * Create new app listener
- */
- if ((rv = app_listener_alloc_and_init (app, &a->sep_ext, &app_listener)))
- return rv;
-
- if ((rv = app_worker_start_listen (app_wrk, app_listener)))
- {
- app_listener_cleanup (app_listener);
- return rv;
- }
-
- a->handle = app_listener_handle (app_listener);
- return 0;
-}
-
-static inline int
-vnet_unlisten_inline (vnet_unbind_args_t * a)
-{
- app_worker_t *app_wrk;
- app_listener_t *al;
- application_t *app;
-
- if (!(app = application_get_if_valid (a->app_index)))
- return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
-
- al = app_listener_get_w_handle (a->handle);
- if (al->app_index != app->app_index)
- {
- clib_warning ("app doesn't own handle %llu!", a->handle);
- return -1;
- }
-
- app_wrk = application_get_worker (app, a->wrk_map_index);
- if (!app_wrk)
- {
- clib_warning ("no app %u worker %u", app->app_index, a->wrk_map_index);
- return -1;
- }
-
- return app_worker_stop_listen (app_wrk, al);
-}
-
-static int
-application_connect (vnet_connect_args_t * a)
-{
- app_worker_t *server_wrk, *client_wrk;
- application_t *client;
- local_session_t *ll;
- app_listener_t *al;
- u32 table_index;
- session_t *ls;
- u8 fib_proto;
- u64 lh;
-
- if (session_endpoint_is_zero (&a->sep))
- return VNET_API_ERROR_INVALID_VALUE;
-
- client = application_get (a->app_index);
- session_endpoint_update_for_app (&a->sep_ext, client, 1 /* is_connect */ );
- client_wrk = application_get_worker (client, a->wrk_map_index);
-
- /*
- * First check the local scope for locally attached destinations.
- * If we have local scope, we pass *all* connects through it since we may
- * have special policy rules even for non-local destinations, think proxy.
- */
- if (application_has_local_scope (client))
- {
- table_index = application_local_session_table (client);
- lh = session_lookup_local_endpoint (table_index, &a->sep);
- if (lh == SESSION_DROP_HANDLE)
- return VNET_API_ERROR_APP_CONNECT_FILTERED;
-
- if (lh == SESSION_INVALID_HANDLE)
- goto global_scope;
-
- ll = application_get_local_listener_w_handle (lh);
- al = app_listener_get_w_session ((session_t *) ll);
-
- /*
- * Break loop if rule in local table points to connecting app. This
- * can happen if client is a generic proxy. Route connect through
- * global table instead.
- */
- if (al->app_index == a->app_index)
- goto global_scope;
-
- server_wrk = app_listener_select_worker (al);
- return app_worker_local_session_connect (client_wrk, server_wrk, ll,
- a->api_context);
- }
-
- /*
- * If nothing found, check the global scope for locally attached
- * destinations. Make sure first that we're allowed to.
- */
-
-global_scope:
- if (session_endpoint_is_local (&a->sep))
- return VNET_API_ERROR_SESSION_CONNECT;
-
- if (!application_has_global_scope (client))
- return VNET_API_ERROR_APP_CONNECT_SCOPE;
-
- fib_proto = session_endpoint_fib_proto (&a->sep);
- table_index = application_session_table (client, fib_proto);
- ls = session_lookup_listener (table_index, &a->sep);
- if (ls)
- {
- al = app_listener_get_w_session (ls);
- server_wrk = app_listener_select_worker (al);
- ll = (local_session_t *) ls;
- return app_worker_local_session_connect (client_wrk, server_wrk, ll,
- a->api_context);
- }
-
- /*
- * Not connecting to a local server, propagate to transport
- */
- if (app_worker_connect_session (client_wrk, &a->sep, a->api_context))
- return VNET_API_ERROR_SESSION_CONNECT;
- return 0;
-}
-
/**
* unformat a vnet URI
*
@@ -371,127 +117,6 @@
return 0;
}
-static int
-app_validate_namespace (u8 * namespace_id, u64 secret, u32 * app_ns_index)
-{
- app_namespace_t *app_ns;
- if (vec_len (namespace_id) == 0)
- {
- /* Use default namespace */
- *app_ns_index = 0;
- return 0;
- }
-
- *app_ns_index = app_namespace_index_from_id (namespace_id);
- if (*app_ns_index == APP_NAMESPACE_INVALID_INDEX)
- return VNET_API_ERROR_APP_INVALID_NS;
- app_ns = app_namespace_get (*app_ns_index);
- if (!app_ns)
- return VNET_API_ERROR_APP_INVALID_NS;
- if (app_ns->ns_secret != secret)
- return VNET_API_ERROR_APP_WRONG_NS_SECRET;
- return 0;
-}
-
-static u8 *
-app_name_from_api_index (u32 api_client_index)
-{
- vl_api_registration_t *regp;
- regp = vl_api_client_index_to_registration (api_client_index);
- if (regp)
- return format (0, "%s%c", regp->name, 0);
-
- clib_warning ("api client index %u does not have an api registration!",
- api_client_index);
- return format (0, "unknown%c", 0);
-}
-
-/**
- * Attach application to vpp
- *
- * Allocates a vpp app, i.e., a structure that keeps back pointers
- * to external app and a segment manager for shared memory fifo based
- * communication with the external app.
- */
-clib_error_t *
-vnet_application_attach (vnet_app_attach_args_t * a)
-{
- svm_fifo_segment_private_t *fs;
- application_t *app = 0;
- app_worker_t *app_wrk;
- segment_manager_t *sm;
- u32 app_ns_index = 0;
- u8 *app_name = 0;
- u64 secret;
- int rv;
-
- 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");
-
- if (a->api_client_index != APP_INVALID_INDEX)
- {
- app_name = app_name_from_api_index (a->api_client_index);
- a->name = app_name;
- }
-
- secret = a->options[APP_OPTIONS_NAMESPACE_SECRET];
- if ((rv = app_validate_namespace (a->namespace_id, secret, &app_ns_index)))
- return clib_error_return_code (0, rv, 0, "namespace validation: %d", rv);
- a->options[APP_OPTIONS_NAMESPACE] = app_ns_index;
-
- if ((rv = application_alloc_and_init ((app_init_args_t *) a)))
- return clib_error_return_code (0, rv, 0, "app init: %d", rv);
-
- app = application_get (a->app_index);
- if ((rv = application_alloc_worker_and_init (app, &app_wrk)))
- return clib_error_return_code (0, rv, 0, "app default wrk init: %d", rv);
-
- a->app_evt_q = app_wrk->event_queue;
- app_wrk->api_client_index = a->api_client_index;
- sm = segment_manager_get (app_wrk->first_segment_manager);
- fs = segment_manager_get_segment_w_lock (sm, 0);
-
- if (application_is_proxy (app))
- application_setup_proxy (app);
-
- ASSERT (vec_len (fs->ssvm.name) <= 128);
- a->segment = &fs->ssvm;
- a->segment_handle = segment_manager_segment_handle (sm, fs);
-
- segment_manager_segment_reader_unlock (sm);
- vec_free (app_name);
- return 0;
-}
-
-/**
- * Detach application from vpp
- */
-int
-vnet_application_detach (vnet_app_detach_args_t * a)
-{
- application_t *app;
-
- app = application_get_if_valid (a->app_index);
- if (!app)
- {
- clib_warning ("app not attached");
- return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
- }
-
- app_interface_check_thread_and_barrier (vnet_application_detach, a);
- application_detach_process (app, a->api_client_index);
- return 0;
-}
-
int
vnet_bind_uri (vnet_listen_args_t * a)
{
@@ -503,19 +128,18 @@
return rv;
sep.app_wrk_index = 0;
clib_memcpy (&a->sep_ext, &sep, sizeof (sep));
- return vnet_listen_inline (a);
+ return vnet_listen (a);
}
int
-vnet_unbind_uri (vnet_unbind_args_t * a)
+vnet_unbind_uri (vnet_unlisten_args_t * a)
{
session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
session_t *listener;
u32 table_index;
int rv;
- rv = parse_uri (a->uri, &sep);
- if (rv)
+ if ((rv = parse_uri (a->uri, &sep)))
return rv;
/* NOTE: only default fib tables supported for uri apis */
@@ -526,86 +150,21 @@
if (!listener)
return VNET_API_ERROR_ADDRESS_NOT_IN_USE;
a->handle = listen_session_get_handle (listener);
- return vnet_unlisten_inline (a);
+ return vnet_unlisten (a);
}
-clib_error_t *
+int
vnet_connect_uri (vnet_connect_args_t * a)
{
session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
int rv;
- /* Parse uri */
- rv = parse_uri (a->uri, &sep);
- if (rv)
- return clib_error_return_code (0, rv, 0, "app init: %d", rv);
+ if ((rv = parse_uri (a->uri, &sep)))
+ return rv;
clib_memcpy (&a->sep_ext, &sep, sizeof (sep));
- if ((rv = application_connect (a)))
- return clib_error_return_code (0, rv, 0, "connect failed");
- return 0;
-}
-
-int
-vnet_disconnect_session (vnet_disconnect_args_t * a)
-{
- if (session_handle_is_local (a->handle))
- {
- local_session_t *ls;
-
- /* Disconnect reply came to worker 1 not main thread */
- app_interface_check_thread_and_barrier (vnet_disconnect_session, a);
-
- if (!(ls = app_worker_get_local_session_from_handle (a->handle)))
- return 0;
-
- return app_worker_local_session_disconnect (a->app_index, ls);
- }
- else
- {
- app_worker_t *app_wrk;
- session_t *s;
-
- s = session_get_from_handle_if_valid (a->handle);
- if (!s)
- return VNET_API_ERROR_INVALID_VALUE;
- app_wrk = app_worker_get (s->app_wrk_index);
- if (app_wrk->app_index != a->app_index)
- return VNET_API_ERROR_INVALID_VALUE;
-
- /* We're peeking into another's thread pool. Make sure */
- ASSERT (s->session_index == session_index_from_handle (a->handle));
-
- session_close (s);
- }
- return 0;
-}
-
-clib_error_t *
-vnet_listen (vnet_listen_args_t * a)
-{
- int rv;
- if ((rv = vnet_listen_inline (a)))
- return clib_error_return_code (0, rv, 0, "bind failed: %d", rv);
- return 0;
-}
-
-clib_error_t *
-vnet_unlisten (vnet_unbind_args_t * a)
-{
- int rv;
- if ((rv = vnet_unlisten_inline (a)))
- return clib_error_return_code (0, rv, 0, "unbind failed: %d", rv);
- return 0;
-}
-
-clib_error_t *
-vnet_connect (vnet_connect_args_t * a)
-{
- int rv;
-
- if ((rv = application_connect (a)))
- return clib_error_return_code (0, rv, 0, "connect failed: %d", rv);
+ if ((rv = vnet_connect (a)))
+ return rv;
return 0;
}
diff --git a/src/vnet/session/application_interface.h b/src/vnet/session/application_interface.h
index d710318..18878cd 100644
--- a/src/vnet/session/application_interface.h
+++ b/src/vnet/session/application_interface.h
@@ -15,12 +15,49 @@
#ifndef __included_uri_h__
#define __included_uri_h__
+#include <vlibmemory/api.h>
+#include <svm/message_queue.h>
#include <svm/svm_fifo_segment.h>
#include <vnet/session/session_types.h>
-#include <vnet/session/application.h>
-#include <vnet/session/transport.h>
#include <vnet/tls/tls_test.h>
+typedef struct _stream_session_cb_vft
+{
+ /** Notify server of new segment */
+ int (*add_segment_callback) (u32 api_client_index, u64 segment_handle);
+
+ /** Notify server of new segment */
+ int (*del_segment_callback) (u32 api_client_index, u64 segment_handle);
+
+ /** Notify server of newly accepted session */
+ int (*session_accept_callback) (session_t * new_session);
+
+ /** Connection request callback */
+ int (*session_connected_callback) (u32 app_wrk_index, u32 opaque,
+ session_t * s, u8 code);
+
+ /** Notify app that session is closing */
+ void (*session_disconnect_callback) (session_t * s);
+
+ /** Notify app that session was reset */
+ void (*session_reset_callback) (session_t * s);
+
+ /** Direct RX callback for built-in application */
+ int (*builtin_app_rx_callback) (session_t * session);
+
+ /** Direct TX callback for built-in application */
+ int (*builtin_app_tx_callback) (session_t * session);
+
+} session_cb_vft_t;
+
+#define foreach_app_init_args \
+ _(u32, api_client_index) \
+ _(u8 *, name) \
+ _(u64 *, options) \
+ _(u8 *, namespace_id) \
+ _(session_cb_vft_t *, session_cb_vft) \
+ _(u32, app_index) \
+
typedef struct _vnet_app_attach_args_t
{
#define _(_type, _name) _type _name;
@@ -67,7 +104,7 @@
};
u32 app_index; /**< Owning application index */
u32 wrk_map_index; /**< App's local pool worker index */
-} vnet_unbind_args_t;
+} vnet_unlisten_args_t;
typedef struct _vnet_connect_args
{
@@ -176,14 +213,14 @@
} session_fd_flag_t;
int vnet_bind_uri (vnet_listen_args_t *);
-int vnet_unbind_uri (vnet_unbind_args_t * a);
-clib_error_t *vnet_connect_uri (vnet_connect_args_t * a);
+int vnet_unbind_uri (vnet_unlisten_args_t * a);
+int vnet_connect_uri (vnet_connect_args_t * a);
-clib_error_t *vnet_application_attach (vnet_app_attach_args_t * a);
-clib_error_t *vnet_listen (vnet_listen_args_t * a);
-clib_error_t *vnet_connect (vnet_connect_args_t * a);
-clib_error_t *vnet_unlisten (vnet_unbind_args_t * a);
+int vnet_application_attach (vnet_app_attach_args_t * a);
int vnet_application_detach (vnet_app_detach_args_t * a);
+int vnet_listen (vnet_listen_args_t * a);
+int vnet_connect (vnet_connect_args_t * a);
+int vnet_unlisten (vnet_unlisten_args_t * a);
int vnet_disconnect_session (vnet_disconnect_args_t * a);
clib_error_t *vnet_app_add_tls_cert (vnet_app_add_tls_cert_args_t * a);
diff --git a/src/vnet/session/application_namespace.c b/src/vnet/session/application_namespace.c
index 9fbca26..47a369e 100644
--- a/src/vnet/session/application_namespace.c
+++ b/src/vnet/session/application_namespace.c
@@ -61,7 +61,7 @@
return app_ns;
}
-clib_error_t *
+int
vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t * a)
{
app_namespace_t *app_ns;
@@ -71,9 +71,8 @@
{
if (a->sw_if_index != APP_NAMESPACE_INVALID_INDEX
&& !vnet_get_sw_interface_safe (vnet_get_main (), a->sw_if_index))
- return clib_error_return_code (0, VNET_API_ERROR_INVALID_SW_IF_INDEX,
- 0, "sw_if_index %u doesn't exist",
- a->sw_if_index);
+ return VNET_API_ERROR_INVALID_SW_IF_INDEX;
+
if (a->sw_if_index != APP_NAMESPACE_INVALID_INDEX)
{
@@ -86,9 +85,8 @@
}
if (a->sw_if_index == APP_NAMESPACE_INVALID_INDEX
&& a->ip4_fib_id == APP_NAMESPACE_INVALID_INDEX)
- return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
- "sw_if_index or fib_id must be "
- "configured");
+ return VNET_API_ERROR_INVALID_VALUE;
+
app_ns = app_namespace_get_from_id (a->ns_id);
if (!app_ns)
{
@@ -109,8 +107,7 @@
}
else
{
- return clib_error_return_code (0, VNET_API_ERROR_UNIMPLEMENTED, 0,
- "namespace deletion not supported");
+ return VNET_API_ERROR_UNIMPLEMENTED;
}
return 0;
}
@@ -184,6 +181,7 @@
u32 sw_if_index, fib_id = APP_NAMESPACE_INVALID_INDEX;
u64 secret;
clib_error_t *error = 0;
+ int rv;
session_cli_return_if_not_enabled ();
@@ -228,7 +226,8 @@
.ip4_fib_id = fib_id,
.is_add = 1
};
- error = vnet_app_namespace_add_del (&args);
+ if ((rv = vnet_app_namespace_add_del (&args)))
+ return clib_error_return (0, "app namespace add del returned %d", rv);
}
return error;
diff --git a/src/vnet/session/application_namespace.h b/src/vnet/session/application_namespace.h
index 8ba5a98..3a24fe1 100644
--- a/src/vnet/session/application_namespace.h
+++ b/src/vnet/session/application_namespace.h
@@ -70,8 +70,7 @@
const u8 *app_namespace_id_from_index (u32 index);
u32 app_namespace_index_from_id (const u8 * ns_id);
void app_namespaces_init (void);
-clib_error_t *vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t *
- a);
+int vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t * a);
u32 app_namespace_get_fib_index (app_namespace_t * app_ns, u8 fib_proto);
session_table_t *app_namespace_get_local_table (app_namespace_t * app_ns);
diff --git a/src/vnet/session/application_worker.c b/src/vnet/session/application_worker.c
index 3baf29d..7fdf71d 100644
--- a/src/vnet/session/application_worker.c
+++ b/src/vnet/session/application_worker.c
@@ -160,7 +160,7 @@
app_worker_free (app_worker_t * app_wrk)
{
application_t *app = application_get (app_wrk->app_index);
- vnet_unbind_args_t _a, *a = &_a;
+ vnet_unlisten_args_t _a, *a = &_a;
u64 handle, *handles = 0;
segment_manager_t *sm;
u32 sm_index;
@@ -188,7 +188,7 @@
a->wrk_map_index = app_wrk->wrk_map_index;
a->handle = handles[i];
/* seg manager is removed when unbind completes */
- vnet_unlisten (a);
+ (void) vnet_unlisten (a);
}
/*
diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c
index 6a84551..015b29f 100755
--- a/src/vnet/session/session_api.c
+++ b/src/vnet/session/session_api.c
@@ -757,7 +757,6 @@
ssvm_private_t *segp, *evt_q_segment;
vnet_app_attach_args_t _a, *a = &_a;
vl_api_registration_t *reg;
- clib_error_t *error = 0;
u8 fd_flags = 0;
reg = vl_api_client_index_to_registration (mp->client_index);
@@ -796,10 +795,9 @@
mp->namespace_id_len);
}
- if ((error = vnet_application_attach (a)))
+ if ((rv = vnet_application_attach (a)))
{
- rv = clib_error_get_code (error);
- clib_error_report (error);
+ clib_warning ("attach returned: %d", rv);
vec_free (a->namespace_id);
goto done;
}
@@ -950,7 +948,7 @@
{
vl_api_unbind_uri_reply_t *rmp;
application_t *app;
- vnet_unbind_args_t _a, *a = &_a;
+ vnet_unlisten_args_t _a, *a = &_a;
int rv;
if (session_manager_is_enabled () == 0)
@@ -981,7 +979,6 @@
vl_api_connect_session_reply_t *rmp;
vnet_connect_args_t _a, *a = &_a;
application_t *app;
- clib_error_t *error = 0;
int rv = 0;
if (session_manager_is_enabled () == 0)
@@ -997,11 +994,8 @@
a->uri = (char *) mp->uri;
a->api_context = mp->context;
a->app_index = app->app_index;
- if ((error = vnet_connect_uri (a)))
- {
- rv = clib_error_get_code (error);
- clib_error_report (error);
- }
+ if ((rv = vnet_connect_uri (a)))
+ clib_warning ("connect_uri returned: %d", rv);
}
else
{
@@ -1182,7 +1176,6 @@
application_t *app = 0;
app_worker_t *app_wrk;
ip46_address_t *ip46;
- clib_error_t *error;
app_listener_t *al;
session_t *s;
int rv = 0;
@@ -1211,11 +1204,8 @@
a->app_index = app->app_index;
a->wrk_map_index = mp->wrk_index;
- if ((error = vnet_listen (a)))
- {
- rv = clib_error_get_code (error);
- clib_error_report (error);
- }
+ if ((rv = vnet_listen (a)))
+ clib_warning ("listen returned: %d", rv);
done:
/* *INDENT-OFF* */
@@ -1256,9 +1246,8 @@
vl_api_unbind_sock_t_handler (vl_api_unbind_sock_t * mp)
{
vl_api_unbind_sock_reply_t *rmp;
- vnet_unbind_args_t _a, *a = &_a;
+ vnet_unlisten_args_t _a, *a = &_a;
application_t *app;
- clib_error_t *error;
int rv = 0;
if (session_manager_is_enabled () == 0)
@@ -1273,11 +1262,8 @@
a->app_index = app->app_index;
a->handle = mp->handle;
a->wrk_map_index = mp->wrk_index;
- if ((error = vnet_unlisten (a)))
- {
- rv = clib_error_get_code (error);
- clib_error_report (error);
- }
+ if ((rv = vnet_unlisten (a)))
+ clib_warning ("unlisten returned: %d", rv);
}
done:
@@ -1290,7 +1276,6 @@
vl_api_connect_session_reply_t *rmp;
vnet_connect_args_t _a, *a = &_a;
application_t *app = 0;
- clib_error_t *error = 0;
int rv = 0;
if (session_manager_is_enabled () == 0)
@@ -1323,11 +1308,8 @@
a->api_context = mp->context;
a->app_index = app->app_index;
a->wrk_map_index = mp->wrk_index;
- if ((error = vnet_connect (a)))
- {
- rv = clib_error_get_code (error);
- clib_error_report (error);
- }
+ if ((rv = vnet_connect (a)))
+ clib_warning ("connect returned: %u", rv);
vec_free (a->sep_ext.hostname);
}
else
@@ -1356,7 +1338,6 @@
int rv = 0, fds[SESSION_N_FD_TYPE], n_fds = 0;
vl_api_app_worker_add_del_reply_t *rmp;
vl_api_registration_t *reg;
- clib_error_t *error = 0;
application_t *app;
u8 fd_flags = 0;
@@ -1383,11 +1364,10 @@
.api_client_index = mp->client_index,
.is_add = mp->is_add
};
- error = vnet_app_worker_add_del (&args);
- if (error)
+ rv = vnet_app_worker_add_del (&args);
+ if (rv)
{
- rv = clib_error_get_code (error);
- clib_error_report (error);
+ clib_warning ("app worker add/del returned: %d", rv);
goto done;
}
@@ -1437,7 +1417,6 @@
vl_api_app_namespace_add_del_t_handler (vl_api_app_namespace_add_del_t * mp)
{
vl_api_app_namespace_add_del_reply_t *rmp;
- clib_error_t *error = 0;
u32 appns_index = 0;
u8 *ns_id = 0;
int rv = 0;
@@ -1463,13 +1442,8 @@
.ip6_fib_id = clib_net_to_host_u32 (mp->ip6_fib_id),
.is_add = 1
};
- error = vnet_app_namespace_add_del (&args);
- if (error)
- {
- rv = clib_error_get_code (error);
- clib_error_report (error);
- }
- else
+ rv = vnet_app_namespace_add_del (&args);
+ if (!rv)
{
appns_index = app_namespace_index_from_id (ns_id);
if (appns_index == APP_NAMESPACE_INVALID_INDEX)
@@ -1495,7 +1469,6 @@
vl_api_session_rule_add_del_reply_t *rmp;
session_rule_add_del_args_t args;
session_rule_table_add_del_args_t *table_args = &args.table_args;
- clib_error_t *error;
u8 fib_proto;
int rv = 0;
@@ -1520,12 +1493,9 @@
clib_memset (&table_args->rmt.fp_addr, 0, sizeof (table_args->rmt.fp_addr));
ip_set (&table_args->lcl.fp_addr, mp->lcl_ip, mp->is_ip4);
ip_set (&table_args->rmt.fp_addr, mp->rmt_ip, mp->is_ip4);
- error = vnet_session_rule_add_del (&args);
- if (error)
- {
- rv = clib_error_get_code (error);
- clib_error_report (error);
- }
+ rv = vnet_session_rule_add_del (&args);
+ if (rv)
+ clib_warning ("rule add del returned: %d", rv);
vec_free (table_args->tag);
REPLY_MACRO (VL_API_SESSION_RULE_ADD_DEL_REPLY);
}
diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c
index f267a4c..854da7f 100644
--- a/src/vnet/session/session_lookup.c
+++ b/src/vnet/session/session_lookup.c
@@ -1240,7 +1240,7 @@
return 0;
}
-clib_error_t *
+int
vnet_session_rule_add_del (session_rule_add_del_args_t * args)
{
app_namespace_t *app_ns = app_namespace_get (args->appns_index);
@@ -1248,29 +1248,26 @@
session_table_t *st;
u32 fib_index;
u8 fib_proto;
- clib_error_t *error;
+ int rv = 0;
if (!app_ns)
- return clib_error_return_code (0, VNET_API_ERROR_APP_INVALID_NS, 0,
- "invalid app ns");
+ return VNET_API_ERROR_APP_INVALID_NS;
+
if (args->scope > 3)
- return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
- "invalid scope");
+ return VNET_API_ERROR_INVALID_VALUE;
+
if (args->transport_proto != TRANSPORT_PROTO_TCP
&& args->transport_proto != TRANSPORT_PROTO_UDP)
- return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
- "invalid transport proto");
+ return VNET_API_ERROR_INVALID_VALUE;
+
if ((args->scope & SESSION_RULE_SCOPE_GLOBAL) || args->scope == 0)
{
fib_proto = args->table_args.rmt.fp_proto;
fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
st = session_table_get_for_fib_index (fib_proto, fib_index);
srt = &st->session_rules[args->transport_proto];
- if ((error = session_rules_table_add_del (srt, &args->table_args)))
- {
- clib_error_report (error);
- return error;
- }
+ if ((rv = session_rules_table_add_del (srt, &args->table_args)))
+ return rv;
}
if (args->scope & SESSION_RULE_SCOPE_LOCAL)
{
@@ -1279,9 +1276,9 @@
args->table_args.lcl_port = 0;
st = app_namespace_get_local_table (app_ns);
srt = &st->session_rules[args->transport_proto];
- error = session_rules_table_add_del (srt, &args->table_args);
+ rv = session_rules_table_add_del (srt, &args->table_args);
}
- return error;
+ return rv;
}
/**
@@ -1388,7 +1385,7 @@
u8 fib_proto, is_add = 1, *ns_id = 0;
u8 *tag = 0;
app_namespace_t *app_ns;
- clib_error_t *error;
+ int rv;
clib_memset (&lcl_ip, 0, sizeof (lcl_ip));
clib_memset (&rmt_ip, 0, sizeof (rmt_ip));
@@ -1485,9 +1482,11 @@
.appns_index = appns_index,
.scope = scope,
};
- error = vnet_session_rule_add_del (&args);
+ if ((rv = vnet_session_rule_add_del (&args)))
+ return clib_error_return (0, "rule add del returned %u", rv);
+
vec_free (tag);
- return error;
+ return 0;
}
/* *INDENT-OFF* */
diff --git a/src/vnet/session/session_lookup.h b/src/vnet/session/session_lookup.h
index 995d2aa..c45794d 100644
--- a/src/vnet/session/session_lookup.h
+++ b/src/vnet/session/session_lookup.h
@@ -123,7 +123,7 @@
u8 transport_proto;
} session_rule_add_del_args_t;
-clib_error_t *vnet_session_rule_add_del (session_rule_add_del_args_t * args);
+int vnet_session_rule_add_del (session_rule_add_del_args_t * args);
void session_lookup_set_tables_appns (app_namespace_t * app_ns);
void session_lookup_init (void);
diff --git a/src/vnet/session/session_rules_table.c b/src/vnet/session/session_rules_table.c
index 4369840..7f5c7bb 100644
--- a/src/vnet/session/session_rules_table.c
+++ b/src/vnet/session/session_rules_table.c
@@ -388,7 +388,7 @@
*
* @return 0 if success, clib_error_t error otherwise
*/
-clib_error_t *
+int
session_rules_table_add_del (session_rules_table_t * srt,
session_rule_table_add_del_args_t * args)
{
@@ -398,8 +398,7 @@
ri_from_tag = session_rules_table_rule_for_tag (srt, args->tag);
if (args->is_add && ri_from_tag != SESSION_RULES_TABLE_INVALID_INDEX)
- return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
- "tag exists");
+ return VNET_API_ERROR_INVALID_VALUE;
if (fib_proto == FIB_PROTOCOL_IP4)
{
@@ -510,8 +509,7 @@
}
}
else
- return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE_2, 0,
- "invalid fib proto");
+ return VNET_API_ERROR_INVALID_VALUE_2;
return 0;
}
diff --git a/src/vnet/session/session_rules_table.h b/src/vnet/session/session_rules_table.h
index 2f0554d..8679cb8 100644
--- a/src/vnet/session/session_rules_table.h
+++ b/src/vnet/session/session_rules_table.h
@@ -111,9 +111,8 @@
ip46_address_t * lcl_ip, u16 lcl_port,
ip46_address_t * rmt_ip, u16 rmt_port,
u8 is_ip4);
-clib_error_t *session_rules_table_add_del (session_rules_table_t * srt,
- session_rule_table_add_del_args_t *
- args);
+int session_rules_table_add_del (session_rules_table_t * srt,
+ session_rule_table_add_del_args_t * args);
u8 *session_rules_table_rule_tag (session_rules_table_t * srt, u32 ri,
u8 is_ip4);
void session_rules_table_init (session_rules_table_t * srt);
diff --git a/src/vnet/tls/tls.c b/src/vnet/tls/tls.c
index e36a884..d78dbcf 100644
--- a/src/vnet/tls/tls.c
+++ b/src/vnet/tls/tls.c
@@ -529,10 +529,10 @@
tls_engine_type_t engine_type;
tls_main_t *tm = &tls_main;
app_worker_t *app_wrk;
- clib_error_t *error;
application_t *app;
tls_ctx_t *ctx;
u32 ctx_index;
+ int rv;
sep = (session_endpoint_cfg_t *) tep;
app_wrk = app_worker_get (sep->app_wrk_index);
@@ -563,8 +563,8 @@
cargs->sep.transport_proto = TRANSPORT_PROTO_TCP;
cargs->app_index = tm->app_index;
cargs->api_context = ctx_index;
- if ((error = vnet_connect (cargs)))
- return clib_error_get_code (error);
+ if ((rv = vnet_connect (cargs)))
+ return rv;
TLS_DBG (1, "New connect request %u engine %d", ctx_index, engine_type);
return 0;
@@ -641,15 +641,16 @@
{
tls_engine_type_t engine_type;
tls_ctx_t *lctx;
+ int rv;
lctx = tls_listener_ctx_get (lctx_index);
- vnet_unbind_args_t a = {
+ vnet_unlisten_args_t a = {
.handle = lctx->tls_session_handle,
.app_index = tls_main.app_index,
.wrk_map_index = 0 /* default wrk */
};
- if (vnet_unlisten (&a))
- clib_warning ("unbind returned");
+ if ((rv = vnet_unlisten (&a)))
+ clib_warning ("unlisten returned %d", rv);
engine_type = lctx->tls_ctx_engine;
tls_vfts[engine_type].ctx_stop_listen (lctx);
diff --git a/src/vnet/tls/tls.h b/src/vnet/tls/tls.h
index 5ddce9a..ac0b39b 100644
--- a/src/vnet/tls/tls.h
+++ b/src/vnet/tls/tls.h
@@ -14,6 +14,7 @@
*/
#include <vnet/session/application_interface.h>
+#include <vnet/session/application.h>
#include <vnet/session/session.h>
#include <vppinfra/lock.h>