session: add support for memfd segments
- update segment manager and session api to work with both flavors of
ssvm segments
- added generic ssvm slave/master init and del functions
- cleanup/refactor tcp_echo
- fixed uses of svm fifo pool as vector
Change-Id: Ieee8b163faa407da6e77e657a2322de213a9d2a0
Signed-off-by: Florin Coras <fcoras@cisco.com>
diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c
index 8090e75..13ccdd7 100644
--- a/src/vnet/session/application.c
+++ b/src/vnet/session/application.c
@@ -227,18 +227,56 @@
clib_warning ("No session reset callback function provided");
}
+/**
+ * Check app config for given segment type
+ *
+ * Returns 1 on success and 0 otherwise
+ */
+static u8
+application_verify_cfg (ssvm_segment_type_t st)
+{
+ u8 is_valid;
+ if (st == SSVM_SEGMENT_MEMFD)
+ {
+ is_valid = (session_manager_get_evt_q_segment () != 0);
+ if (!is_valid)
+ clib_warning ("memfd seg: vpp's event qs IN binary api svm region");
+ return is_valid;
+ }
+ else if (st == SSVM_SEGMENT_SHM)
+ {
+ is_valid = (session_manager_get_evt_q_segment () == 0);
+ if (!is_valid)
+ clib_warning ("shm seg: vpp's event qs NOT IN binary api svm region");
+ return is_valid;
+ }
+ else
+ return 1;
+}
+
int
application_init (application_t * app, u32 api_client_index, u64 * options,
session_cb_vft_t * cb_fns)
{
- segment_manager_t *sm;
- segment_manager_properties_t *props;
+ ssvm_segment_type_t st = SSVM_SEGMENT_MEMFD;
u32 app_evt_queue_size, first_seg_size;
- u32 default_rx_fifo_size = 16 << 10, default_tx_fifo_size = 16 << 10;
+ segment_manager_properties_t *props;
+ vl_api_registration_t *reg;
+ segment_manager_t *sm;
int rv;
- app_evt_queue_size = options[APP_OPTIONS_EVT_QUEUE_SIZE] > 0 ?
- options[APP_OPTIONS_EVT_QUEUE_SIZE] : default_app_evt_queue_size;
+ /*
+ * Make sure we support the requested configuration
+ */
+ reg = vl_api_client_index_to_registration (api_client_index);
+ if (!reg)
+ return VNET_API_ERROR_APP_UNSUPPORTED_CFG;
+
+ if (vl_api_registration_file_index (reg) == ~0)
+ st = SSVM_SEGMENT_SHM;
+
+ if (!application_verify_cfg (st))
+ return VNET_API_ERROR_APP_UNSUPPORTED_CFG;
/*
* Setup segment manager
@@ -247,21 +285,27 @@
sm->app_index = app->index;
props = segment_manager_properties_alloc ();
app->sm_properties = segment_manager_properties_index (props);
- props->add_segment_size = options[APP_OPTIONS_ADD_SEGMENT_SIZE];
- props->rx_fifo_size = options[APP_OPTIONS_RX_FIFO_SIZE];
- props->rx_fifo_size =
- props->rx_fifo_size ? props->rx_fifo_size : default_rx_fifo_size;
- props->tx_fifo_size = options[APP_OPTIONS_TX_FIFO_SIZE];
- props->tx_fifo_size =
- props->tx_fifo_size ? props->tx_fifo_size : default_tx_fifo_size;
- props->add_segment = props->add_segment_size != 0;
+ if (options[APP_OPTIONS_ADD_SEGMENT_SIZE])
+ {
+ props->add_segment_size = options[APP_OPTIONS_ADD_SEGMENT_SIZE];
+ props->add_segment = 1;
+ }
+ if (options[APP_OPTIONS_RX_FIFO_SIZE])
+ 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];
props->preallocated_fifo_pairs = options[APP_OPTIONS_PREALLOC_FIFO_PAIRS];
- props->use_private_segment = options[APP_OPTIONS_FLAGS]
- & APP_OPTIONS_FLAGS_IS_BUILTIN;
props->private_segment_count = options[APP_OPTIONS_PRIVATE_SEGMENT_COUNT];
+ if (options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_IS_BUILTIN)
+ props->segment_type = SSVM_N_SEGMENT_TYPES;
+ else
+ props->segment_type = st;
+ 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];
- if ((rv = segment_manager_init (sm, app->sm_properties, first_seg_size)))
+ if ((rv = segment_manager_init (sm, app->sm_properties, first_seg_size,
+ app_evt_queue_size)))
return rv;
sm->first_is_protected = 1;
@@ -478,15 +522,13 @@
application_add_segment_notify (u32 app_index, u32 fifo_segment_index)
{
application_t *app = application_get (app_index);
- u32 seg_size = 0;
- u8 *seg_name;
+ svm_fifo_segment_private_t *fs;
/* Send an API message to the external app, to map new segment */
ASSERT (app->cb_fns.add_segment_callback);
- segment_manager_get_segment_info (fifo_segment_index, &seg_name, &seg_size);
- return app->cb_fns.add_segment_callback (app->api_client_index, seg_name,
- seg_size);
+ fs = segment_manager_get_segment (fifo_segment_index);
+ return app->cb_fns.add_segment_callback (app->api_client_index, &fs->ssvm);
}
u8
diff --git a/src/vnet/session/application.h b/src/vnet/session/application.h
index fd6454f..afe738f 100644
--- a/src/vnet/session/application.h
+++ b/src/vnet/session/application.h
@@ -30,8 +30,8 @@
typedef struct _stream_session_cb_vft
{
/** Notify server of new segment */
- int (*add_segment_callback) (u32 api_client_index, const u8 * seg_name,
- u32 seg_size);
+ int (*add_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);
diff --git a/src/vnet/session/application_interface.c b/src/vnet/session/application_interface.c
index ec31789..f2a13be 100644
--- a/src/vnet/session/application_interface.c
+++ b/src/vnet/session/application_interface.c
@@ -413,11 +413,11 @@
clib_error_t *
vnet_application_attach (vnet_app_attach_args_t * a)
{
+ svm_fifo_segment_private_t *fs;
application_t *app = 0;
segment_manager_t *sm;
- u8 *seg_name;
- u64 secret;
u32 app_ns_index = 0;
+ u64 secret;
int rv;
app = application_lookup (a->api_client_index);
@@ -437,16 +437,15 @@
a->app_event_queue_address = pointer_to_uword (app->event_queue);
sm = segment_manager_get (app->first_segment_manager);
- segment_manager_get_segment_info (sm->segment_indices[0],
- &seg_name, &a->segment_size);
+ fs = segment_manager_get_segment (sm->segment_indices[0]);
if (application_is_proxy (app))
application_setup_proxy (app);
- a->segment_name_length = vec_len (seg_name);
- a->segment_name = seg_name;
- ASSERT (vec_len (a->segment_name) <= 128);
+ ASSERT (vec_len (fs->ssvm.name) <= 128);
+ a->segment = &fs->ssvm;
a->app_index = app->index;
+
return 0;
}
diff --git a/src/vnet/session/application_interface.h b/src/vnet/session/application_interface.h
index 68973a9..8db318f 100644
--- a/src/vnet/session/application_interface.h
+++ b/src/vnet/session/application_interface.h
@@ -39,9 +39,7 @@
/*
* Results
*/
- u8 *segment_name;
- u32 segment_name_length;
- u32 segment_size;
+ ssvm_private_t *segment;
u64 app_event_queue_address;
u32 app_index;
} vnet_app_attach_args_t;
diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c
index dc3e4c9..c3a794b 100644
--- a/src/vnet/session/segment_manager.c
+++ b/src/vnet/session/segment_manager.c
@@ -49,6 +49,9 @@
segment_manager_properties_t *props;
pool_get (segment_manager_properties_pool, props);
memset (props, 0, sizeof (*props));
+ props->add_segment_size = default_segment_size;
+ props->rx_fifo_size = default_fifo_size;
+ props->tx_fifo_size = default_fifo_size;
return props;
}
@@ -73,53 +76,64 @@
return p - segment_manager_properties_pool;
}
+svm_fifo_segment_private_t *
+segment_manager_get_segment (u32 segment_index)
+{
+ return svm_fifo_segment_get_segment (segment_index);
+}
+
void
segment_manager_get_segment_info (u32 index, u8 ** name, u32 * size)
{
svm_fifo_segment_private_t *s;
s = svm_fifo_segment_get_segment (index);
- *name = s->h->segment_name;
+ *name = s->ssvm.name;
*size = s->ssvm.ssvm_size;
}
always_inline int
-session_manager_add_segment_i (segment_manager_t * sm, u32 segment_size,
- u8 * segment_name)
+segment_manager_add_segment_i (segment_manager_t * sm, u32 segment_size,
+ u32 protected_space)
{
- svm_fifo_segment_create_args_t _ca, *ca = &_ca;
+ svm_fifo_segment_create_args_t _ca = { 0 }, *ca = &_ca;
segment_manager_properties_t *props;
- int rv;
- memset (ca, 0, sizeof (*ca));
props = segment_manager_properties_get (sm->properties_index);
- if (!props->use_private_segment)
- {
- ca->segment_name = (char *) segment_name;
- ca->segment_size = segment_size;
- ca->rx_fifo_size = props->rx_fifo_size;
- ca->tx_fifo_size = props->tx_fifo_size;
- ca->preallocated_fifo_pairs = props->preallocated_fifo_pairs;
- rv = svm_fifo_segment_create (ca);
- if (rv)
+ /* Not configured for addition of new segments and not first */
+ if (!props->add_segment && !segment_size)
+ {
+ clib_warning ("cannot allocate new segment");
+ return VNET_API_ERROR_INVALID_VALUE;
+ }
+
+ ca->segment_size = segment_size ? segment_size : props->add_segment_size;
+ ca->rx_fifo_size = props->rx_fifo_size;
+ ca->tx_fifo_size = props->tx_fifo_size;
+ ca->preallocated_fifo_pairs = props->preallocated_fifo_pairs;
+ ca->seg_protected_space = protected_space ? protected_space : 0;
+
+ if (props->segment_type != SSVM_N_SEGMENT_TYPES)
+ {
+ ca->segment_name = (char *) format (0, "%d-%d%c", getpid (),
+ segment_name_counter++, 0);
+ ca->segment_type = props->segment_type;
+ if (svm_fifo_segment_create (ca))
{
clib_warning ("svm_fifo_segment_create ('%s', %d) failed",
ca->segment_name, ca->segment_size);
return VNET_API_ERROR_SVM_SEGMENT_CREATE_FAIL;
}
+ vec_free (ca->segment_name);
}
else
{
- u32 rx_fifo_size, tx_fifo_size, rx_rounded_data_size,
- tx_rounded_data_size;
+ u32 rx_fifo_size, tx_fifo_size;
+ u32 rx_rounded_data_size, tx_rounded_data_size;
u32 approx_segment_count;
u64 approx_total_size;
ca->segment_name = "process-private-segment";
- ca->segment_size = segment_size;
- ca->rx_fifo_size = props->rx_fifo_size;
- ca->tx_fifo_size = props->tx_fifo_size;
- ca->preallocated_fifo_pairs = props->preallocated_fifo_pairs;
ca->private_segment_count = props->private_segment_count;
/* Calculate space requirements */
@@ -131,61 +145,44 @@
approx_total_size = (u64) ca->preallocated_fifo_pairs
* (rx_fifo_size + tx_fifo_size);
- approx_segment_count = (approx_total_size + (ca->segment_size - 1))
- / (u64) ca->segment_size;
+ approx_segment_count = (approx_total_size + protected_space
+ + (ca->segment_size -
+ 1)) / (u64) ca->segment_size;
/* The user asked us to figure it out... */
- if (ca->private_segment_count == 0)
+ if (ca->private_segment_count == 0
+ || approx_segment_count < ca->private_segment_count)
{
ca->private_segment_count = approx_segment_count;
}
/* Follow directions, but issue a warning */
- else if (approx_segment_count != ca->private_segment_count)
+ else if (approx_segment_count < ca->private_segment_count)
{
clib_warning ("Honoring segment count %u, calculated count was %u",
ca->private_segment_count, approx_segment_count);
}
+ else if (approx_segment_count > ca->private_segment_count)
+ {
+ clib_warning ("Segment count too low %u, calculated %u.",
+ ca->private_segment_count, approx_segment_count);
+ return VNET_API_ERROR_INVALID_VALUE;
+ }
if (svm_fifo_segment_create_process_private (ca))
clib_warning ("Failed to create process private segment");
ASSERT (vec_len (ca->new_segment_indices));
}
+
vec_append (sm->segment_indices, ca->new_segment_indices);
vec_free (ca->new_segment_indices);
return 0;
}
int
-session_manager_add_segment (segment_manager_t * sm)
+segment_manager_add_segment (segment_manager_t * sm)
{
- svm_fifo_segment_create_args_t _ca, *ca = &_ca;
- segment_manager_properties_t *props;
- u32 add_segment_size;
- u8 *segment_name;
- int rv;
-
- memset (ca, 0, sizeof (*ca));
- props = segment_manager_properties_get (sm->properties_index);
- segment_name = format (0, "%d-%d%c", getpid (), segment_name_counter++, 0);
- add_segment_size = props->add_segment_size ?
- props->add_segment_size : default_segment_size;
-
- rv = session_manager_add_segment_i (sm, add_segment_size, segment_name);
- vec_free (segment_name);
- return rv;
-}
-
-int
-session_manager_add_first_segment (segment_manager_t * sm, u32 segment_size)
-{
- u8 *segment_name;
- int rv;
-
- segment_name = format (0, "%d-%d%c", getpid (), segment_name_counter++, 0);
- rv = session_manager_add_segment_i (sm, segment_size, segment_name);
- vec_free (segment_name);
- return rv;
+ return segment_manager_add_segment_i (sm, 0, 0);
}
segment_manager_t *
@@ -203,14 +200,18 @@
*/
int
segment_manager_init (segment_manager_t * sm, u32 props_index,
- u32 first_seg_size)
+ u32 first_seg_size, u32 evt_q_size)
{
+ u32 protected_space;
int rv;
- /* app allocates these */
sm->properties_index = props_index;
+
+ protected_space = max_pow2 (sizeof (svm_queue_t)
+ + evt_q_size * sizeof (session_fifo_event_t));
+ protected_space = round_pow2_u64 (protected_space, CLIB_CACHE_LINE_BYTES);
first_seg_size = first_seg_size > 0 ? first_seg_size : default_segment_size;
- rv = session_manager_add_first_segment (sm, first_seg_size);
+ rv = segment_manager_add_segment_i (sm, first_seg_size, protected_space);
if (rv)
{
clib_warning ("Failed to allocate segment");
@@ -257,7 +258,7 @@
svm_fifo_segment_private_t *fifo_segment;
u32 svm_segment_index;
clib_spinlock_lock (&sm->lockp);
- svm_segment_index = sm->segment_indices[segment_index];
+ svm_segment_index = vec_elt (sm->segment_indices, segment_index);
fifo_segment = svm_fifo_segment_get_segment (svm_segment_index);
if (!fifo_segment
|| ((fifo_segment->h->flags & FIFO_SEGMENT_F_IS_PREALLOCATED)
@@ -307,8 +308,7 @@
if (session->session_state != SESSION_STATE_CLOSED)
{
session->session_state = SESSION_STATE_CLOSED;
- session_send_session_evt_to_thread (session_handle
- (session),
+ session_send_session_evt_to_thread (session_handle (session),
FIFO_EVENT_DISCONNECT,
thread_index);
}
@@ -371,8 +371,8 @@
int
segment_manager_alloc_session_fifos (segment_manager_t * sm,
- svm_fifo_t ** server_rx_fifo,
- svm_fifo_t ** server_tx_fifo,
+ svm_fifo_t ** rx_fifo,
+ svm_fifo_t ** tx_fifo,
u32 * fifo_segment_index)
{
svm_fifo_segment_private_t *fifo_segment;
@@ -392,39 +392,37 @@
again:
for (i = 0; i < vec_len (sm->segment_indices); i++)
{
- *fifo_segment_index = sm->segment_indices[i];
+ *fifo_segment_index = vec_elt (sm->segment_indices, i);
fifo_segment = svm_fifo_segment_get_segment (*fifo_segment_index);
fifo_size = props->rx_fifo_size;
fifo_size = (fifo_size == 0) ? default_fifo_size : fifo_size;
- *server_rx_fifo =
- svm_fifo_segment_alloc_fifo (fifo_segment, fifo_size,
- FIFO_SEGMENT_RX_FREELIST);
+ *rx_fifo = svm_fifo_segment_alloc_fifo (fifo_segment, fifo_size,
+ FIFO_SEGMENT_RX_FREELIST);
fifo_size = props->tx_fifo_size;
fifo_size = (fifo_size == 0) ? default_fifo_size : fifo_size;
- *server_tx_fifo =
- svm_fifo_segment_alloc_fifo (fifo_segment, fifo_size,
- FIFO_SEGMENT_TX_FREELIST);
+ *tx_fifo = svm_fifo_segment_alloc_fifo (fifo_segment, fifo_size,
+ FIFO_SEGMENT_TX_FREELIST);
- if (*server_rx_fifo == 0)
+ if (*rx_fifo == 0)
{
/* This would be very odd, but handle it... */
- if (*server_tx_fifo != 0)
+ if (*tx_fifo != 0)
{
- svm_fifo_segment_free_fifo (fifo_segment, *server_tx_fifo,
+ svm_fifo_segment_free_fifo (fifo_segment, *tx_fifo,
FIFO_SEGMENT_TX_FREELIST);
- *server_tx_fifo = 0;
+ *tx_fifo = 0;
}
continue;
}
- if (*server_tx_fifo == 0)
+ if (*tx_fifo == 0)
{
- if (*server_rx_fifo != 0)
+ if (*rx_fifo != 0)
{
- svm_fifo_segment_free_fifo (fifo_segment, *server_rx_fifo,
+ svm_fifo_segment_free_fifo (fifo_segment, *rx_fifo,
FIFO_SEGMENT_RX_FREELIST);
- *server_rx_fifo = 0;
+ *rx_fifo = 0;
}
continue;
}
@@ -432,9 +430,9 @@
}
/* See if we're supposed to create another segment */
- if (*server_rx_fifo == 0)
+ if (*rx_fifo == 0)
{
- if (props->add_segment && !props->use_private_segment)
+ if (props->add_segment && !props->segment_type)
{
if (added_a_segment)
{
@@ -443,7 +441,7 @@
return SESSION_ERROR_NEW_SEG_NO_SPACE;
}
- if (session_manager_add_segment (sm))
+ if (segment_manager_add_segment (sm))
{
clib_spinlock_unlock (&sm->lockp);
return VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
@@ -462,8 +460,8 @@
/* Backpointers to segment manager */
sm_index = segment_manager_index (sm);
- (*server_tx_fifo)->segment_manager = sm_index;
- (*server_rx_fifo)->segment_manager = sm_index;
+ (*tx_fifo)->segment_manager = sm_index;
+ (*rx_fifo)->segment_manager = sm_index;
clib_spinlock_unlock (&sm->lockp);
@@ -577,14 +575,12 @@
{
svm_fifo_segment_private_t *segments, *seg;
segment_manager_t *sm;
- u8 show_segments = 0, verbose = 0, *name;
+ u8 show_segments = 0, verbose = 0;
uword address;
u64 size;
u32 active_fifos;
u32 free_fifos;
- mheap_t *heap_header;
-
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "segments"))
@@ -615,37 +611,20 @@
segments = svm_fifo_segment_segments_pool ();
vlib_cli_output (vm, "%d svm fifo segments allocated",
pool_elts (segments));
- vlib_cli_output (vm, "%-25s%15s%16s%16s%16s", "Name",
+ vlib_cli_output (vm, "%-15s%10s%15s%15s%15s%15s", "Name", "Type",
"HeapSize (M)", "ActiveFifos", "FreeFifos", "Address");
/* *INDENT-OFF* */
pool_foreach (seg, segments, ({
- if (seg->h->flags & FIFO_SEGMENT_F_IS_PRIVATE)
- {
- address = pointer_to_uword (seg->ssvm.sh->heap);
- if (seg->h->flags & FIFO_SEGMENT_F_IS_MAIN_HEAP)
- name = format (0, "main heap");
- else
- name = format (0, "private heap");
- heap_header = mheap_header (seg->ssvm.sh->heap);
- size = heap_header->max_size;
- }
- else
- {
- address = seg->ssvm.sh->ssvm_va;
- size = seg->ssvm.ssvm_size;
- name = seg->ssvm.sh->name;
- }
+ svm_fifo_segment_info (seg, &address, &size);
active_fifos = svm_fifo_segment_num_fifos (seg);
free_fifos = svm_fifo_segment_num_free_fifos (seg, ~0 /* size */);
- vlib_cli_output (vm, "%-25v%15llu%16u%16u%16llx",
- name, size >> 20ULL, active_fifos, free_fifos,
- address);
+ vlib_cli_output (vm, "%-15v%10U%15llu%15u%15u%15llx",
+ ssvm_name (&seg->ssvm), format_svm_fifo_segment_type,
+ seg, size >> 20ULL, active_fifos, free_fifos,
+ address);
if (verbose)
- vlib_cli_output (vm, "%U",
- format_svm_fifo_segment, seg, verbose);
- if (seg->h->flags & FIFO_SEGMENT_F_IS_PRIVATE)
- vec_free (name);
+ vlib_cli_output (vm, "%U", format_svm_fifo_segment, seg, verbose);
}));
/* *INDENT-ON* */
diff --git a/src/vnet/session/segment_manager.h b/src/vnet/session/segment_manager.h
index 41e2308..b2a792d 100644
--- a/src/vnet/session/segment_manager.h
+++ b/src/vnet/session/segment_manager.h
@@ -36,8 +36,8 @@
/** Flag that indicates if additional segments should be created */
u8 add_segment;
- /** Use private memory segment instead of shared memory */
- u8 use_private_segment;
+ /** 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;
@@ -93,13 +93,13 @@
}
segment_manager_t *segment_manager_new ();
-int
-segment_manager_init (segment_manager_t * sm, u32 props_index, u32 seg_size);
+int segment_manager_init (segment_manager_t * sm, u32 props_index,
+ u32 seg_size, u32 evt_queue_size);
-void segment_manager_get_segment_info (u32 index, u8 ** name, u32 * size);
-int
-session_manager_add_first_segment (segment_manager_t * sm, u32 segment_size);
-int session_manager_add_segment (segment_manager_t * sm);
+svm_fifo_segment_private_t *segment_manager_get_segment (u32 segment_index);
+int segment_manager_add_first_segment (segment_manager_t * sm,
+ u32 segment_size);
+int segment_manager_add_segment (segment_manager_t * sm);
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);
@@ -112,8 +112,8 @@
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, u32 queue_size);
+svm_queue_t *segment_manager_alloc_queue (segment_manager_t * sm,
+ 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.c b/src/vnet/session/session.c
index adcbb29..be98e71 100644
--- a/src/vnet/session/session.c
+++ b/src/vnet/session/session.c
@@ -961,32 +961,66 @@
}
/**
- * Allocate vpp event queue (once) per worker thread
+ * Allocate event queues in the shared-memory segment
+ *
+ * That can either be a newly created memfd segment, that will need to be
+ * mapped by all stack users, or the binary api's svm region. The latter is
+ * assumed to be already mapped. NOTE that this assumption DOES NOT hold if
+ * api clients bootstrap shm api over sockets (i.e. use memfd segments) and
+ * vpp uses api svm region for event queues.
*/
void
-session_vpp_event_queue_allocate (session_manager_main_t * smm,
- u32 thread_index)
+session_vpp_event_queues_allocate (session_manager_main_t * smm)
{
+ u32 evt_q_length = 2048, evt_size = sizeof (session_fifo_event_t);
+ ssvm_private_t *eqs = &smm->evt_qs_segment;
api_main_t *am = &api_main;
+ u64 eqs_size = 64 << 20;
+ pid_t vpp_pid = getpid ();
void *oldheap;
- u32 event_queue_length = 2048;
+ int i;
- if (smm->vpp_event_queues[thread_index] == 0)
+ if (smm->configured_event_queue_length)
+ evt_q_length = smm->configured_event_queue_length;
+
+ if (smm->evt_qs_use_memfd_seg)
{
- /* Allocate event fifo in the /vpe-api shared-memory segment */
- oldheap = svm_push_data_heap (am->vlib_rp);
+ if (smm->evt_qs_segment_size)
+ eqs_size = smm->evt_qs_segment_size;
- if (smm->configured_event_queue_length)
- event_queue_length = smm->configured_event_queue_length;
+ eqs->ssvm_size = eqs_size;
+ eqs->i_am_master = 1;
+ eqs->my_pid = vpp_pid;
+ eqs->name = format (0, "%s%c", "evt-qs-segment", 0);
+ eqs->requested_va = smm->session_baseva;
- smm->vpp_event_queues[thread_index] =
- svm_queue_init
- (event_queue_length,
- sizeof (session_fifo_event_t), 0 /* consumer pid */ ,
- 0 /* (do not) send signal when queue non-empty */ );
-
- svm_pop_heap (oldheap);
+ ssvm_master_init (eqs, SSVM_SEGMENT_MEMFD);
}
+
+ if (smm->evt_qs_use_memfd_seg)
+ oldheap = ssvm_push_heap (eqs->sh);
+ else
+ oldheap = svm_push_data_heap (am->vlib_rp);
+
+ for (i = 0; i < vec_len (smm->vpp_event_queues); i++)
+ {
+ smm->vpp_event_queues[i] = svm_queue_init (evt_q_length, evt_size,
+ vpp_pid, 0);
+ }
+
+ if (smm->evt_qs_use_memfd_seg)
+ ssvm_pop_heap (oldheap);
+ else
+ svm_pop_heap (oldheap);
+}
+
+ssvm_private_t *
+session_manager_get_evt_q_segment (void)
+{
+ session_manager_main_t *smm = &session_manager_main;
+ if (smm->evt_qs_use_memfd_seg)
+ return &smm->evt_qs_segment;
+ return 0;
}
/**
@@ -1076,10 +1110,6 @@
if (num_threads < 1)
return clib_error_return (0, "n_thread_stacks not set");
- /* $$$ config parameters */
- svm_fifo_segment_init (0x200000000ULL /* first segment base VA */ ,
- 20 /* timeout in seconds */ );
-
/* configure per-thread ** vectors */
vec_validate (smm->sessions, num_threads - 1);
vec_validate (smm->tx_buffers, num_threads - 1);
@@ -1117,9 +1147,12 @@
vec_validate (smm->last_event_poll_by_thread, num_threads - 1);
#endif
- /* Allocate vpp event queues */
- for (i = 0; i < vec_len (smm->vpp_event_queues); i++)
- session_vpp_event_queue_allocate (smm, i);
+ /* Allocate vpp event queues segment and queue */
+ session_vpp_event_queues_allocate (smm);
+
+ /* Initialize fifo segment main baseva and timeout */
+ svm_fifo_segment_init (smm->session_baseva + smm->evt_qs_segment_size,
+ smm->segment_timeout);
/* Preallocate sessions */
if (smm->preallocated_sessions)
@@ -1192,6 +1225,9 @@
session_manager_main_init (vlib_main_t * vm)
{
session_manager_main_t *smm = &session_manager_main;
+ smm->session_baseva = 0x200000000ULL;
+ smm->segment_timeout = 20;
+ smm->evt_qs_segment_size = 64 << 20;
smm->is_enabled = 0;
return 0;
}
@@ -1272,6 +1308,8 @@
else if (unformat (input, "local-endpoints-table-buckets %d",
&smm->local_endpoints_table_buckets))
;
+ else if (unformat (input, "evt_qs_memfd_seg"))
+ smm->evt_qs_use_memfd_seg = 1;
else
return clib_error_return (0, "unknown input `%U'",
format_unformat_error, input);
diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h
index 5e017c6..98e8acb 100644
--- a/src/vnet/session/session.h
+++ b/src/vnet/session/session.h
@@ -149,6 +149,9 @@
/** vpp fifo event queue */
svm_queue_t **vpp_event_queues;
+ /** Event queues memfd segment initialized only if so configured */
+ ssvm_private_t evt_qs_segment;
+
/** Unique segment name counter */
u32 unique_segment_name_counter;
@@ -170,7 +173,13 @@
* Config parameters
*/
- /** session table size parameters */
+ /** Session ssvm segment configs*/
+ uword session_baseva;
+ u32 segment_timeout;
+ u32 evt_qs_segment_size;
+ u8 evt_qs_use_memfd_seg;
+
+ /** Session table size parameters */
u32 configured_v4_session_table_buckets;
u32 configured_v4_session_table_memory;
u32 configured_v4_halfopen_table_buckets;
@@ -443,6 +452,7 @@
void session_send_session_evt_to_thread (u64 session_handle,
fifo_event_type_t evt_type,
u32 thread_index);
+ssvm_private_t *session_manager_get_evt_q_segment (void);
u8 *format_stream_session (u8 * s, va_list * args);
uword unformat_stream_session (unformat_input_t * input, va_list * args);
diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c
index eeda839..5201ec6 100755
--- a/src/vnet/session/session_api.c
+++ b/src/vnet/session/session_api.c
@@ -58,25 +58,54 @@
_(SESSION_RULES_DUMP, session_rules_dump) \
static int
-send_add_segment_callback (u32 api_client_index, const u8 * segment_name,
- u32 segment_size)
+session_send_memfd_fd (vl_api_registration_t * reg, const ssvm_private_t * sp)
+{
+ clib_error_t *error;
+ if (vl_api_registration_file_index (reg) == VL_API_INVALID_FI)
+ {
+ clib_warning ("can't send memfd fd");
+ return -1;
+ }
+ error = vl_api_send_fd_msg (reg, sp->fd);
+ if (error)
+ {
+ clib_error_report (error);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+send_add_segment_callback (u32 api_client_index, const ssvm_private_t * sp)
{
vl_api_map_another_segment_t *mp;
- svm_queue_t *q;
+ vl_api_registration_t *reg;
- q = vl_api_client_index_to_input_queue (api_client_index);
+ reg = vl_mem_api_client_index_to_registration (api_client_index);
+ if (!reg)
+ {
+ clib_warning ("no registration: %u", api_client_index);
+ return -1;
+ }
- if (!q)
- return -1;
+ if (ssvm_type (sp) == 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_MAP_ANOTHER_SEGMENT);
- mp->segment_size = segment_size;
- strncpy ((char *) mp->segment_name, (char *) segment_name,
+ mp->segment_size = sp->ssvm_size;
+ strncpy ((char *) mp->segment_name, (char *) sp->name,
sizeof (mp->segment_name) - 1);
- vl_msg_api_send_shmem (q, (u8 *) & mp);
+ vl_msg_api_send_shmem (reg->vl_input_queue, (u8 *) & mp);
+
+ if (ssvm_type (sp) == SSVM_SEGMENT_MEMFD)
+ return session_send_memfd_fd (reg, sp);
return 0;
}
@@ -84,20 +113,23 @@
static int
send_session_accept_callback (stream_session_t * s)
{
- vl_api_accept_session_t *mp;
- svm_queue_t *q, *vpp_queue;
application_t *server = application_get (s->app_index);
- transport_connection_t *tc;
transport_proto_vft_t *tp_vft;
+ vl_api_accept_session_t *mp;
+ vl_api_registration_t *reg;
+ transport_connection_t *tc;
stream_session_t *listener;
+ svm_queue_t *vpp_queue;
- q = vl_api_client_index_to_input_queue (server->api_client_index);
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)
+ {
+ clib_warning ("no registration: %u", server->api_client_index);
+ return -1;
+ }
- if (!q)
- return -1;
-
- mp = vl_msg_api_alloc_as_if_client (sizeof (*mp));
+ 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_ACCEPT_SESSION);
@@ -123,7 +155,7 @@
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 (q, (u8 *) & mp);
+ vl_msg_api_send_shmem (reg->vl_input_queue, (u8 *) & mp);
return 0;
}
@@ -131,39 +163,43 @@
static void
send_session_disconnect_callback (stream_session_t * s)
{
- vl_api_disconnect_session_t *mp;
- svm_queue_t *q;
application_t *app = application_get (s->app_index);
+ vl_api_disconnect_session_t *mp;
+ vl_api_registration_t *reg;
- q = vl_api_client_index_to_input_queue (app->api_client_index);
+ reg = vl_mem_api_client_index_to_registration (app->api_client_index);
+ if (!reg)
+ {
+ clib_warning ("no registration: %u", app->api_client_index);
+ return;
+ }
- if (!q)
- return;
-
- mp = vl_msg_api_alloc_as_if_client (sizeof (*mp));
+ 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 = session_handle (s);
- vl_msg_api_send_shmem (q, (u8 *) & mp);
+ vl_msg_api_send_shmem (reg->vl_input_queue, (u8 *) & mp);
}
static void
send_session_reset_callback (stream_session_t * s)
{
- vl_api_reset_session_t *mp;
- svm_queue_t *q;
application_t *app = application_get (s->app_index);
+ vl_api_registration_t *reg;
+ vl_api_reset_session_t *mp;
- q = vl_api_client_index_to_input_queue (app->api_client_index);
+ reg = vl_mem_api_client_index_to_registration (app->api_client_index);
+ if (!reg)
+ {
+ clib_warning ("no registration: %u", app->api_client_index);
+ return;
+ }
- if (!q)
- return;
-
- mp = vl_msg_api_alloc_as_if_client (sizeof (*mp));
+ 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_RESET_SESSION);
mp->handle = session_handle (s);
- vl_msg_api_send_shmem (q, (u8 *) & mp);
+ vl_msg_api_send_shmem (reg->vl_input_queue, (u8 *) & mp);
}
int
@@ -171,18 +207,20 @@
stream_session_t * s, u8 is_fail)
{
vl_api_connect_session_reply_t *mp;
- svm_queue_t *q;
- application_t *app;
- svm_queue_t *vpp_queue;
transport_connection_t *tc;
+ vl_api_registration_t *reg;
+ svm_queue_t *vpp_queue;
+ application_t *app;
app = application_get (app_index);
- q = vl_api_client_index_to_input_queue (app->api_client_index);
+ reg = vl_mem_api_client_index_to_registration (app->api_client_index);
+ if (!reg)
+ {
+ clib_warning ("no registration: %u", app->api_client_index);
+ return -1;
+ }
- if (!q)
- return -1;
-
- mp = vl_msg_api_alloc_as_if_client (sizeof (*mp));
+ mp = vl_mem_api_alloc_as_if_client_w_reg (reg, sizeof (*mp));
mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_CONNECT_SESSION_REPLY);
mp->context = api_context;
@@ -208,7 +246,7 @@
done:
mp->retval = is_fail ?
clib_host_to_net_u32 (VNET_API_ERROR_SESSION_CONNECT) : 0;
- vl_msg_api_send_shmem (q, (u8 *) & mp);
+ vl_msg_api_send_shmem (reg->vl_input_queue, (u8 *) & mp);
return 0;
}
@@ -310,7 +348,9 @@
vl_api_application_attach_t_handler (vl_api_application_attach_t * mp)
{
vl_api_application_attach_reply_t *rmp;
+ ssvm_private_t *segp, *evt_q_segment;
vnet_app_attach_args_t _a, *a = &_a;
+ vl_api_registration_t *reg;
clib_error_t *error = 0;
int rv = 0;
@@ -354,18 +394,30 @@
REPLY_MACRO2 (VL_API_APPLICATION_ATTACH_REPLY, ({
if (!rv)
{
+ segp = a->segment;
rmp->segment_name_length = 0;
- rmp->segment_size = a->segment_size;
- if (a->segment_name_length)
+ rmp->segment_size = segp->ssvm_size;
+ if (vec_len (segp->name))
{
- memcpy (rmp->segment_name, a->segment_name,
- a->segment_name_length);
- rmp->segment_name_length = a->segment_name_length;
+ memcpy (rmp->segment_name, segp->name, vec_len (segp->name));
+ rmp->segment_name_length = vec_len (segp->name);
}
rmp->app_event_queue_address = a->app_event_queue_address;
}
}));
/* *INDENT-ON* */
+
+ if (rv)
+ return;
+
+ reg = vl_api_client_index_to_registration (mp->client_index);
+
+ /* Send fifo segment fd if needed */
+ if (ssvm_type (a->segment) == SSVM_SEGMENT_MEMFD)
+ session_send_memfd_fd (reg, a->segment);
+ /* Send event queues segment */
+ if ((evt_q_segment = session_manager_get_evt_q_segment ()))
+ session_send_memfd_fd (reg, evt_q_segment);
}
static void
diff --git a/src/vnet/session/session_test.c b/src/vnet/session/session_test.c
index 64657c1..a9a902d 100644
--- a/src/vnet/session/session_test.c
+++ b/src/vnet/session/session_test.c
@@ -103,7 +103,6 @@
{
session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
u64 options[APP_OPTIONS_N_OPTIONS], bind4_handle, bind6_handle;
- u8 segment_name[128];
clib_error_t *error = 0;
u32 server_index;
@@ -117,7 +116,6 @@
.options = options,
.namespace_id = 0,
.session_cb_vft = &dummy_session_cbs,
- .segment_name = segment_name,
};
error = vnet_application_attach (&attach_args);
@@ -178,7 +176,6 @@
clib_error_t *error = 0;
u8 *ns_id = format (0, "appns1"), intf_mac[6];
app_namespace_t *app_ns;
- u8 segment_name[128];
application_t *server;
stream_session_t *s;
int code;
@@ -197,7 +194,6 @@
.options = options,
.namespace_id = 0,
.session_cb_vft = &dummy_session_cbs,
- .segment_name = segment_name,
};
vnet_bind_args_t bind_args = {
@@ -781,7 +777,7 @@
transport_connection_t *tc;
u32 dummy_port = 1111;
clib_error_t *error = 0;
- u8 segment_name[128], is_filtered = 0, *ns_id = format (0, "appns1");
+ u8 is_filtered = 0, *ns_id = format (0, "appns1");
stream_session_t *listener, *s;
app_namespace_t *default_ns = app_namespace_get_default ();
u32 local_ns_index = default_ns->local_table_index;
@@ -809,7 +805,6 @@
.options = options,
.namespace_id = 0,
.session_cb_vft = &dummy_session_cbs,
- .segment_name = segment_name,
};
vnet_bind_args_t bind_args = {
@@ -1342,7 +1337,7 @@
u32 server_index, app_index;
u32 dummy_server_api_index = ~0, sw_if_index = 0;
clib_error_t *error = 0;
- u8 segment_name[128], intf_mac[6], sst, is_filtered = 0;
+ u8 intf_mac[6], sst, is_filtered = 0;
stream_session_t *s;
transport_connection_t *tc;
u16 lcl_port = 1234, rmt_port = 4321;
@@ -1407,7 +1402,6 @@
.options = options,
.namespace_id = 0,
.session_cb_vft = &dummy_session_cbs,
- .segment_name = segment_name,
};
attach_args.api_client_index = dummy_server_api_index;