aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/svm/ssvm.c9
-rw-r--r--src/svm/svm_fifo_segment.h4
-rw-r--r--src/tests/vnet/session/tcp_echo.c1
-rw-r--r--src/tests/vnet/session/udp_echo.c130
-rw-r--r--src/vcl.am2
-rw-r--r--src/vnet/session-apps/echo_server.c21
-rw-r--r--src/vnet/session-apps/http_server.c8
-rw-r--r--src/vnet/session-apps/proxy.c8
-rw-r--r--src/vnet/session/application.c654
-rw-r--r--src/vnet/session/application.h98
-rw-r--r--src/vnet/session/application_interface.c135
-rw-r--r--src/vnet/session/application_interface.h7
-rw-r--r--src/vnet/session/segment_manager.c53
-rw-r--r--src/vnet/session/segment_manager.h31
-rw-r--r--src/vnet/session/session.api23
-rw-r--r--src/vnet/session/session.h58
-rwxr-xr-xsrc/vnet/session/session_api.c257
-rw-r--r--src/vnet/session/session_lookup.c76
-rw-r--r--src/vnet/session/session_lookup.h7
-rw-r--r--src/vnet/session/session_table.h1
-rw-r--r--src/vnet/session/session_test.c116
-rw-r--r--src/vnet/session/stream_session.h73
-rw-r--r--src/vnet/session/transport.h1
-rw-r--r--test/test_session.py3
24 files changed, 1280 insertions, 496 deletions
diff --git a/src/svm/ssvm.c b/src/svm/ssvm.c
index 7077f8be641..04e0efa3d62 100644
--- a/src/svm/ssvm.c
+++ b/src/svm/ssvm.c
@@ -33,7 +33,7 @@ ssvm_master_init_shm (ssvm_private_t * ssvm)
clib_mem_vm_map_t mapa = { 0 };
u8 junk = 0, *ssvm_filename;
ssvm_shared_header_t *sh;
- uword page_size;
+ uword page_size, requested_va = 0;
void *oldheap;
if (ssvm->ssvm_size == 0)
@@ -75,9 +75,12 @@ ssvm_master_init_shm (ssvm_private_t * ssvm)
page_size = clib_mem_vm_get_page_size (ssvm_fd);
if (ssvm->requested_va)
- clib_mem_vm_randomize_va (&ssvm->requested_va, min_log2 (page_size));
+ {
+ requested_va = ssvm->requested_va;
+ clib_mem_vm_randomize_va (&requested_va, min_log2 (page_size));
+ }
- mapa.requested_va = ssvm->requested_va;
+ mapa.requested_va = requested_va;
mapa.size = ssvm->ssvm_size;
mapa.fd = ssvm_fd;
if (clib_mem_vm_ext_map (&mapa))
diff --git a/src/svm/svm_fifo_segment.h b/src/svm/svm_fifo_segment.h
index bf8d5139e3c..1872da169f9 100644
--- a/src/svm/svm_fifo_segment.h
+++ b/src/svm/svm_fifo_segment.h
@@ -31,8 +31,8 @@ typedef enum
#define FIFO_SEGMENT_MAX_FIFO_SIZE (8<<20) /* 8mb max fifo size */
#define FIFO_SEGMENT_ALLOC_CHUNK_SIZE 32 /* Allocation quantum */
-#define FIFO_SEGMENT_F_IS_PREALLOCATED 1 << 0 /* Segment is preallocated */
-#define FIFO_SEGMENT_F_WILL_DELETE 1 << 1 /* Segment will be removed */
+#define FIFO_SEGMENT_F_IS_PREALLOCATED (1 << 0)
+#define FIFO_SEGMENT_F_WILL_DELETE (1 << 1)
typedef struct
{
diff --git a/src/tests/vnet/session/tcp_echo.c b/src/tests/vnet/session/tcp_echo.c
index d48c5d9de03..a925384b6e4 100644
--- a/src/tests/vnet/session/tcp_echo.c
+++ b/src/tests/vnet/session/tcp_echo.c
@@ -479,6 +479,7 @@ vl_api_disconnect_session_t_handler (vl_api_disconnect_session_t * mp)
rmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION_REPLY);
rmp->retval = rv;
rmp->handle = mp->handle;
+ rmp->context = mp->context;
vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & rmp);
if (session)
diff --git a/src/tests/vnet/session/udp_echo.c b/src/tests/vnet/session/udp_echo.c
index e425169b944..d1363fc7104 100644
--- a/src/tests/vnet/session/udp_echo.c
+++ b/src/tests/vnet/session/udp_echo.c
@@ -126,6 +126,8 @@ typedef struct
svm_fifo_segment_main_t *segment_main;
u8 *connect_test_data;
+
+ uword *segments_table;
} uri_udp_test_main_t;
#if CLIB_DEBUG > 0
@@ -173,8 +175,9 @@ application_send_attach (uri_udp_test_main_t * utm)
bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_ATTACH);
bmp->client_index = utm->my_client_index;
bmp->context = ntohl (0xfeedface);
- bmp->options[APP_OPTIONS_FLAGS] =
- APP_OPTIONS_FLAGS_ACCEPT_REDIRECT | APP_OPTIONS_FLAGS_ADD_SEGMENT;
+ bmp->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_ADD_SEGMENT;
+ bmp->options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
+ bmp->options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
bmp->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = 2;
bmp->options[APP_OPTIONS_RX_FIFO_SIZE] = fifo_size;
bmp->options[APP_OPTIONS_TX_FIFO_SIZE] = fifo_size;
@@ -308,7 +311,7 @@ cut_through_thread_fn (void *arg)
/* We read from the tx fifo and write to the rx fifo */
do
{
- actual_transfer = svm_fifo_dequeue_nowait (tx_fifo,
+ actual_transfer = svm_fifo_dequeue_nowait (rx_fifo,
vec_len (my_copy_buffer),
my_copy_buffer);
}
@@ -319,7 +322,7 @@ cut_through_thread_fn (void *arg)
buffer_offset = 0;
while (actual_transfer > 0)
{
- rv = svm_fifo_enqueue_nowait (rx_fifo, actual_transfer,
+ rv = svm_fifo_enqueue_nowait (tx_fifo, actual_transfer,
my_copy_buffer + buffer_offset);
if (rv > 0)
{
@@ -605,7 +608,10 @@ vl_api_bind_uri_reply_t_handler (vl_api_bind_uri_reply_t * mp)
static void
vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp)
{
+ uri_udp_test_main_t *utm = &uri_udp_test_main;
svm_fifo_segment_create_args_t _a, *a = &_a;
+ svm_fifo_segment_private_t *seg;
+ u8 *seg_name;
int rv;
memset (a, 0, sizeof (*a));
@@ -619,8 +625,35 @@ vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp)
mp->segment_name);
return;
}
- clib_warning ("Mapped new segment '%s' size %d", mp->segment_name,
- mp->segment_size);
+ seg = svm_fifo_segment_get_segment (a->new_segment_indices[0]);
+ clib_warning ("Mapped new segment '%s' size %d", seg->ssvm.name,
+ seg->ssvm.ssvm_size);
+ seg_name = format (0, "%s", (char *) mp->segment_name);
+ hash_set_mem (utm->segments_table, seg_name, a->new_segment_indices[0]);
+ vec_free (seg_name);
+}
+
+static void
+vl_api_unmap_segment_t_handler (vl_api_unmap_segment_t * mp)
+{
+ uri_udp_test_main_t *utm = &uri_udp_test_main;
+ svm_fifo_segment_private_t *seg;
+ u64 *seg_indexp;
+ u8 *seg_name;
+
+
+ seg_name = format (0, "%s", mp->segment_name);
+ seg_indexp = hash_get_mem (utm->segments_table, seg_name);
+ if (!seg_indexp)
+ {
+ clib_warning ("segment not mapped: %s", seg_name);
+ return;
+ }
+ hash_unset_mem (utm->segments_table, seg_name);
+ seg = svm_fifo_segment_get_segment ((u32) seg_indexp[0]);
+ svm_fifo_segment_delete (seg);
+ clib_warning ("Unmapped segment '%s'", seg_name);
+ vec_free (seg_name);
}
/**
@@ -720,6 +753,8 @@ vl_api_accept_session_t_handler (vl_api_accept_session_t * mp)
svm_fifo_t *rx_fifo, *tx_fifo;
session_t *session;
static f64 start_time;
+ u32 session_index;
+ int rv = 0;
if (start_time == 0.0)
start_time = clib_time_now (&utm->clib_time);
@@ -727,19 +762,42 @@ vl_api_accept_session_t_handler (vl_api_accept_session_t * mp)
utm->vpp_event_queue =
uword_to_pointer (mp->vpp_event_queue_address, svm_queue_t *);
- pool_get (utm->sessions, session);
-
rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
- rx_fifo->client_session_index = session - utm->sessions;
tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
- tx_fifo->client_session_index = session - utm->sessions;
- session->server_rx_fifo = rx_fifo;
- session->server_tx_fifo = tx_fifo;
+ pool_get (utm->sessions, session);
+ memset (session, 0, sizeof (*session));
+ session_index = session - utm->sessions;
- hash_set (utm->session_index_by_vpp_handles, mp->handle,
- session - utm->sessions);
+ /* Cut-through case */
+ if (mp->server_event_queue_address)
+ {
+ clib_warning ("cut-through session");
+ utm->our_event_queue = uword_to_pointer (mp->server_event_queue_address,
+ svm_queue_t *);
+ rx_fifo->master_session_index = session_index;
+ tx_fifo->master_session_index = session_index;
+ utm->cut_through_session_index = session_index;
+ session->server_rx_fifo = rx_fifo;
+ session->server_tx_fifo = tx_fifo;
+
+ rv = pthread_create (&utm->cut_through_thread_handle,
+ NULL /*attr */ , cut_through_thread_fn, 0);
+ if (rv)
+ {
+ clib_warning ("pthread_create returned %d", rv);
+ rv = VNET_API_ERROR_SYSCALL_ERROR_1;
+ }
+ }
+ else
+ {
+ rx_fifo->client_session_index = session_index;
+ tx_fifo->client_session_index = session_index;
+ session->server_rx_fifo = rx_fifo;
+ session->server_tx_fifo = tx_fifo;
+ }
+ hash_set (utm->session_index_by_vpp_handles, mp->handle, session_index);
if (pool_elts (utm->sessions) && (pool_elts (utm->sessions) % 20000) == 0)
{
f64 now = clib_time_now (&utm->clib_time);
@@ -753,6 +811,7 @@ vl_api_accept_session_t_handler (vl_api_accept_session_t * mp)
rmp->_vl_msg_id = ntohs (VL_API_ACCEPT_SESSION_REPLY);
rmp->handle = mp->handle;
rmp->context = mp->context;
+ rmp->retval = rv;
vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *) & rmp);
CLIB_MEMORY_BARRIER ();
@@ -787,6 +846,7 @@ vl_api_disconnect_session_t_handler (vl_api_disconnect_session_t * mp)
rmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION_REPLY);
rmp->retval = rv;
rmp->handle = mp->handle;
+ rmp->context = mp->context;
vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *) & rmp);
}
@@ -804,34 +864,6 @@ vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp)
return;
}
- /* We've been redirected */
- if (mp->segment_name_length > 0)
- {
- svm_fifo_segment_main_t *sm = &svm_fifo_segment_main;
- svm_fifo_segment_create_args_t _a, *a = &_a;
- u32 segment_index;
- svm_fifo_segment_private_t *seg;
- int rv;
-
- memset (a, 0, sizeof (*a));
- a->segment_name = (char *) mp->segment_name;
-
- sleep (1);
-
- rv = svm_fifo_segment_attach (a);
- if (rv)
- {
- clib_warning ("sm_fifo_segment_create ('%v') failed",
- mp->segment_name);
- return;
- }
-
- segment_index = a->new_segment_indices[0];
- vec_add2 (utm->seg, seg, 1);
- memcpy (seg, sm->segments + segment_index, sizeof (*seg));
- sleep (1);
- }
-
pool_get (utm->sessions, session);
session->server_rx_fifo = uword_to_pointer (mp->server_rx_fifo,
svm_fifo_t *);
@@ -840,8 +872,16 @@ vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp)
svm_fifo_t *);
ASSERT (session->server_tx_fifo);
- if (mp->segment_name_length > 0)
- utm->cut_through_session_index = session - utm->sessions;
+ /* Cut-through case */
+ if (mp->client_event_queue_address)
+ {
+ clib_warning ("cut-through session");
+ utm->cut_through_session_index = session - utm->sessions;
+ utm->vpp_event_queue = uword_to_pointer (mp->vpp_event_queue_address,
+ svm_queue_t *);
+ utm->our_event_queue = uword_to_pointer (mp->client_event_queue_address,
+ svm_queue_t *);
+ }
else
{
utm->connected_session = session - utm->sessions;
@@ -859,6 +899,7 @@ _(UNBIND_URI_REPLY, unbind_uri_reply) \
_(ACCEPT_SESSION, accept_session) \
_(DISCONNECT_SESSION, disconnect_session) \
_(MAP_ANOTHER_SEGMENT, map_another_segment) \
+_(UNMAP_SEGMENT, unmap_segment) \
_(APPLICATION_ATTACH_REPLY, application_attach_reply) \
_(APPLICATION_DETACH_REPLY, application_detach_reply) \
@@ -1068,6 +1109,7 @@ main (int argc, char **argv)
utm->session_index_by_vpp_handles = hash_create (0, sizeof (uword));
utm->my_pid = getpid ();
utm->configured_segment_size = 1 << 20;
+ utm->segments_table = hash_create_vec (0, sizeof (u8), sizeof (u64));
clib_time_init (&utm->clib_time);
init_error_string_table (utm);
diff --git a/src/vcl.am b/src/vcl.am
index f090041b884..5f48f6df168 100644
--- a/src/vcl.am
+++ b/src/vcl.am
@@ -68,3 +68,5 @@ sock_test_client_SOURCES = vcl/sock_test_client.c
nobase_include_HEADERS += \
vcl/sock_test.h
+
+# vi:syntax=automake
diff --git a/src/vnet/session-apps/echo_server.c b/src/vnet/session-apps/echo_server.c
index 024ffa66f96..0d0350819c9 100644
--- a/src/vnet/session-apps/echo_server.c
+++ b/src/vnet/session-apps/echo_server.c
@@ -245,7 +245,6 @@ static session_cb_vft_t echo_server_session_cb_vft = {
.session_disconnect_callback = echo_server_session_disconnect_callback,
.session_connected_callback = echo_server_session_connected_callback,
.add_segment_callback = echo_server_add_segment_callback,
- .redirect_connect_callback = echo_server_redirect_connect_callback,
.builtin_server_rx_callback = echo_server_rx_callback,
.session_reset_callback = echo_server_session_reset_callback
};
@@ -387,7 +386,7 @@ echo_server_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
u8 server_uri_set = 0, *appns_id = 0;
u64 tmp, appns_flags = 0, appns_secret = 0;
char *default_uri = "tcp://0.0.0.0/1234";
- int rv;
+ int rv, is_stop = 0;
esm->no_echo = 0;
esm->fifo_size = 64 << 10;
@@ -431,11 +430,29 @@ echo_server_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
appns_flags |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
else if (unformat (input, "secret %lu", &appns_secret))
;
+ else if (unformat (input, "stop"))
+ is_stop = 1;
else
return clib_error_return (0, "failed: unknown input `%U'",
format_unformat_error, input);
}
+ if (is_stop)
+ {
+ if (esm->app_index == (u32) ~ 0)
+ {
+ clib_warning ("server not running");
+ return clib_error_return (0, "failed: server not running");
+ }
+ rv = echo_server_detach ();
+ if (rv)
+ {
+ clib_warning ("failed: detach");
+ return clib_error_return (0, "failed: server detach %d", rv);
+ }
+ return 0;
+ }
+
vnet_session_enable_disable (vm, 1 /* turn on TCP, etc. */ );
if (!server_uri_set)
diff --git a/src/vnet/session-apps/http_server.c b/src/vnet/session-apps/http_server.c
index 07eaab4c1ae..eeb755b0fc4 100644
--- a/src/vnet/session-apps/http_server.c
+++ b/src/vnet/session-apps/http_server.c
@@ -471,19 +471,11 @@ http_server_add_segment_callback (u32 client_index, const ssvm_private_t * sp)
return -1;
}
-static int
-http_server_redirect_connect_callback (u32 client_index, void *mp)
-{
- clib_warning ("called...");
- return -1;
-}
-
static session_cb_vft_t http_server_session_cb_vft = {
.session_accept_callback = http_server_session_accept_callback,
.session_disconnect_callback = http_server_session_disconnect_callback,
.session_connected_callback = http_server_session_connected_callback,
.add_segment_callback = http_server_add_segment_callback,
- .redirect_connect_callback = http_server_redirect_connect_callback,
.builtin_server_rx_callback = http_server_rx_callback,
.session_reset_callback = http_server_session_reset_callback
};
diff --git a/src/vnet/session-apps/proxy.c b/src/vnet/session-apps/proxy.c
index 2fdb63f1780..1cbacdbc894 100644
--- a/src/vnet/session-apps/proxy.c
+++ b/src/vnet/session-apps/proxy.c
@@ -146,13 +146,6 @@ proxy_add_segment_callback (u32 client_index, const ssvm_private_t * sp)
}
static int
-proxy_redirect_connect_callback (u32 client_index, void *mp)
-{
- clib_warning ("called...");
- return -1;
-}
-
-static int
proxy_rx_callback (stream_session_t * s)
{
u32 max_dequeue;
@@ -239,7 +232,6 @@ static session_cb_vft_t proxy_session_cb_vft = {
.session_disconnect_callback = proxy_disconnect_callback,
.session_connected_callback = proxy_connected_callback,
.add_segment_callback = proxy_add_segment_callback,
- .redirect_connect_callback = proxy_redirect_connect_callback,
.builtin_server_rx_callback = proxy_rx_callback,
.session_reset_callback = proxy_reset_callback
};
diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c
index 71fc93f960f..9020d1c2864 100644
--- a/src/vnet/session/application.c
+++ b/src/vnet/session/application.c
@@ -28,11 +28,6 @@ static application_t *app_pool;
*/
static uword *app_by_api_client_index;
-/**
- * Default application event queue size
- */
-static u32 default_app_evt_queue_size = 128;
-
static u8 *
app_get_name_from_reg_index (application_t * app)
{
@@ -138,6 +133,7 @@ application_new ()
app->index = application_get_index (app);
app->connects_seg_manager = APP_INVALID_SEGMENT_MANAGER_INDEX;
app->first_segment_manager = APP_INVALID_SEGMENT_MANAGER_INDEX;
+ app->local_segment_manager = APP_INVALID_SEGMENT_MANAGER_INDEX;
if (CLIB_DEBUG > 1)
clib_warning ("[%d] New app (%d)", getpid (), app->index);
return app;
@@ -147,8 +143,8 @@ void
application_del (application_t * app)
{
vnet_unbind_args_t _a, *a = &_a;
- segment_manager_t *sm;
u64 handle, *handles = 0;
+ segment_manager_t *sm;
u32 index;
int i;
@@ -207,6 +203,12 @@ application_del (application_t * app)
segment_manager_del (sm);
}
}
+
+ /*
+ * Local connections cleanup
+ */
+ application_local_sessions_del (app);
+
application_table_del (app);
pool_put (app_pool, app);
}
@@ -255,8 +257,8 @@ int
application_init (application_t * app, u32 api_client_index, u64 * options,
session_cb_vft_t * cb_fns)
{
- u32 app_evt_queue_size, first_seg_size, prealloc_fifo_pairs;
ssvm_segment_type_t seg_type = SSVM_SEGMENT_MEMFD;
+ u32 first_seg_size, prealloc_fifo_pairs;
segment_manager_properties_t *props;
vl_api_registration_t *reg;
segment_manager_t *sm;
@@ -298,15 +300,14 @@ application_init (application_t * app, u32 api_client_index, u64 * options,
props->rx_fifo_size = options[APP_OPTIONS_RX_FIFO_SIZE];
if (options[APP_OPTIONS_TX_FIFO_SIZE])
props->tx_fifo_size = options[APP_OPTIONS_TX_FIFO_SIZE];
+ if (options[APP_OPTIONS_EVT_QUEUE_SIZE])
+ props->evt_q_size = options[APP_OPTIONS_EVT_QUEUE_SIZE];
props->segment_type = seg_type;
- app_evt_queue_size = options[APP_OPTIONS_EVT_QUEUE_SIZE] > 0 ?
- options[APP_OPTIONS_EVT_QUEUE_SIZE] : default_app_evt_queue_size;
first_seg_size = options[APP_OPTIONS_SEGMENT_SIZE];
prealloc_fifo_pairs = options[APP_OPTIONS_PREALLOC_FIFO_PAIRS];
- if ((rv = segment_manager_init (sm, first_seg_size, app_evt_queue_size,
- prealloc_fifo_pairs)))
+ if ((rv = segment_manager_init (sm, first_seg_size, prealloc_fifo_pairs)))
return rv;
sm->first_is_protected = 1;
@@ -319,6 +320,7 @@ application_init (application_t * app, u32 api_client_index, u64 * options,
app->cb_fns = *cb_fns;
app->ns_index = options[APP_OPTIONS_NAMESPACE];
app->listeners_table = hash_create (0, sizeof (u64));
+ app->local_connects = hash_create (0, sizeof (u64));
app->proxied_transports = options[APP_OPTIONS_PROXY_TRANSPORT];
app->event_queue = segment_manager_event_queue (sm);
@@ -333,6 +335,13 @@ application_init (application_t * app, u32 api_client_index, u64 * options,
/* Add app to lookup by api_client_index table */
application_table_add (app);
+ /*
+ * Segment manager for local sessions
+ */
+ sm = segment_manager_new ();
+ sm->app_index = app->index;
+ app->local_segment_manager = segment_manager_index (sm);
+
return 0;
}
@@ -388,11 +397,11 @@ application_alloc_segment_manager (application_t * app)
*/
int
application_start_listen (application_t * srv, session_endpoint_t * sep,
- u64 * res)
+ session_handle_t * res)
{
segment_manager_t *sm;
stream_session_t *s;
- u64 handle;
+ session_handle_t handle;
session_type_t sst;
sst = session_type_from_proto_and_ip (sep->transport_proto, sep->is_ip4);
@@ -425,7 +434,7 @@ err:
* Stop listening on session associated to handle
*/
int
-application_stop_listen (application_t * srv, u64 handle)
+application_stop_listen (application_t * srv, session_handle_t handle)
{
stream_session_t *listener;
uword *indexp;
@@ -499,6 +508,26 @@ application_get_listen_segment_manager (application_t * app,
return segment_manager_get (*smp);
}
+segment_manager_t *
+application_get_local_segment_manager (application_t * app)
+{
+ return segment_manager_get (app->local_segment_manager);
+}
+
+segment_manager_t *
+application_get_local_segment_manager_w_session (application_t * app,
+ local_session_t * ls)
+{
+ stream_session_t *listener;
+ if (application_local_session_listener_has_transport (ls))
+ {
+ listener = listen_session_get (ls->listener_session_type,
+ ls->listener_index);
+ return application_get_listen_segment_manager (app, listener);
+ }
+ return segment_manager_get (app->local_segment_manager);
+}
+
int
application_is_proxy (application_t * app)
{
@@ -731,12 +760,407 @@ application_get_segment_manager_properties (u32 app_index)
return &app->sm_properties;
}
+local_session_t *
+application_alloc_local_session (application_t * app)
+{
+ local_session_t *s;
+ pool_get (app->local_sessions, s);
+ memset (s, 0, sizeof (*s));
+ s->app_index = app->index;
+ s->session_index = s - app->local_sessions;
+ s->session_type = session_type_from_proto_and_ip (TRANSPORT_PROTO_NONE, 0);
+ return s;
+}
+
+void
+application_free_local_session (application_t * app, local_session_t * s)
+{
+ pool_put (app->local_sessions, s);
+ if (CLIB_DEBUG)
+ memset (s, 0xfc, sizeof (*s));
+}
+
+local_session_t *
+application_get_local_session (application_t * app, u32 session_index)
+{
+ return pool_elt_at_index (app->local_sessions, session_index);
+}
+
+local_session_t *
+application_get_local_session_from_handle (session_handle_t handle)
+{
+ application_t *server;
+ u32 session_index, server_index;
+ local_session_parse_handle (handle, &server_index, &session_index);
+ server = application_get (server_index);
+ return application_get_local_session (server, session_index);
+}
+
+always_inline void
+application_local_listener_session_endpoint (local_session_t * ll,
+ session_endpoint_t * sep)
+{
+ sep->transport_proto =
+ session_type_transport_proto (ll->listener_session_type);
+ sep->port = ll->port;
+ sep->is_ip4 = ll->listener_session_type & 1;
+}
+
+int
+application_start_local_listen (application_t * server,
+ session_endpoint_t * sep,
+ session_handle_t * handle)
+{
+ session_handle_t lh;
+ local_session_t *ll;
+ u32 table_index;
+
+ table_index = application_local_session_table (server);
+
+ /* An exact sep match, as opposed to session_lookup_local_listener */
+ lh = session_lookup_endpoint_listener (table_index, sep, 1);
+ if (lh != SESSION_INVALID_HANDLE)
+ return VNET_API_ERROR_ADDRESS_IN_USE;
+
+ pool_get (server->local_listen_sessions, ll);
+ memset (ll, 0, sizeof (*ll));
+ ll->session_type = session_type_from_proto_and_ip (TRANSPORT_PROTO_NONE, 0);
+ ll->app_index = server->index;
+ ll->session_index = ll - server->local_listen_sessions;
+ ll->port = sep->port;
+ /* Store the original session type for the unbind */
+ ll->listener_session_type =
+ session_type_from_proto_and_ip (sep->transport_proto, sep->is_ip4);
+
+ *handle = application_local_session_handle (ll);
+ session_lookup_add_session_endpoint (table_index, sep, *handle);
+
+ return 0;
+}
+
+/**
+ * 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.
+ */
+int
+application_stop_local_listen (application_t * server, session_handle_t lh)
+{
+ session_endpoint_t sep = SESSION_ENDPOINT_NULL;
+ u32 table_index, ll_index, server_index;
+ stream_session_t *sl = 0;
+ local_session_t *ll, *ls;
+
+ table_index = application_local_session_table (server);
+
+ /* We have both local and global table binds. Figure from global what
+ * the sep we should be cleaning up is.
+ */
+ if (!session_handle_is_local (lh))
+ {
+ sl = listen_session_get_from_handle (lh);
+ if (!sl || listen_session_get_local_session_endpoint (sl, &sep))
+ {
+ clib_warning ("broken listener");
+ return -1;
+ }
+ lh = session_lookup_endpoint_listener (table_index, &sep, 0);
+ if (lh == SESSION_INVALID_HANDLE)
+ return -1;
+ }
+
+ local_session_parse_handle (lh, &server_index, &ll_index);
+ ASSERT (server->index == server_index);
+ if (!(ll = application_get_local_listen_session (server, ll_index)))
+ {
+ clib_warning ("no local listener");
+ return -1;
+ }
+ application_local_listener_session_endpoint (ll, &sep);
+ session_lookup_del_session_endpoint (table_index, &sep);
+
+ /* *INDENT-OFF* */
+ pool_foreach (ls, server->local_sessions, ({
+ if (ls->listener_index == ll->session_index)
+ application_local_session_disconnect (server->index, ls);
+ }));
+ /* *INDENT-ON* */
+ pool_put_index (server->local_listen_sessions, ll->session_index);
+
+ return 0;
+}
+
+int
+application_local_session_connect (u32 table_index, application_t * client,
+ application_t * server,
+ local_session_t * ll, u32 opaque)
+{
+ u32 seg_size, evt_q_sz, evt_q_elts, margin = 16 << 10;
+ segment_manager_properties_t *props, *cprops;
+ int rv, has_transport, seg_index;
+ svm_fifo_segment_private_t *seg;
+ segment_manager_t *sm;
+ local_session_t *ls;
+ svm_queue_t *sq, *cq;
+
+ ls = application_alloc_local_session (server);
+
+ props = application_segment_manager_properties (server);
+ cprops = application_segment_manager_properties (client);
+ evt_q_elts = props->evt_q_size + cprops->evt_q_size;
+ evt_q_sz = evt_q_elts * sizeof (session_fifo_event_t);
+ seg_size = props->rx_fifo_size + props->tx_fifo_size + evt_q_sz + margin;
+
+ has_transport = session_has_transport ((stream_session_t *) ll);
+ if (!has_transport)
+ {
+ /* Local sessions don't have backing transport */
+ ls->port = ll->port;
+ sm = application_get_local_segment_manager (server);
+ }
+ else
+ {
+ stream_session_t *sl = (stream_session_t *) ll;
+ transport_connection_t *tc;
+ tc = listen_session_get_transport (sl);
+ ls->port = tc->lcl_port;
+ sm = application_get_listen_segment_manager (server, sl);
+ }
+
+ seg_index = segment_manager_add_segment (sm, seg_size);
+ if (seg_index < 0)
+ {
+ clib_warning ("failed to add new cut-through segment");
+ return seg_index;
+ }
+ seg = segment_manager_get_segment_w_lock (sm, seg_index);
+ sq = segment_manager_alloc_queue (seg, props->evt_q_size);
+ cq = segment_manager_alloc_queue (seg, cprops->evt_q_size);
+ ls->server_evt_q = pointer_to_uword (sq);
+ ls->client_evt_q = pointer_to_uword (cq);
+ rv = segment_manager_try_alloc_fifos (seg, props->rx_fifo_size,
+ props->tx_fifo_size,
+ &ls->server_rx_fifo,
+ &ls->server_tx_fifo);
+ if (rv)
+ {
+ clib_warning ("failed to add fifos in cut-through segment");
+ segment_manager_segment_reader_unlock (sm);
+ goto failed;
+ }
+ ls->server_rx_fifo->master_session_index = ls->session_index;
+ ls->server_tx_fifo->master_session_index = ls->session_index;
+ ls->server_rx_fifo->master_thread_index = ~0;
+ ls->server_tx_fifo->master_thread_index = ~0;
+ ls->svm_segment_index = seg_index;
+ ls->listener_index = ll->session_index;
+ ls->client_index = client->index;
+ ls->client_opaque = opaque;
+ ls->listener_session_type = ll->session_type;
+
+ if ((rv = server->cb_fns.add_segment_callback (server->api_client_index,
+ &seg->ssvm)))
+ {
+ clib_warning ("failed to notify server of new segment");
+ segment_manager_segment_reader_unlock (sm);
+ goto failed;
+ }
+ segment_manager_segment_reader_unlock (sm);
+ if ((rv = server->cb_fns.session_accept_callback ((stream_session_t *) ls)))
+ {
+ clib_warning ("failed to send accept cut-through notify to server");
+ goto failed;
+ }
+ if (server->flags & APP_OPTIONS_FLAGS_IS_BUILTIN)
+ application_local_session_connect_notify (ls);
+
+ return 0;
+
+failed:
+ if (!has_transport)
+ segment_manager_del_segment (sm, seg);
+ return rv;
+}
+
+static uword
+application_client_local_connect_key (local_session_t * ls)
+{
+ return ((uword) ls->app_index << 32 | (uword) ls->session_index);
+}
+
+static void
+application_client_local_connect_key_parse (uword key, u32 * app_index,
+ u32 * session_index)
+{
+ *app_index = key >> 32;
+ *session_index = key & 0xFFFFFFFF;
+}
+
+int
+application_local_session_connect_notify (local_session_t * ls)
+{
+ svm_fifo_segment_private_t *seg;
+ application_t *client, *server;
+ segment_manager_t *sm;
+ int rv, is_fail = 0;
+ uword client_key;
+
+ client = application_get (ls->client_index);
+ server = application_get (ls->app_index);
+ sm = application_get_local_segment_manager_w_session (server, ls);
+ seg = segment_manager_get_segment_w_lock (sm, ls->svm_segment_index);
+ if ((rv = client->cb_fns.add_segment_callback (client->api_client_index,
+ &seg->ssvm)))
+ {
+ clib_warning ("failed to notify client %u of new segment",
+ ls->client_index);
+ segment_manager_segment_reader_unlock (sm);
+ application_local_session_disconnect (ls->client_index, ls);
+ is_fail = 1;
+ }
+ else
+ {
+ segment_manager_segment_reader_unlock (sm);
+ }
+
+ client->cb_fns.session_connected_callback (client->index, ls->client_opaque,
+ (stream_session_t *) ls,
+ is_fail);
+
+ client_key = application_client_local_connect_key (ls);
+ hash_set (client->local_connects, client_key, client_key);
+ return 0;
+}
+
+int
+application_local_session_disconnect (u32 app_index, local_session_t * ls)
+{
+ svm_fifo_segment_private_t *seg;
+ application_t *client, *server;
+ segment_manager_t *sm;
+ uword client_key;
+
+ client = application_get_if_valid (ls->client_index);
+ server = application_get (ls->app_index);
+
+ if (ls->session_state == SESSION_STATE_CLOSED)
+ {
+ cleanup:
+ client_key = application_client_local_connect_key (ls);
+ sm = application_get_local_segment_manager_w_session (server, ls);
+ seg = segment_manager_get_segment (sm, ls->svm_segment_index);
+
+ if (client)
+ {
+ hash_unset (client->local_connects, client_key);
+ client->cb_fns.del_segment_callback (client->api_client_index,
+ &seg->ssvm);
+ }
+
+ server->cb_fns.del_segment_callback (server->api_client_index,
+ &seg->ssvm);
+ segment_manager_del_segment (sm, seg);
+ application_free_local_session (server, ls);
+ return 0;
+ }
+
+ if (app_index == ls->client_index)
+ {
+ send_local_session_disconnect_callback (ls->app_index, ls);
+ }
+ else
+ {
+ if (!client)
+ {
+ goto cleanup;
+ }
+ else if (ls->session_state < SESSION_STATE_READY)
+ {
+ client->cb_fns.session_connected_callback (client->index,
+ ls->client_opaque,
+ (stream_session_t *) ls,
+ 1 /* is_fail */ );
+ ls->session_state = SESSION_STATE_CLOSED;
+ goto cleanup;
+ }
+ else
+ {
+ send_local_session_disconnect_callback (ls->client_index, ls);
+ }
+ }
+
+ ls->session_state = SESSION_STATE_CLOSED;
+
+ return 0;
+}
+
+void
+application_local_sessions_del (application_t * app)
+{
+ u32 index, server_index, session_index, table_index;
+ segment_manager_t *sm;
+ u64 handle, *handles = 0;
+ local_session_t *ls, *ll;
+ application_t *server;
+ session_endpoint_t sep;
+ int i;
+
+ /*
+ * Local listens. Don't bother with local sessions, we clean them lower
+ */
+ table_index = application_local_session_table (app);
+ /* *INDENT-OFF* */
+ pool_foreach (ll, app->local_listen_sessions, ({
+ application_local_listener_session_endpoint (ll, &sep);
+ session_lookup_del_session_endpoint (table_index, &sep);
+ }));
+ /* *INDENT-ON* */
+
+ /*
+ * Local sessions
+ */
+ if (app->local_sessions)
+ {
+ /* *INDENT-OFF* */
+ pool_foreach (ls, app->local_sessions, ({
+ application_local_session_disconnect (app->index, ls);
+ }));
+ /* *INDENT-ON* */
+ }
+
+ /*
+ * Local connects
+ */
+ vec_reset_length (handles);
+ /* *INDENT-OFF* */
+ hash_foreach (handle, index, app->local_connects, ({
+ vec_add1 (handles, handle);
+ }));
+ /* *INDENT-ON* */
+
+ for (i = 0; i < vec_len (handles); i++)
+ {
+ application_client_local_connect_key_parse (handles[i], &server_index,
+ &session_index);
+ server = application_get_if_valid (server_index);
+ if (server)
+ {
+ ls = application_get_local_session (server, session_index);
+ application_local_session_disconnect (app->index, ls);
+ }
+ }
+
+ sm = segment_manager_get (app->local_segment_manager);
+ sm->app_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
+ segment_manager_del (sm);
+}
+
u8 *
format_application_listener (u8 * s, va_list * args)
{
application_t *app = va_arg (*args, application_t *);
u64 handle = va_arg (*args, u64);
- u32 index = va_arg (*args, u32);
+ u32 sm_index = va_arg (*args, u32);
int verbose = va_arg (*args, int);
stream_session_t *listener;
u8 *app_name, *str;
@@ -759,7 +1183,7 @@ format_application_listener (u8 * s, va_list * args)
if (verbose)
{
s = format (s, "%-40s%-20s%-15u%-15u%-10u", str, app_name,
- app->api_client_index, handle, index);
+ app->api_client_index, handle, sm_index);
}
else
s = format (s, "%-40s%-20s", str, app_name);
@@ -832,6 +1256,76 @@ application_format_connects (application_t * app, int verbose)
vec_free (app_name);
}
+void
+application_format_local_sessions (application_t * app, int verbose)
+{
+ vlib_main_t *vm = vlib_get_main ();
+ local_session_t *ls;
+ transport_proto_t tp;
+ u8 *conn = 0;
+
+ /* Header */
+ if (app == 0)
+ {
+ vlib_cli_output (vm, "%-40s%-15s%-20s", "Connection", "ServerApp",
+ "ClientApp");
+ return;
+ }
+
+ /* *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_index, "*");
+ vec_reset_length (conn);
+ }));
+ pool_foreach (ls, app->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_index,
+ ls->client_index);
+ vec_reset_length (conn);
+ }));
+ /* *INDENT-ON* */
+
+ vec_free (conn);
+}
+
+void
+application_format_local_connects (application_t * app, int verbose)
+{
+ vlib_main_t *vm = vlib_get_main ();
+ u32 app_index, session_index;
+ application_t *server;
+ 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;
+ }
+
+ /* *INDENT-OFF* */
+ hash_foreach (client_key, value, app->local_connects, ({
+ application_client_local_connect_key_parse (client_key, &app_index,
+ &session_index);
+ server = application_get (app_index);
+ ls = application_get_local_session (server, session_index);
+ vlib_cli_output (vm, "%-40s%-15s%-20s", "TODO", ls->app_index, ls->client_index);
+ }));
+ /* *INDENT-ON* */
+}
+
u8 *
format_application (u8 * s, va_list * args)
{
@@ -869,13 +1363,92 @@ format_application (u8 * s, va_list * args)
return s;
}
+
+void
+application_format_all_listeners (vlib_main_t * vm, int do_local, int verbose)
+{
+ application_t *app;
+ u32 sm_index;
+ u64 handle;
+
+ if (!pool_elts (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_pool, ({
+ if (!pool_elts (app->local_sessions)
+ && !pool_elts(app->local_connects))
+ continue;
+ application_format_local_sessions (app, verbose);
+ }));
+ /* *INDENT-ON* */
+ }
+ else
+ {
+ vlib_cli_output (vm, "%U", format_application_listener, 0 /* header */ ,
+ 0, 0, verbose);
+
+ /* *INDENT-OFF* */
+ pool_foreach (app, app_pool, ({
+ if (hash_elts (app->listeners_table) == 0)
+ continue;
+ hash_foreach (handle, sm_index, app->listeners_table, ({
+ vlib_cli_output (vm, "%U", format_application_listener, app,
+ handle, sm_index, verbose);
+ }));
+ }));
+ /* *INDENT-ON* */
+ }
+}
+
+void
+application_format_all_clients (vlib_main_t * vm, int do_local, int verbose)
+{
+ application_t *app;
+
+ if (!pool_elts (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_pool, ({
+ if (app->local_connects)
+ application_format_local_connects (app, verbose);
+ }));
+ /* *INDENT-ON* */
+ }
+ else
+ {
+ application_format_connects (0, verbose);
+
+ /* *INDENT-OFF* */
+ pool_foreach (app, app_pool, ({
+ if (app->connects_seg_manager == (u32)~0)
+ continue;
+ 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;
- int do_server = 0;
- int do_client = 0;
int verbose = 0;
session_cli_return_if_not_enabled ();
@@ -886,6 +1459,8 @@ show_app_command_fn (vlib_main_t * vm, unformat_input_t * input,
do_server = 1;
else if (unformat (input, "client"))
do_client = 1;
+ else if (unformat (input, "local"))
+ do_local = 1;
else if (unformat (input, "verbose"))
verbose = 1;
else
@@ -893,49 +1468,10 @@ show_app_command_fn (vlib_main_t * vm, unformat_input_t * input,
}
if (do_server)
- {
- u64 handle;
- u32 index;
- if (pool_elts (app_pool))
- {
- vlib_cli_output (vm, "%U", format_application_listener,
- 0 /* header */ , 0, 0, verbose);
-
- /* *INDENT-OFF* */
- pool_foreach (app, app_pool, ({
- /* App's listener sessions */
- if (hash_elts (app->listeners_table) == 0)
- continue;
- hash_foreach (handle, index, app->listeners_table, ({
- vlib_cli_output (vm, "%U", format_application_listener, app,
- handle, index, verbose);
- }));
- }));
- /* *INDENT-ON* */
-
- }
- else
- vlib_cli_output (vm, "No active server bindings");
- }
+ application_format_all_listeners (vm, do_local, verbose);
if (do_client)
- {
- if (pool_elts (app_pool))
- {
- application_format_connects (0, verbose);
-
- /* *INDENT-OFF* */
- pool_foreach (app, app_pool,
- ({
- if (app->connects_seg_manager == (u32)~0)
- continue;
- application_format_connects (app, verbose);
- }));
- /* *INDENT-ON* */
- }
- else
- vlib_cli_output (vm, "No active client bindings");
- }
+ application_format_all_clients (vm, do_local, verbose);
/* Print app related info */
if (!do_server && !do_client)
diff --git a/src/vnet/session/application.h b/src/vnet/session/application.h
index 36ae6fce8b2..4938bef08bd 100644
--- a/src/vnet/session/application.h
+++ b/src/vnet/session/application.h
@@ -32,6 +32,9 @@ typedef struct _stream_session_cb_vft
/** Notify server of new segment */
int (*add_segment_callback) (u32 api_client_index,
const ssvm_private_t * ssvm_seg);
+ /** Notify server of new segment */
+ int (*del_segment_callback) (u32 api_client_index,
+ const ssvm_private_t * ssvm_seg);
/** Notify server of newly accepted session */
int (*session_accept_callback) (stream_session_t * new_session);
@@ -49,8 +52,6 @@ typedef struct _stream_session_cb_vft
/** Direct RX callback, for built-in servers */
int (*builtin_server_rx_callback) (stream_session_t * session);
- /** Redirect connection to local server */
- int (*redirect_connect_callback) (u32 api_client_index, void *mp);
} session_cb_vft_t;
typedef struct _application
@@ -81,8 +82,9 @@ typedef struct _application
session_cb_vft_t cb_fns;
/*
- * svm segment management
+ * ssvm (fifo) segment management
*/
+ /** Segment manager used for outgoing connects issued by the app */
u32 connects_seg_manager;
/** Lookup tables for listeners. Value is segment manager index */
@@ -100,10 +102,25 @@ typedef struct _application
segment_manager_properties_t sm_properties;
u16 proxied_transports;
+
+ /*
+ * Local "cut through" connections specific
+ */
+
+ /** Segment manager used for incoming "cut through" connects */
+ u32 local_segment_manager;
+
+ /** Pool of local listen sessions */
+ local_session_t *local_listen_sessions;
+
+ /** Pool of local sessions the app owns (as a server) */
+ local_session_t *local_sessions;
+
+ /** Hash table of the app's local connects */
+ uword *local_connects;
} application_t;
#define APP_INVALID_INDEX ((u32)~0)
-#define APP_DROP_INDEX (((u32)~0) - 1)
#define APP_NS_INVALID_INDEX ((u32)~0)
#define APP_INVALID_SEGMENT_MANAGER_INDEX ((u32) ~0)
@@ -117,8 +134,14 @@ application_t *application_lookup (u32 api_client_index);
u32 application_get_index (application_t * app);
int application_start_listen (application_t * app,
- session_endpoint_t * tep, u64 * handle);
-int application_stop_listen (application_t * srv, u64 handle);
+ session_endpoint_t * tep,
+ session_handle_t * handle);
+int application_start_local_listen (application_t * server,
+ session_endpoint_t * sep,
+ session_handle_t * handle);
+int application_stop_listen (application_t * srv, session_handle_t handle);
+int application_stop_local_listen (application_t * server,
+ session_handle_t listener_handle);
int application_open_session (application_t * app, session_endpoint_t * tep,
u32 api_context);
int application_api_queue_is_full (application_t * app);
@@ -126,7 +149,7 @@ int application_api_queue_is_full (application_t * app);
segment_manager_t *application_get_listen_segment_manager (application_t *
app,
stream_session_t *
- s);
+ ls);
segment_manager_t *application_get_connect_segment_manager (application_t *
app);
int application_is_proxy (application_t * app);
@@ -151,6 +174,67 @@ segment_manager_properties_t *application_get_segment_manager_properties (u32
segment_manager_properties_t
* application_segment_manager_properties (application_t * app);
+local_session_t *application_alloc_local_session (application_t * app);
+void application_free_local_session (application_t * app,
+ local_session_t * ls);
+local_session_t *application_get_local_session (application_t * app,
+ u32 session_index);
+local_session_t *application_get_local_session_from_handle (session_handle_t
+ handle);
+int application_local_session_connect (u32 table_index,
+ application_t * client,
+ application_t * server,
+ local_session_t * ll, u32 opaque);
+int application_local_session_connect_notify (local_session_t * ls);
+int application_local_session_disconnect (u32 app_index,
+ local_session_t * ls);
+void application_local_sessions_del (application_t * app);
+
+always_inline u32
+local_session_id (local_session_t * ll)
+{
+ ASSERT (ll->app_index < (2 << 16) && ll->session_index < (2 << 16));
+ return ((u32) ll->app_index << 16 | (u32) ll->session_index);
+}
+
+always_inline void
+local_session_parse_id (u32 ls_id, u32 * app_index, u32 * session_index)
+{
+ *app_index = ls_id >> 16;
+ *session_index = ls_id & 0xFFF;
+}
+
+always_inline void
+local_session_parse_handle (session_handle_t handle, u32 * server_index,
+ u32 * session_index)
+{
+ u32 bottom;
+ ASSERT ((handle >> 32) == SESSION_LOCAL_TABLE_PREFIX);
+ bottom = (handle & 0xFFFFFFFF);
+ local_session_parse_id (bottom, server_index, session_index);
+}
+
+always_inline session_handle_t
+application_local_session_handle (local_session_t * ls)
+{
+ return ((u64) SESSION_LOCAL_TABLE_PREFIX << 32) | local_session_id (ls);
+}
+
+always_inline local_session_t *
+application_get_local_listen_session (application_t * app, u32 session_index)
+{
+ return pool_elt_at_index (app->local_listen_sessions, session_index);
+}
+
+always_inline u8
+application_local_session_listener_has_transport (local_session_t * ls)
+{
+ transport_proto_t tp;
+ tp = session_type_transport_proto (ls->listener_session_type);
+ return (tp != TRANSPORT_PROTO_NONE);
+}
+
+
#endif /* SRC_VNET_SESSION_APPLICATION_H_ */
/*
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;
}
diff --git a/src/vnet/session/application_interface.h b/src/vnet/session/application_interface.h
index 8db318fa413..4b7a2dfa66c 100644
--- a/src/vnet/session/application_interface.h
+++ b/src/vnet/session/application_interface.h
@@ -87,12 +87,12 @@ typedef struct _vnet_connect_args
/* Used for redirects */
void *mp;
- u64 session_handle;
+ session_handle_t session_handle;
} vnet_connect_args_t;
typedef struct _vnet_disconnect_args_t
{
- u64 handle;
+ session_handle_t handle;
u32 app_index;
} vnet_disconnect_args_t;
@@ -152,6 +152,9 @@ int
api_parse_session_handle (u64 handle, u32 * session_index,
u32 * thread_index);
+void send_local_session_disconnect_callback (u32 app_index,
+ local_session_t * ls);
+
#endif /* __included_uri_h__ */
/*
diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c
index f8af3fb45c8..eb2455732e6 100644
--- a/src/vnet/session/segment_manager.c
+++ b/src/vnet/session/segment_manager.c
@@ -27,8 +27,9 @@ static u32 segment_name_counter = 0;
/**
* Default fifo and segment size. TODO config.
*/
-u32 default_fifo_size = 1 << 12;
-u32 default_segment_size = 1 << 20;
+static u32 default_fifo_size = 1 << 12;
+static u32 default_segment_size = 1 << 20;
+static u32 default_app_evt_queue_size = 128;
segment_manager_properties_t *
segment_manager_properties_get (segment_manager_t * sm)
@@ -42,6 +43,7 @@ segment_manager_properties_init (segment_manager_properties_t * props)
props->add_segment_size = default_segment_size;
props->rx_fifo_size = default_fifo_size;
props->tx_fifo_size = default_fifo_size;
+ props->evt_q_size = default_app_evt_queue_size;
return props;
}
@@ -67,7 +69,7 @@ segment_manager_segment_index (segment_manager_t * sm,
/**
* Remove segment without lock
*/
-always_inline void
+void
segment_manager_del_segment (segment_manager_t * sm,
svm_fifo_segment_private_t * fs)
{
@@ -131,6 +133,7 @@ segment_manager_get_segment_w_lock (segment_manager_t * sm, u32 segment_index)
void
segment_manager_segment_reader_unlock (segment_manager_t * sm)
{
+ ASSERT (sm->segments_rwlock->n_readers > 0);
clib_rwlock_reader_unlock (&sm->segments_rwlock);
}
@@ -146,7 +149,7 @@ segment_manager_segment_writer_unlock (segment_manager_t * sm)
* If needed a writer's lock is acquired before allocating a new segment
* to avoid affecting any of the segments pool readers.
*/
-always_inline int
+int
segment_manager_add_segment (segment_manager_t * sm, u32 segment_size)
{
segment_manager_main_t *smm = &segment_manager_main;
@@ -243,7 +246,7 @@ segment_manager_new ()
*/
int
segment_manager_init (segment_manager_t * sm, u32 first_seg_size,
- u32 evt_q_size, u32 prealloc_fifo_pairs)
+ u32 prealloc_fifo_pairs)
{
u32 rx_fifo_size, tx_fifo_size, pair_size;
u32 rx_rounded_data_size, tx_rounded_data_size;
@@ -283,10 +286,11 @@ segment_manager_init (segment_manager_t * sm, u32 first_seg_size,
return seg_index;
}
+ segment = segment_manager_get_segment (sm, seg_index);
if (i == 0)
- sm->event_queue = segment_manager_alloc_queue (sm, evt_q_size);
+ sm->event_queue = segment_manager_alloc_queue (segment,
+ props->evt_q_size);
- segment = segment_manager_get_segment (sm, seg_index);
svm_fifo_segment_preallocate_fifo_pairs (segment,
props->rx_fifo_size,
props->tx_fifo_size,
@@ -304,7 +308,9 @@ segment_manager_init (segment_manager_t * sm, u32 first_seg_size,
clib_warning ("Failed to allocate segment");
return seg_index;
}
- sm->event_queue = segment_manager_alloc_queue (sm, evt_q_size);
+ segment = segment_manager_get_segment (sm, seg_index);
+ sm->event_queue = segment_manager_alloc_queue (segment,
+ props->evt_q_size);
}
return 0;
@@ -422,10 +428,10 @@ segment_manager_init_del (segment_manager_t * sm)
}
}
-always_inline int
-segment_try_alloc_fifos (svm_fifo_segment_private_t * fifo_segment,
- u32 rx_fifo_size, u32 tx_fifo_size,
- svm_fifo_t ** rx_fifo, svm_fifo_t ** tx_fifo)
+int
+segment_manager_try_alloc_fifos (svm_fifo_segment_private_t * fifo_segment,
+ u32 rx_fifo_size, u32 tx_fifo_size,
+ svm_fifo_t ** rx_fifo, svm_fifo_t ** tx_fifo)
{
rx_fifo_size = clib_max (rx_fifo_size, default_fifo_size);
*rx_fifo = svm_fifo_segment_alloc_fifo (fifo_segment, rx_fifo_size,
@@ -466,7 +472,7 @@ segment_manager_alloc_session_fifos (segment_manager_t * sm,
svm_fifo_t ** tx_fifo,
u32 * fifo_segment_index)
{
- svm_fifo_segment_private_t *fifo_segment;
+ svm_fifo_segment_private_t *fifo_segment = 0;
int alloc_fail = 1, rv = 0, new_fs_index;
segment_manager_properties_t *props;
u8 added_a_segment = 0;
@@ -481,9 +487,10 @@ segment_manager_alloc_session_fifos (segment_manager_t * sm,
/* *INDENT-OFF* */
segment_manager_foreach_segment_w_lock (fifo_segment, sm, ({
- alloc_fail = segment_try_alloc_fifos (fifo_segment, props->rx_fifo_size,
- props->tx_fifo_size, rx_fifo,
- tx_fifo);
+ alloc_fail = segment_manager_try_alloc_fifos (fifo_segment,
+ props->rx_fifo_size,
+ props->tx_fifo_size,
+ rx_fifo, tx_fifo);
/* Exit with lock held, drop it after notifying app */
if (!alloc_fail)
goto alloc_success;
@@ -528,9 +535,10 @@ alloc_check:
return SESSION_ERROR_SEG_CREATE;
}
fifo_segment = segment_manager_get_segment_w_lock (sm, new_fs_index);
- alloc_fail = segment_try_alloc_fifos (fifo_segment, props->rx_fifo_size,
- props->tx_fifo_size, rx_fifo,
- tx_fifo);
+ alloc_fail = segment_manager_try_alloc_fifos (fifo_segment,
+ props->rx_fifo_size,
+ props->tx_fifo_size,
+ rx_fifo, tx_fifo);
added_a_segment = 1;
goto alloc_check;
}
@@ -588,16 +596,13 @@ segment_manager_dealloc_fifos (u32 segment_index, svm_fifo_t * rx_fifo,
* Must be called with lock held
*/
svm_queue_t *
-segment_manager_alloc_queue (segment_manager_t * sm, u32 queue_size)
+segment_manager_alloc_queue (svm_fifo_segment_private_t * segment,
+ u32 queue_size)
{
- svm_fifo_segment_private_t *segment;
ssvm_shared_header_t *sh;
svm_queue_t *q;
void *oldheap;
- ASSERT (!pool_is_free_index (sm->segments, 0));
-
- segment = segment_manager_get_segment (sm, 0);
sh = segment->ssvm.sh;
oldheap = ssvm_push_heap (sh);
diff --git a/src/vnet/session/segment_manager.h b/src/vnet/session/segment_manager.h
index 9b1d4cd0c06..62e5e97e703 100644
--- a/src/vnet/session/segment_manager.h
+++ b/src/vnet/session/segment_manager.h
@@ -27,9 +27,7 @@ typedef struct _segment_manager_properties
/** Session fifo sizes. */
u32 rx_fifo_size;
u32 tx_fifo_size;
-
- /** Preallocated pool sizes */
-// u32 preallocated_fifo_pairs;
+ u32 evt_q_size;
/** Configured additional segment size */
u32 add_segment_size;
@@ -40,8 +38,6 @@ typedef struct _segment_manager_properties
/** Segment type: if set to SSVM_N_TYPES, private segments are used */
ssvm_segment_type_t segment_type;
- /** Use one or more private mheaps, instead of the global heap */
-// u32 private_segment_count;
} segment_manager_properties_t;
typedef struct _segment_manager
@@ -126,7 +122,7 @@ segment_manager_event_queue (segment_manager_t * sm)
segment_manager_t *segment_manager_new ();
int segment_manager_init (segment_manager_t * sm, u32 first_seg_size,
- u32 evt_q_size, u32 prealloc_fifo_pairs);
+ u32 prealloc_fifo_pairs);
svm_fifo_segment_private_t *segment_manager_get_segment (segment_manager_t *
sm,
@@ -134,6 +130,9 @@ svm_fifo_segment_private_t *segment_manager_get_segment (segment_manager_t *
svm_fifo_segment_private_t
* segment_manager_get_segment_w_lock (segment_manager_t * sm,
u32 segment_index);
+int segment_manager_add_segment (segment_manager_t * sm, u32 segment_size);
+void segment_manager_del_segment (segment_manager_t * sm,
+ svm_fifo_segment_private_t * fs);
void segment_manager_segment_reader_unlock (segment_manager_t * sm);
void segment_manager_segment_writer_unlock (segment_manager_t * sm);
@@ -143,15 +142,17 @@ void segment_manager_del_sessions (segment_manager_t * sm);
void segment_manager_del (segment_manager_t * sm);
void segment_manager_init_del (segment_manager_t * sm);
u8 segment_manager_has_fifos (segment_manager_t * sm);
-int
-segment_manager_alloc_session_fifos (segment_manager_t * sm,
- svm_fifo_t ** server_rx_fifo,
- svm_fifo_t ** server_tx_fifo,
- u32 * fifo_segment_index);
-void
-segment_manager_dealloc_fifos (u32 svm_segment_index, svm_fifo_t * rx_fifo,
- svm_fifo_t * tx_fifo);
-svm_queue_t *segment_manager_alloc_queue (segment_manager_t * sm,
+int segment_manager_alloc_session_fifos (segment_manager_t * sm,
+ svm_fifo_t ** server_rx_fifo,
+ svm_fifo_t ** server_tx_fifo,
+ u32 * fifo_segment_index);
+int segment_manager_try_alloc_fifos (svm_fifo_segment_private_t * fs,
+ u32 rx_fifo_size, u32 tx_fifo_size,
+ svm_fifo_t ** rx_fifo,
+ svm_fifo_t ** tx_fifo);
+void segment_manager_dealloc_fifos (u32 segment_index, svm_fifo_t * rx_fifo,
+ svm_fifo_t * tx_fifo);
+svm_queue_t *segment_manager_alloc_queue (svm_fifo_segment_private_t * fs,
u32 queue_size);
void segment_manager_dealloc_queue (segment_manager_t * sm, svm_queue_t * q);
void segment_manager_app_detach (segment_manager_t * sm);
diff --git a/src/vnet/session/session.api b/src/vnet/session/session.api
index 1c3e84b7ea1..a6739fc61bf 100644
--- a/src/vnet/session/session.api
+++ b/src/vnet/session/session.api
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-option version = "1.0.0";
+option version = "1.0.1";
/** \brief client->vpp, attach application to session layer
@param client_index - opaque cookie to identify the sender
@@ -72,6 +72,17 @@ autoreply define map_another_segment {
u8 segment_name[128];
};
+/** \brief vpp->client unmap shared memory segment
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param segment_name -
+*/
+autoreply define unmap_segment {
+ u32 client_index;
+ u32 context;
+ u8 segment_name[128];
+};
+
/** \brief Bind to a given URI
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@@ -122,10 +133,12 @@ autoreply define connect_uri {
@param context - sender context, to match reply w/ request
@param listener_handle - tells client which listener this pertains to
@param handle - unique session identifier
- @param session_thread_index - thread index of new session
@param rx_fifo_address - rx (vpp -> vpp-client) fifo address
@param tx_fifo_address - tx (vpp-client -> vpp) fifo address
- @param vpp_event_queue_address - vpp's event queue address
+ @param vpp_event_queue_address - vpp's event queue address or client's
+ event queue for cut through
+ @param server_event_queue_address - server's event queue address for
+ cut through sessions
@param port - remote port
@param is_ip4 - 1 if the ip is ip4
@param ip - remote ip
@@ -138,6 +151,7 @@ define accept_session {
u64 server_rx_fifo;
u64 server_tx_fifo;
u64 vpp_event_queue_address;
+ u64 server_event_queue_address;
u16 port;
u8 is_ip4;
u8 ip[16];
@@ -176,7 +190,6 @@ define disconnect_session {
@param handle - session handle
*/
define disconnect_session_reply {
- u32 client_index;
u32 context;
i32 retval;
u64 handle;
@@ -302,6 +315,7 @@ define connect_session {
@param server_rx_fifo - rx (vpp -> vpp-client) fifo address
@param server_tx_fifo - tx (vpp-client -> vpp) fifo address
@param vpp_event_queue_address - vpp's event queue address
+ @param client_event_queue_address - client's event queue address
@param segment_size - size of segment to be attached. Only for redirects.
@param segment_name_length - non-zero if the client needs to attach to
the fifo segment
@@ -317,6 +331,7 @@ define connect_session_reply {
u64 server_rx_fifo;
u64 server_tx_fifo;
u64 vpp_event_queue_address;
+ u64 client_event_queue_address;
u32 segment_size;
u8 segment_name_length;
u8 segment_name[128];
diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h
index ec00e291721..108e5fe259a 100644
--- a/src/vnet/session/session.h
+++ b/src/vnet/session/session.h
@@ -87,12 +87,14 @@ typedef struct
void *arg;
} rpc_args_t;
+typedef u64 session_handle_t;
+
/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
union
{
svm_fifo_t * fifo;
- u64 session_handle;
+ session_handle_t session_handle;
rpc_args_t rpc_args;
};
u8 event_type;
@@ -251,38 +253,61 @@ session_get_if_valid (u64 si, u32 thread_index)
return pool_elt_at_index (session_manager_main.sessions[thread_index], si);
}
-always_inline u64
+always_inline session_handle_t
session_handle (stream_session_t * s)
{
return ((u64) s->thread_index << 32) | (u64) s->session_index;
}
always_inline u32
-session_index_from_handle (u64 handle)
+session_index_from_handle (session_handle_t handle)
{
return handle & 0xFFFFFFFF;
}
always_inline u32
-session_thread_from_handle (u64 handle)
+session_thread_from_handle (session_handle_t handle)
{
return handle >> 32;
}
always_inline void
-session_parse_handle (u64 handle, u32 * index, u32 * thread_index)
+session_parse_handle (session_handle_t handle, u32 * index,
+ u32 * thread_index)
{
*index = session_index_from_handle (handle);
*thread_index = session_thread_from_handle (handle);
}
always_inline stream_session_t *
-session_get_from_handle (u64 handle)
+session_get_from_handle (session_handle_t handle)
{
session_manager_main_t *smm = &session_manager_main;
- return
- pool_elt_at_index (smm->sessions[session_thread_from_handle (handle)],
- session_index_from_handle (handle));
+ u32 session_index, thread_index;
+ session_parse_handle (handle, &session_index, &thread_index);
+ return pool_elt_at_index (smm->sessions[thread_index], session_index);
+}
+
+always_inline stream_session_t *
+session_get_from_handle_if_valid (session_handle_t handle)
+{
+ u32 session_index, thread_index;
+ session_parse_handle (handle, &session_index, &thread_index);
+ return session_get_if_valid (session_index, thread_index);
+}
+
+always_inline u8
+session_handle_is_local (session_handle_t handle)
+{
+ if ((handle >> 32) == SESSION_LOCAL_TABLE_PREFIX)
+ return 1;
+ return 0;
+}
+
+always_inline transport_proto_t
+session_type_transport_proto (session_type_t st)
+{
+ return (st >> 1);
}
always_inline transport_proto_t
@@ -291,12 +316,25 @@ session_get_transport_proto (stream_session_t * s)
return (s->session_type >> 1);
}
+always_inline fib_protocol_t
+session_get_fib_proto (stream_session_t * s)
+{
+ u8 is_ip4 = s->session_type & 1;
+ return (is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6);
+}
+
always_inline session_type_t
session_type_from_proto_and_ip (transport_proto_t proto, u8 is_ip4)
{
return (proto << 1 | is_ip4);
}
+always_inline u8
+session_has_transport (stream_session_t * s)
+{
+ return (session_get_transport_proto (s) != TRANSPORT_PROTO_NONE);
+}
+
/**
* Acquires a lock that blocks a session pool from expanding.
*
@@ -470,7 +508,7 @@ listen_session_get_handle (stream_session_t * s)
}
always_inline stream_session_t *
-listen_session_get_from_handle (u64 handle)
+listen_session_get_from_handle (session_handle_t handle)
{
session_manager_main_t *smm = &session_manager_main;
stream_session_t *s;
diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c
index 57af960597d..11fa0faa738 100755
--- a/src/vnet/session/session_api.c
+++ b/src/vnet/session/session_api.c
@@ -111,6 +111,40 @@ send_add_segment_callback (u32 api_client_index, const ssvm_private_t * sp)
}
static int
+send_del_segment_callback (u32 api_client_index, const ssvm_private_t * fs)
+{
+ vl_api_unmap_segment_t *mp;
+ vl_api_registration_t *reg;
+
+ reg = vl_mem_api_client_index_to_registration (api_client_index);
+ if (!reg)
+ {
+ clib_warning ("no registration: %u", api_client_index);
+ return -1;
+ }
+
+ if (ssvm_type (fs) == SSVM_SEGMENT_MEMFD
+ && vl_api_registration_file_index (reg) == VL_API_INVALID_FI)
+ {
+ clib_warning ("can't send memfd fd");
+ return -1;
+ }
+
+ mp = vl_msg_api_alloc_as_if_client (sizeof (*mp));
+ memset (mp, 0, sizeof (*mp));
+ mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_UNMAP_SEGMENT);
+ strncpy ((char *) mp->segment_name, (char *) fs->name,
+ sizeof (mp->segment_name) - 1);
+
+ vl_msg_api_send_shmem (reg->vl_input_queue, (u8 *) & mp);
+
+ if (ssvm_type (fs) == SSVM_SEGMENT_MEMFD)
+ return session_send_memfd_fd (reg, fs);
+
+ return 0;
+}
+
+static int
send_session_accept_callback (stream_session_t * s)
{
application_t *server = application_get (s->app_index);
@@ -121,7 +155,6 @@ send_session_accept_callback (stream_session_t * s)
stream_session_t *listener;
svm_queue_t *vpp_queue;
- vpp_queue = session_manager_get_vpp_event_queue (s->thread_index);
reg = vl_mem_api_client_index_to_registration (server->api_client_index);
if (!reg)
{
@@ -134,32 +167,78 @@ send_session_accept_callback (stream_session_t * s)
mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_ACCEPT_SESSION);
mp->context = server->index;
- listener = listen_session_get (s->session_type, s->listener_index);
- tp_vft = transport_protocol_get_vft (session_get_transport_proto (s));
- tc = tp_vft->get_connection (s->connection_index, s->thread_index);
- mp->listener_handle = listen_session_get_handle (listener);
+ mp->server_rx_fifo = pointer_to_uword (s->server_rx_fifo);
+ mp->server_tx_fifo = pointer_to_uword (s->server_tx_fifo);
- if (application_is_proxy (server))
+ if (session_has_transport (s))
{
- listener =
- application_first_listener (server,
- transport_connection_fib_proto (tc),
- tc->proto);
- if (listener)
- mp->listener_handle = listen_session_get_handle (listener);
+ listener = listen_session_get (s->session_type, s->listener_index);
+ mp->listener_handle = listen_session_get_handle (listener);
+ if (application_is_proxy (server))
+ {
+ listener =
+ application_first_listener (server, session_get_fib_proto (s),
+ session_get_transport_proto (s));
+ if (listener)
+ mp->listener_handle = listen_session_get_handle (listener);
+ }
+ vpp_queue = session_manager_get_vpp_event_queue (s->thread_index);
+ mp->vpp_event_queue_address = pointer_to_uword (vpp_queue);
+ mp->handle = session_handle (s);
+ tp_vft = transport_protocol_get_vft (session_get_transport_proto (s));
+ tc = tp_vft->get_connection (s->connection_index, s->thread_index);
+ mp->port = tc->rmt_port;
+ mp->is_ip4 = tc->is_ip4;
+ clib_memcpy (&mp->ip, &tc->rmt_ip, sizeof (tc->rmt_ip));
+ }
+ else
+ {
+ local_session_t *ls = (local_session_t *) s;
+ local_session_t *ll;
+ if (application_local_session_listener_has_transport (ls))
+ {
+ listener = listen_session_get (ls->listener_session_type,
+ ls->listener_index);
+ mp->listener_handle = listen_session_get_handle (listener);
+ }
+ else
+ {
+ ll = application_get_local_listen_session (server,
+ ls->listener_index);
+ mp->listener_handle = application_local_session_handle (ll);
+ }
+ mp->handle = application_local_session_handle (ls);
+ mp->port = ls->port;
+ mp->vpp_event_queue_address = ls->client_evt_q;
+ mp->server_event_queue_address = ls->server_evt_q;
}
- mp->handle = session_handle (s);
- mp->server_rx_fifo = pointer_to_uword (s->server_rx_fifo);
- mp->server_tx_fifo = pointer_to_uword (s->server_tx_fifo);
- mp->vpp_event_queue_address = pointer_to_uword (vpp_queue);
- mp->port = tc->rmt_port;
- mp->is_ip4 = tc->is_ip4;
- clib_memcpy (&mp->ip, &tc->rmt_ip, sizeof (tc->rmt_ip));
vl_msg_api_send_shmem (reg->vl_input_queue, (u8 *) & mp);
return 0;
}
+void
+send_local_session_disconnect_callback (u32 app_index, local_session_t * ls)
+{
+ application_t *app = application_get (app_index);
+ vl_api_disconnect_session_t *mp;
+ vl_api_registration_t *reg;
+
+ reg = vl_mem_api_client_index_to_registration (app->api_client_index);
+ if (!reg)
+ {
+ clib_warning ("no registration: %u", app->api_client_index);
+ return;
+ }
+
+ mp = vl_mem_api_alloc_as_if_client_w_reg (reg, sizeof (*mp));
+ memset (mp, 0, sizeof (*mp));
+ mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_DISCONNECT_SESSION);
+ mp->handle = application_local_session_handle (ls);
+ mp->context = app->api_client_index;
+ vl_msg_api_send_shmem (reg->vl_input_queue, (u8 *) & mp);
+}
+
static void
send_session_disconnect_callback (stream_session_t * s)
{
@@ -178,6 +257,7 @@ send_session_disconnect_callback (stream_session_t * s)
memset (mp, 0, sizeof (*mp));
mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_DISCONNECT_SESSION);
mp->handle = session_handle (s);
+ mp->context = app->api_client_index;
vl_msg_api_send_shmem (reg->vl_input_queue, (u8 *) & mp);
}
@@ -227,21 +307,34 @@ send_session_connected_callback (u32 app_index, u32 api_context,
if (is_fail)
goto done;
- tc = session_get_transport (s);
- if (!tc)
+ if (session_has_transport (s))
{
- is_fail = 1;
- goto done;
- }
+ tc = session_get_transport (s);
+ if (!tc)
+ {
+ is_fail = 1;
+ goto done;
+ }
- vpp_queue = session_manager_get_vpp_event_queue (s->thread_index);
- mp->server_rx_fifo = pointer_to_uword (s->server_rx_fifo);
- mp->server_tx_fifo = pointer_to_uword (s->server_tx_fifo);
- mp->handle = session_handle (s);
- mp->vpp_event_queue_address = pointer_to_uword (vpp_queue);
- clib_memcpy (mp->lcl_ip, &tc->lcl_ip, sizeof (tc->lcl_ip));
- mp->is_ip4 = tc->is_ip4;
- mp->lcl_port = tc->lcl_port;
+ vpp_queue = session_manager_get_vpp_event_queue (s->thread_index);
+ mp->handle = session_handle (s);
+ mp->vpp_event_queue_address = pointer_to_uword (vpp_queue);
+ clib_memcpy (mp->lcl_ip, &tc->lcl_ip, sizeof (tc->lcl_ip));
+ mp->is_ip4 = tc->is_ip4;
+ mp->lcl_port = tc->lcl_port;
+ mp->server_rx_fifo = pointer_to_uword (s->server_rx_fifo);
+ mp->server_tx_fifo = pointer_to_uword (s->server_tx_fifo);
+ }
+ else
+ {
+ local_session_t *ls = (local_session_t *) s;
+ mp->handle = application_local_session_handle (ls);
+ mp->lcl_port = ls->port;
+ mp->vpp_event_queue_address = ls->server_evt_q;
+ mp->client_event_queue_address = ls->client_evt_q;
+ mp->server_rx_fifo = pointer_to_uword (s->server_tx_fifo);
+ mp->server_tx_fifo = pointer_to_uword (s->server_rx_fifo);
+ }
done:
mp->retval = is_fail ?
@@ -250,87 +343,13 @@ done:
return 0;
}
-/**
- * Redirect a connect_uri message to the indicated server.
- * Only sent if the server has bound the related port with
- * URI_OPTIONS_FLAGS_USE_FIFO
- */
-static int
-redirect_connect_callback (u32 server_api_client_index, void *mp_arg)
-{
- vl_api_connect_sock_t *mp = mp_arg;
- svm_queue_t *server_q, *client_q;
- segment_manager_properties_t *props;
- vlib_main_t *vm = vlib_get_main ();
- f64 timeout = vlib_time_now (vm) + 0.5;
- application_t *app;
- int rv = 0;
-
- server_q = vl_api_client_index_to_input_queue (server_api_client_index);
-
- if (!server_q)
- {
- rv = VNET_API_ERROR_INVALID_VALUE;
- goto out;
- }
-
- client_q = vl_api_client_index_to_input_queue (mp->client_index);
- if (!client_q)
- {
- rv = VNET_API_ERROR_INVALID_VALUE_2;
- goto out;
- }
-
- /* Tell the server the client's API queue address, so it can reply */
- mp->client_queue_address = pointer_to_uword (client_q);
- app = application_lookup (mp->client_index);
- if (!app)
- {
- clib_warning ("no client application");
- return -1;
- }
-
- props = application_segment_manager_properties (app);
- mp->options[APP_OPTIONS_RX_FIFO_SIZE] = props->rx_fifo_size;
- mp->options[APP_OPTIONS_TX_FIFO_SIZE] = props->tx_fifo_size;
-
- /*
- * Bounce message handlers MUST NOT block the data-plane.
- * Spin waiting for the queue lock, but
- */
-
- while (vlib_time_now (vm) < timeout)
- {
- rv = svm_queue_add (server_q, (u8 *) & mp, 1 /*nowait */ );
- switch (rv)
- {
- /* correctly enqueued */
- case 0:
- return VNET_API_ERROR_SESSION_REDIRECT;
-
- /* continue spinning, wait for pthread_mutex_trylock to work */
- case -1:
- continue;
-
- /* queue stuffed, drop the msg */
- case -2:
- rv = VNET_API_ERROR_QUEUE_FULL;
- goto out;
- }
- }
-out:
- /* Dispose of the message */
- vl_msg_api_free (mp);
- return rv;
-}
-
static session_cb_vft_t session_cb_vft = {
.session_accept_callback = send_session_accept_callback,
.session_disconnect_callback = send_session_disconnect_callback,
.session_connected_callback = send_session_connected_callback,
.session_reset_callback = send_session_reset_callback,
.add_segment_callback = send_add_segment_callback,
- .redirect_connect_callback = redirect_connect_callback
+ .del_segment_callback = send_del_segment_callback,
};
static void
@@ -601,7 +620,7 @@ vl_api_disconnect_session_reply_t_handler (vl_api_disconnect_session_reply_t *
}
/* Disconnect has been confirmed. Confirm close to transport */
- app = application_lookup (mp->client_index);
+ app = application_lookup (mp->context);
if (app)
{
a->handle = mp->handle;
@@ -644,9 +663,9 @@ vl_api_reset_session_reply_t_handler (vl_api_reset_session_reply_t * mp)
static void
vl_api_accept_session_reply_t_handler (vl_api_accept_session_reply_t * mp)
{
+ vnet_disconnect_args_t _a = { 0 }, *a = &_a;
+ local_session_t *ls;
stream_session_t *s;
- u32 session_index, thread_index;
- vnet_disconnect_args_t _a, *a = &_a;
/* Server isn't interested, kill the session */
if (mp->retval)
@@ -654,11 +673,25 @@ vl_api_accept_session_reply_t_handler (vl_api_accept_session_reply_t * mp)
a->app_index = mp->context;
a->handle = mp->handle;
vnet_disconnect_session (a);
+ return;
+ }
+
+ if (session_handle_is_local (mp->handle))
+ {
+ ls = application_get_local_session_from_handle (mp->handle);
+ if (!ls || ls->app_index != mp->context)
+ {
+ clib_warning ("server %u doesn't own local handle %llu",
+ mp->context, mp->handle);
+ return;
+ }
+ if (application_local_session_connect_notify (ls))
+ return;
+ ls->session_state = SESSION_STATE_READY;
}
else
{
- session_parse_handle (mp->handle, &session_index, &thread_index);
- s = session_get_if_valid (session_index, thread_index);
+ s = session_get_from_handle_if_valid (mp->handle);
if (!s)
{
clib_warning ("session doesn't exist");
diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c
index 77f6f4be78d..9ce0b1a22eb 100644
--- a/src/vnet/session/session_lookup.c
+++ b/src/vnet/session/session_lookup.c
@@ -388,17 +388,18 @@ session_lookup_action_index_is_valid (u32 action_index)
return 1;
}
-static u32
-session_lookup_action_to_app_index (u32 action_index)
+static u64
+session_lookup_action_to_handle (u32 action_index)
{
switch (action_index)
{
case SESSION_RULES_TABLE_ACTION_DROP:
- return APP_DROP_INDEX;
+ return SESSION_DROP_HANDLE;
case SESSION_RULES_TABLE_ACTION_ALLOW:
case SESSION_RULES_TABLE_INVALID_INDEX:
- return APP_INVALID_INDEX;
+ return SESSION_INVALID_HANDLE;
default:
+ /* application index */
return action_index;
}
}
@@ -420,12 +421,13 @@ session_lookup_action_to_session (u32 action_index, u8 fib_proto,
u8 transport_proto)
{
u32 app_index;
- app_index = session_lookup_action_to_app_index (action_index);
+ app_index = session_lookup_action_to_handle (action_index);
/* Nothing sophisticated for now, action index is app index */
return session_lookup_app_listen_session (app_index, fib_proto,
transport_proto);
}
+/** UNUSED */
stream_session_t *
session_lookup_rules_table_session4 (session_table_t * st, u8 proto,
ip4_address_t * lcl, u16 lcl_port,
@@ -435,12 +437,13 @@ session_lookup_rules_table_session4 (session_table_t * st, u8 proto,
u32 action_index, app_index;
action_index = session_rules_table_lookup4 (srt, lcl, rmt, lcl_port,
rmt_port);
- app_index = session_lookup_action_to_app_index (action_index);
+ app_index = session_lookup_action_to_handle (action_index);
/* Nothing sophisticated for now, action index is app index */
return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP4,
proto);
}
+/** UNUSED */
stream_session_t *
session_lookup_rules_table_session6 (session_table_t * st, u8 proto,
ip6_address_t * lcl, u16 lcl_port,
@@ -450,7 +453,7 @@ session_lookup_rules_table_session6 (session_table_t * st, u8 proto,
u32 action_index, app_index;
action_index = session_rules_table_lookup6 (srt, lcl, rmt, lcl_port,
rmt_port);
- app_index = session_lookup_action_to_app_index (action_index);
+ app_index = session_lookup_action_to_handle (action_index);
return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP6,
proto);
}
@@ -463,7 +466,7 @@ session_lookup_rules_table_session6 (session_table_t * st, u8 proto,
* @param use_rules flag that indicates if the session rules of the table
* should be used
* @return invalid handle if nothing is found, the handle of a valid listener
- * or an action_index if a rule is hit
+ * or an action derived handle if a rule is hit
*/
u64
session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep,
@@ -494,7 +497,7 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep,
ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0,
sep->port);
if (session_lookup_action_index_is_valid (ai))
- return session_lookup_action_to_app_index (ai);
+ return session_lookup_action_to_handle (ai);
}
}
else
@@ -515,7 +518,7 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep,
ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0,
sep->port);
if (session_lookup_action_index_is_valid (ai))
- return session_lookup_action_to_app_index (ai);
+ return session_lookup_action_to_handle (ai);
}
}
return SESSION_INVALID_HANDLE;
@@ -535,9 +538,9 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep,
*
* @param table_index table where the lookup should be done
* @param sep session endpoint to be looked up
- * @return index that can be interpreted as an app index or drop action.
+ * @return session handle that can be interpreted as an adjacency
*/
-u32
+u64
session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep)
{
session_rules_table_t *srt;
@@ -563,7 +566,7 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep)
ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0,
sep->port);
if (session_lookup_action_index_is_valid (ai))
- return session_lookup_action_to_app_index (ai);
+ return session_lookup_action_to_handle (ai);
/*
* Check if session endpoint is a listener
@@ -572,7 +575,7 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep)
sep->transport_proto);
rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
if (rv == 0)
- return (u32) kv4.value;
+ return kv4.value;
/*
* Zero out the ip. Logic is that connect to local ips, say
@@ -581,7 +584,7 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep)
kv4.key[0] = 0;
rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
if (rv == 0)
- return (u32) kv4.value;
+ return kv4.value;
/*
* Zero out the port and check if we have proxy
@@ -589,7 +592,7 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep)
kv4.key[1] = 0;
rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
if (rv == 0)
- return (u32) kv4.value;
+ return kv4.value;
}
else
{
@@ -601,13 +604,13 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep)
ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0,
sep->port);
if (session_lookup_action_index_is_valid (ai))
- return session_lookup_action_to_app_index (ai);
+ return session_lookup_action_to_handle (ai);
make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
sep->transport_proto);
rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
if (rv == 0)
- return (u32) kv6.value;
+ return kv6.value;
/*
* Zero out the ip. Same logic as above.
@@ -615,7 +618,7 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep)
kv6.key[0] = kv6.key[1] = 0;
rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
if (rv == 0)
- return (u32) kv6.value;
+ return kv6.value;
/*
* Zero out the port. Same logic as above.
@@ -623,9 +626,9 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep)
kv6.key[4] = kv6.key[5] = 0;
rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
if (rv == 0)
- return (u32) kv6.value;
+ return kv6.value;
}
- return APP_INVALID_INDEX;
+ return SESSION_INVALID_HANDLE;
}
static stream_session_t *
@@ -1234,37 +1237,6 @@ session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt,
return 0;
}
-u64
-session_lookup_local_listener_make_handle (session_endpoint_t * sep)
-{
- return ((u64) SESSION_LOCAL_TABLE_PREFIX << 32
- | (u32) sep->port << 16 | (u32) sep->transport_proto << 8
- | (u32) sep->is_ip4);
-}
-
-u8
-session_lookup_local_is_handle (u64 handle)
-{
- if (handle >> 32 == SESSION_LOCAL_TABLE_PREFIX)
- return 1;
- return 0;
-}
-
-int
-session_lookup_local_listener_parse_handle (u64 handle,
- session_endpoint_t * sep)
-{
- u32 local_table_handle;
- if (handle >> 32 != SESSION_LOCAL_TABLE_PREFIX)
- return -1;
- local_table_handle = handle & 0xFFFFFFFFULL;
- sep->is_ip4 = local_table_handle & 0xff;
- local_table_handle >>= 8;
- sep->transport_proto = local_table_handle & 0xff;
- sep->port = local_table_handle >> 8;
- return 0;
-}
-
clib_error_t *
vnet_session_rule_add_del (session_rule_add_del_args_t * args)
{
diff --git a/src/vnet/session/session_lookup.h b/src/vnet/session/session_lookup.h
index 1bdf6d17fcb..1acf923831d 100644
--- a/src/vnet/session/session_lookup.h
+++ b/src/vnet/session/session_lookup.h
@@ -64,7 +64,7 @@ int session_lookup_del_connection (transport_connection_t * tc);
u64 session_lookup_endpoint_listener (u32 table_index,
session_endpoint_t * sepi,
u8 use_rules);
-u32 session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep);
+u64 session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep);
stream_session_t *session_lookup_global_session_endpoint (session_endpoint_t
*);
int session_lookup_add_session_endpoint (u32 table_index,
@@ -80,11 +80,6 @@ transport_connection_t *session_lookup_half_open_connection (u64 handle,
u8 is_ip4);
u32 session_lookup_get_index_for_fib (u32 fib_proto, u32 fib_index);
-u64 session_lookup_local_listener_make_handle (session_endpoint_t * sep);
-u8 session_lookup_local_is_handle (u64 handle);
-int session_lookup_local_listener_parse_handle (u64 handle,
- session_endpoint_t * sep);
-
void session_lookup_show_table_entries (vlib_main_t * vm,
session_table_t * table, u8 type,
u8 is_local);
diff --git a/src/vnet/session/session_table.h b/src/vnet/session/session_table.h
index 636ee44a2fe..31b1f647e23 100644
--- a/src/vnet/session/session_table.h
+++ b/src/vnet/session/session_table.h
@@ -55,6 +55,7 @@ typedef struct _session_lookup_table
#define SESSION_LOCAL_TABLE_PREFIX ((u32)~0)
#define SESSION_INVALID_INDEX ((u32)~0)
#define SESSION_INVALID_HANDLE ((u64)~0)
+#define SESSION_DROP_HANDLE (((u64)~0) - 1)
typedef int (*ip4_session_table_walk_fn_t) (clib_bihash_kv_16_8_t * kvp,
void *ctx);
diff --git a/src/vnet/session/session_test.c b/src/vnet/session/session_test.c
index febe1b7998a..85e8732ddab 100644
--- a/src/vnet/session/session_test.c
+++ b/src/vnet/session/session_test.c
@@ -53,12 +53,20 @@ dummy_session_connected_callback (u32 app_index, u32 api_context,
return -1;
}
+static u32 dummy_segment_count;
+
int
-dummy_add_segment_callback (u32 client_index, const u8 * seg_name,
- u32 seg_size)
+dummy_add_segment_callback (u32 client_index, const ssvm_private_t * fs)
{
- clib_warning ("called...");
- return -1;
+ dummy_segment_count = 1;
+ return 0;
+}
+
+int
+dummy_del_segment_callback (u32 client_index, const ssvm_private_t * fs)
+{
+ dummy_segment_count = 0;
+ return 0;
}
int
@@ -73,11 +81,14 @@ dummy_session_disconnect_callback (stream_session_t * s)
clib_warning ("called...");
}
+static u32 dummy_accept;
+
int
dummy_session_accept_callback (stream_session_t * s)
{
- clib_warning ("called...");
- return -1;
+ dummy_accept = 1;
+ s->session_state = SESSION_STATE_READY;
+ return 0;
}
int
@@ -94,7 +105,8 @@ static session_cb_vft_t dummy_session_cbs = {
.session_accept_callback = dummy_session_accept_callback,
.session_disconnect_callback = dummy_session_disconnect_callback,
.builtin_server_rx_callback = dummy_server_rx_callback,
- .redirect_connect_callback = dummy_redirect_connect_callback,
+ .add_segment_callback = dummy_add_segment_callback,
+ .del_segment_callback = dummy_del_segment_callback,
};
/* *INDENT-ON* */
@@ -146,7 +158,6 @@ session_test_basic (vlib_main_t * vm, unformat_input_t * input)
memset (options, 0, sizeof (options));
options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
- options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
vnet_app_attach_args_t attach_args = {
@@ -205,7 +216,7 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
{
u64 options[APP_OPTIONS_N_OPTIONS], dummy_secret = 1234;
u32 server_index, server_st_index, server_local_st_index;
- u32 dummy_port = 1234, local_listener, client_index;
+ u32 dummy_port = 1234, client_index;
u32 dummy_api_context = 4321, dummy_client_api_index = 1234;
u32 dummy_server_api_index = ~0, sw_if_index = 0;
session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
@@ -216,6 +227,7 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
app_namespace_t *app_ns;
application_t *server;
stream_session_t *s;
+ u64 handle;
int code;
server_sep.is_ip4 = 1;
@@ -225,7 +237,6 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
memset (options, 0, sizeof (options));
options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
- options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
vnet_app_attach_args_t attach_args = {
.api_client_index = ~0,
.options = options,
@@ -361,9 +372,8 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
SESSION_TEST ((s->app_index == server_index), "app_index should be that of "
"the server");
server_local_st_index = application_local_session_table (server);
- local_listener =
- session_lookup_local_endpoint (server_local_st_index, &server_sep);
- SESSION_TEST ((local_listener != SESSION_INVALID_INDEX),
+ handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
+ SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
"listener should exist in local table");
/*
@@ -381,12 +391,15 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
code = clib_error_get_code (error);
SESSION_TEST ((code == 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 return error code");
+ SESSION_TEST ((error == 0), "client connect should not return error code");
code = clib_error_get_code (error);
- SESSION_TEST ((code == VNET_API_ERROR_SESSION_REDIRECT),
- "error code should be redirect");
+ SESSION_TEST ((dummy_segment_count == 1),
+ "should've received request to map new segment");
+ SESSION_TEST ((dummy_accept == 1), "should've received accept request");
detach_args.app_index = client_index;
vnet_application_detach (&detach_args);
@@ -413,9 +426,9 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
s = session_lookup_listener (server_st_index, &server_sep);
SESSION_TEST ((s == 0), "listener should not exist in global table");
- local_listener =
- session_lookup_local_endpoint (server_local_st_index, &server_sep);
- SESSION_TEST ((s == 0), "listener should not exist in local table");
+ handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
+ SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
+ "listener should not exist in local table");
detach_args.app_index = server_index;
vnet_application_detach (&detach_args);
@@ -438,18 +451,16 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
s = session_lookup_listener (server_st_index, &server_sep);
SESSION_TEST ((s == 0), "listener should not exist in global table");
server_local_st_index = application_local_session_table (server);
- local_listener =
- session_lookup_local_endpoint (server_local_st_index, &server_sep);
- SESSION_TEST ((local_listener != SESSION_INVALID_INDEX),
+ handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
+ SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
"listener should exist in local table");
unbind_args.handle = bind_args.handle;
error = vnet_unbind (&unbind_args);
SESSION_TEST ((error == 0), "unbind should work");
- local_listener =
- session_lookup_local_endpoint (server_local_st_index, &server_sep);
- SESSION_TEST ((local_listener == SESSION_INVALID_INDEX),
+ handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
+ SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
"listener should not exist in local table");
/*
@@ -510,9 +521,8 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
SESSION_TEST ((s->app_index == server_index), "app_index should be that of "
"the server");
server_local_st_index = application_local_session_table (server);
- local_listener =
- session_lookup_local_endpoint (server_local_st_index, &server_sep);
- SESSION_TEST ((local_listener != SESSION_INVALID_INDEX),
+ handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
+ SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
"zero listener should exist in local table");
detach_args.app_index = server_index;
vnet_application_detach (&detach_args);
@@ -800,7 +810,7 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
u64 options[APP_OPTIONS_N_OPTIONS];
u16 lcl_port = 1234, rmt_port = 4321;
- u32 server_index, server_index2, app_index;
+ u32 server_index, server_index2;
u32 dummy_server_api_index = ~0;
transport_connection_t *tc;
u32 dummy_port = 1111;
@@ -811,6 +821,7 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
u32 local_ns_index = default_ns->local_table_index;
int verbose = 0, rv;
app_namespace_t *app_ns;
+ u64 handle;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
@@ -844,7 +855,6 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
* Attach server with global and local default scope
*/
options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
- options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
attach_args.namespace_id = 0;
@@ -918,8 +928,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
.port = rmt_port,
.transport_proto = TRANSPORT_PROTO_TCP,
};
- app_index = session_lookup_local_endpoint (local_ns_index, &sep);
- SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
+ handle = session_lookup_local_endpoint (local_ns_index, &sep);
+ SESSION_TEST ((handle != server_index), "local session endpoint lookup "
"should not work (global scope)");
tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
@@ -943,8 +953,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
&is_filtered);
SESSION_TEST ((tc->c_index == listener->connection_index),
"optimized lookup for lcl port + 1 should work");
- app_index = session_lookup_local_endpoint (local_ns_index, &sep);
- SESSION_TEST ((app_index == server_index), "local session endpoint lookup "
+ handle = session_lookup_local_endpoint (local_ns_index, &sep);
+ SESSION_TEST ((handle == server_index), "local session endpoint lookup "
"should work (lcl ip was zeroed)");
/*
@@ -976,8 +986,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
"should fail (deny rule)");
SESSION_TEST ((is_filtered == 1), "lookup should be filtered (deny)");
- app_index = session_lookup_local_endpoint (local_ns_index, &sep);
- SESSION_TEST ((app_index == APP_DROP_INDEX), "lookup for 1.2.3.4/32 1234 "
+ handle = session_lookup_local_endpoint (local_ns_index, &sep);
+ SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
"5.6.7.8/16 4321 in local table should return deny");
tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
@@ -1011,9 +1021,9 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
"should fail (allow without app)");
SESSION_TEST ((is_filtered == 0), "lookup should NOT be filtered");
- app_index = session_lookup_local_endpoint (local_ns_index, &sep);
- SESSION_TEST ((app_index == APP_INVALID_INDEX), "lookup for 1.2.3.4/32 1234"
- " 5.6.7.8/32 4321 in local table should return invalid");
+ handle = session_lookup_local_endpoint (local_ns_index, &sep);
+ SESSION_TEST ((handle == SESSION_INVALID_HANDLE), "lookup for 1.2.3.4/32 "
+ "1234 5.6.7.8/32 4321 in local table should return invalid");
if (verbose)
{
@@ -1023,8 +1033,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
}
sep.ip.ip4.as_u32 += 1 << 24;
- app_index = session_lookup_local_endpoint (local_ns_index, &sep);
- SESSION_TEST ((app_index == APP_DROP_INDEX), "lookup for 1.2.3.4/32 1234"
+ handle = session_lookup_local_endpoint (local_ns_index, &sep);
+ SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234"
" 5.6.7.9/32 4321 in local table should return deny");
vnet_connect_args_t connect_args = {
@@ -1075,8 +1085,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
TRANSPORT_PROTO_TCP);
}
- app_index = session_lookup_local_endpoint (local_ns_index, &sep);
- SESSION_TEST ((app_index == APP_DROP_INDEX),
+ handle = session_lookup_local_endpoint (local_ns_index, &sep);
+ SESSION_TEST ((handle == SESSION_DROP_HANDLE),
"local session endpoint lookup should return deny");
/*
@@ -1091,8 +1101,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
error = vnet_session_rule_add_del (&args);
SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
- app_index = session_lookup_local_endpoint (local_ns_index, &sep);
- SESSION_TEST ((app_index == APP_INVALID_INDEX),
+ handle = session_lookup_local_endpoint (local_ns_index, &sep);
+ SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
"local session endpoint lookup should return invalid");
/*
@@ -1108,8 +1118,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
args.table_args.rmt_port = 4321;
error = vnet_session_rule_add_del (&args);
SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
- app_index = session_lookup_local_endpoint (local_ns_index, &sep);
- SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
+ handle = session_lookup_local_endpoint (local_ns_index, &sep);
+ SESSION_TEST ((handle != server_index), "local session endpoint lookup "
"should not work (removed)");
args.table_args.is_add = 0;
@@ -1296,14 +1306,14 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
/*
* Lookup default namespace
*/
- app_index = session_lookup_local_endpoint (local_ns_index, &sep);
- SESSION_TEST ((app_index == APP_INVALID_INDEX),
+ handle = session_lookup_local_endpoint (local_ns_index, &sep);
+ SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
"lookup for 1.2.3.4/32 1234 5.6.7.8/32 4321 in local table "
"should return allow (invalid)");
sep.port += 1;
- app_index = session_lookup_local_endpoint (local_ns_index, &sep);
- SESSION_TEST ((app_index == APP_DROP_INDEX), "lookup for 1.2.3.4/32 1234 "
+ handle = session_lookup_local_endpoint (local_ns_index, &sep);
+ SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
"5.6.7.8/16 432*2* in local table should return deny");
connect_args.app_index = server_index;
@@ -1317,8 +1327,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
/*
* Lookup test namespace
*/
- app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
- SESSION_TEST ((app_index == APP_DROP_INDEX), "lookup for 1.2.3.4/32 1234 "
+ handle = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
+ SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
"5.6.7.8/16 4321 in local table should return deny");
connect_args.app_index = server_index;
diff --git a/src/vnet/session/stream_session.h b/src/vnet/session/stream_session.h
index b484efefa01..57d256cdbc6 100644
--- a/src/vnet/session/stream_session.h
+++ b/src/vnet/session/stream_session.h
@@ -36,6 +36,26 @@ typedef enum
SESSION_STATE_N_STATES,
} stream_session_state_t;
+/* TODO convert to macro once cleanup completed */
+typedef struct app_session_
+{
+ /** fifo pointers. Once allocated, these do not move */
+ svm_fifo_t *server_rx_fifo;
+ svm_fifo_t *server_tx_fifo;
+
+ /** Type */
+ session_type_t session_type;
+
+ /** State */
+ volatile u8 session_state;
+
+ /** Session index in owning pool */
+ u32 session_index;
+
+ /** Application index */
+ u32 app_index;
+} app_session_t;
+
typedef struct _stream_session_t
{
/** fifo pointers. Once allocated, these do not move */
@@ -48,6 +68,12 @@ typedef struct _stream_session_t
/** State */
volatile u8 session_state;
+ /** Session index in per_thread pool */
+ u32 session_index;
+
+ /** stream server pool index */
+ u32 app_index;
+
u8 thread_index;
/** To avoid n**2 "one event per frame" check */
@@ -56,21 +82,56 @@ typedef struct _stream_session_t
/** svm segment index where fifos were allocated */
u32 svm_segment_index;
- /** Session index in per_thread pool */
- u32 session_index;
-
/** Transport specific */
u32 connection_index;
- /** stream server pool index */
- u32 app_index;
-
/** Parent listener session if the result of an accept */
u32 listener_index;
CLIB_CACHE_LINE_ALIGN_MARK (pad);
} stream_session_t;
+typedef struct local_session_
+{
+ /** fifo pointers. Once allocated, these do not move */
+ svm_fifo_t *server_rx_fifo;
+ svm_fifo_t *server_tx_fifo;
+
+ /** Type */
+ session_type_t session_type;
+
+ /** State */
+ volatile u8 session_state;
+
+ /** Session index */
+ u32 session_index;
+
+ /** Server index */
+ u32 app_index;
+
+ /** Segment index where fifos were allocated */
+ u32 svm_segment_index;
+
+ u32 listener_index;
+
+ /** Port for connection */
+ u16 port;
+
+ /** Has transport embedded when listener not purely local */
+ session_type_t listener_session_type;
+
+ /**
+ * Client data
+ */
+ u32 client_index;
+ u32 client_opaque;
+
+ u64 server_evt_q;
+ u64 client_evt_q;
+
+ CLIB_CACHE_LINE_ALIGN_MARK (pad);
+} local_session_t;
+
typedef struct _session_endpoint
{
/*
diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h
index 12b6a0551d8..76ee2262ecd 100644
--- a/src/vnet/session/transport.h
+++ b/src/vnet/session/transport.h
@@ -71,6 +71,7 @@ typedef enum _transport_proto
TRANSPORT_PROTO_TCP,
TRANSPORT_PROTO_UDP,
TRANSPORT_PROTO_SCTP,
+ TRANSPORT_PROTO_NONE,
TRANSPORT_N_PROTO
} transport_proto_t;
diff --git a/test/test_session.py b/test/test_session.py
index 80e27c0a0e7..047b8ca553a 100644
--- a/test/test_session.py
+++ b/test/test_session.py
@@ -85,6 +85,9 @@ class TestSession(VppTestCase):
self.logger.critical(error)
self.assertEqual(error.find("failed"), -1)
+ if self.vpp_dead:
+ self.assert_equal(0)
+
# Delete inter-table routes
ip_t01.remove_vpp_config()
ip_t10.remove_vpp_config()