aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/session/application_interface.c
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2018-02-08 15:10:09 -0800
committerFlorin Coras <fcoras@cisco.com>2018-02-14 00:54:43 -0800
commitf8f516a8b0ccab2f5d9796f90419bf2661c750af (patch)
treef02f6c01ed1bf33aeb4ebb5714af470e537f87c2 /src/vnet/session/application_interface.c
parent7758bf68a03a32f17c07154172157f5bdf30e684 (diff)
session: support local sessions and deprecate redirects
Memfd backed shared memory segments can only be negotiated over sockets. For such scenarios, the existing redirect mechanism that establishes cut-through sessions does not work anymore as the two peer application do not share such a socket. This patch adds support for local sessions, as opposed to sessions backed by a transport connection, in a way that is almost transparent to the two applications by reusing the existing binary api messages. Moreover, all segment allocations are now entirely done through the segment manager valloc, so segment overlaps due to independent allocations previously required for redirects are completely avoided. The one notable characteristic of local sessions (cut-through from app perspective) notification messages is that they carry pointers to two event queues, one for each app peer, instead of one. For transport-backed sessions one of the queues can be inferred but for local session they cannot. Change-Id: Ia443fb63e2d9d8e43490275062a708f039038175 Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/vnet/session/application_interface.c')
-rw-r--r--src/vnet/session/application_interface.c135
1 files changed, 56 insertions, 79 deletions
diff --git a/src/vnet/session/application_interface.c b/src/vnet/session/application_interface.c
index efdd3dde9ad..1023c8c9a62 100644
--- a/src/vnet/session/application_interface.c
+++ b/src/vnet/session/application_interface.c
@@ -119,12 +119,8 @@ vnet_bind_i (u32 app_index, session_endpoint_t * sep, u64 * handle)
*/
if (application_has_local_scope (app) && session_endpoint_is_zero (sep))
{
- table_index = application_local_session_table (app);
- listener = session_lookup_endpoint_listener (table_index, sep, 1);
- if (listener != SESSION_INVALID_HANDLE)
- return VNET_API_ERROR_ADDRESS_IN_USE;
- session_lookup_add_session_endpoint (table_index, sep, app->index);
- *handle = session_lookup_local_listener_make_handle (sep);
+ if ((rv = application_start_local_listen (app, sep, handle)))
+ return rv;
have_local = 1;
}
@@ -143,47 +139,21 @@ vnet_bind_i (u32 app_index, session_endpoint_t * sep, u64 * handle)
}
int
-vnet_unbind_i (u32 app_index, u64 handle)
+vnet_unbind_i (u32 app_index, session_handle_t handle)
{
- application_t *app = application_get_if_valid (app_index);
- stream_session_t *listener = 0;
- u32 table_index;
+ application_t *app;
+ int rv;
- if (!app)
+ if (!(app = application_get_if_valid (app_index)))
{
SESSION_DBG ("app (%d) not attached", app_index);
return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
}
- /*
- * Clean up local session table. If we have a listener session use it to
- * find the port and proto. If not, the handle must be a local table handle
- * so parse it.
- */
-
if (application_has_local_scope (app))
{
- session_endpoint_t sep = SESSION_ENDPOINT_NULL;
- if (!session_lookup_local_is_handle (handle))
- listener = listen_session_get_from_handle (handle);
- if (listener)
- {
- if (listen_session_get_local_session_endpoint (listener, &sep))
- {
- clib_warning ("broken listener");
- return -1;
- }
- }
- else
- {
- if (session_lookup_local_listener_parse_handle (handle, &sep))
- {
- clib_warning ("can't parse handle");
- return -1;
- }
- }
- table_index = application_local_session_table (app);
- session_lookup_del_session_endpoint (table_index, &sep);
+ if ((rv = application_stop_local_listen (app, handle)))
+ return rv;
}
/*
@@ -194,53 +164,47 @@ vnet_unbind_i (u32 app_index, u64 handle)
return 0;
}
-static int
-app_connect_redirect (application_t * server, void *mp)
-{
- return server->cb_fns.redirect_connect_callback (server->api_client_index,
- mp);
-}
-
int
-vnet_connect_i (u32 app_index, u32 api_context, session_endpoint_t * sep,
+vnet_connect_i (u32 client_index, u32 api_context, session_endpoint_t * sep,
void *mp)
{
- application_t *server, *app;
- u32 table_index, server_index;
+ application_t *server, *client;
+ u32 table_index, server_index, li;
stream_session_t *listener;
+ local_session_t *ll;
+ u64 lh;
if (session_endpoint_is_zero (sep))
return VNET_API_ERROR_INVALID_VALUE;
- app = application_get (app_index);
- session_endpoint_update_for_app (sep, app);
+ client = application_get (client_index);
+ session_endpoint_update_for_app (sep, client);
/*
- * First check the the local scope for locally attached destinations.
+ * 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 (app))
+ if (application_has_local_scope (client))
{
- table_index = application_local_session_table (app);
- server_index = session_lookup_local_endpoint (table_index, sep);
- if (server_index == APP_DROP_INDEX)
+ table_index = application_local_session_table (client);
+ lh = session_lookup_local_endpoint (table_index, sep);
+ if (lh == SESSION_DROP_HANDLE)
return VNET_API_ERROR_APP_CONNECT_FILTERED;
+ local_session_parse_handle (lh, &server_index, &li);
+
/*
* 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 (server_index != app_index)
+ if (server_index != client_index
+ && (server = application_get_if_valid (server_index)))
{
- server = application_get (server_index);
- /*
- * Server is willing to have a direct fifo connection created
- * instead of going through the state machine, etc.
- */
- if (server && (server->flags & APP_OPTIONS_FLAGS_ACCEPT_REDIRECT))
- return app_connect_redirect (server, mp);
+ ll = application_get_local_listen_session (server, li);
+ return application_local_session_connect (table_index, client,
+ server, ll, api_context);
}
}
@@ -251,23 +215,25 @@ vnet_connect_i (u32 app_index, u32 api_context, session_endpoint_t * sep,
if (session_endpoint_is_local (sep))
return VNET_API_ERROR_SESSION_CONNECT;
- if (!application_has_global_scope (app))
+ if (!application_has_global_scope (client))
return VNET_API_ERROR_APP_CONNECT_SCOPE;
- table_index = application_session_table (app,
+ table_index = application_session_table (client,
session_endpoint_fib_proto (sep));
listener = session_lookup_listener (table_index, sep);
if (listener)
{
server = application_get (listener->app_index);
- if (server && (server->flags & APP_OPTIONS_FLAGS_ACCEPT_REDIRECT))
- return app_connect_redirect (server, mp);
+ if (server)
+ return application_local_session_connect (table_index, client, server,
+ (local_session_t *)
+ listener, api_context);
}
/*
* Not connecting to a local server, propagate to transport
*/
- if (application_open_session (app, sep, api_context))
+ if (application_open_session (client, sep, api_context))
return VNET_API_ERROR_SESSION_CONNECT;
return 0;
}
@@ -490,19 +456,30 @@ vnet_connect_uri (vnet_connect_args_t * a)
int
vnet_disconnect_session (vnet_disconnect_args_t * a)
{
- u32 index, thread_index;
- stream_session_t *s;
-
- session_parse_handle (a->handle, &index, &thread_index);
- s = session_get_if_valid (index, thread_index);
-
- if (!s || s->app_index != a->app_index)
- return VNET_API_ERROR_INVALID_VALUE;
+ if (session_handle_is_local (a->handle))
+ {
+ local_session_t *ls;
+ ls = application_get_local_session_from_handle (a->handle);
+ if (ls->app_index != a->app_index && ls->client_index != a->app_index)
+ {
+ clib_warning ("app %u is neither client nor server for session %u",
+ a->app_index, a->app_index);
+ return VNET_API_ERROR_INVALID_VALUE;
+ }
+ return application_local_session_disconnect (a->app_index, ls);
+ }
+ else
+ {
+ stream_session_t *s;
+ s = session_get_from_handle_if_valid (a->handle);
+ if (!s || s->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 == index);
+ /* We're peeking into another's thread pool. Make sure */
+ ASSERT (s->session_index == session_index_from_handle (a->handle));
- stream_session_disconnect (s);
+ stream_session_disconnect (s);
+ }
return 0;
}