diff options
author | Florin Coras <fcoras@cisco.com> | 2018-01-15 01:08:33 -0800 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2018-01-25 23:53:35 +0000 |
commit | b384b543313b6b47a277c903e9d4fcd4343054fa (patch) | |
tree | 1996e3a25eb3a32fe5bbc405d75f38dd041a5a40 /src/vnet/session | |
parent | 4e578068fc3fe8ba176d211123ddd88962dab315 (diff) |
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>
Diffstat (limited to 'src/vnet/session')
-rw-r--r-- | src/vnet/session/application.c | 84 | ||||
-rw-r--r-- | src/vnet/session/application.h | 4 | ||||
-rw-r--r-- | src/vnet/session/application_interface.c | 13 | ||||
-rw-r--r-- | src/vnet/session/application_interface.h | 4 | ||||
-rw-r--r-- | src/vnet/session/segment_manager.c | 195 | ||||
-rw-r--r-- | src/vnet/session/segment_manager.h | 20 | ||||
-rw-r--r-- | src/vnet/session/session.c | 82 | ||||
-rw-r--r-- | src/vnet/session/session.h | 12 | ||||
-rwxr-xr-x | src/vnet/session/session_api.c | 148 | ||||
-rw-r--r-- | src/vnet/session/session_test.c | 10 |
10 files changed, 342 insertions, 230 deletions
diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c index 8090e75a6dc..13ccdd7cbc8 100644 --- a/src/vnet/session/application.c +++ b/src/vnet/session/application.c @@ -227,18 +227,56 @@ application_verify_cb_fns (session_cb_vft_t * cb_fns) 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 @@ application_init (application_t * app, u32 api_client_index, u64 * options, 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 @@ int 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 fd6454f21af..afe738f199c 100644 --- a/src/vnet/session/application.h +++ b/src/vnet/session/application.h @@ -30,8 +30,8 @@ typedef enum 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 ec317896f14..f2a13be6144 100644 --- a/src/vnet/session/application_interface.c +++ b/src/vnet/session/application_interface.c @@ -413,11 +413,11 @@ session_validate_namespace (u8 * namespace_id, u64 secret, u32 * app_ns_index) 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 @@ vnet_application_attach (vnet_app_attach_args_t * a) 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 68973a9f938..8db318fa413 100644 --- a/src/vnet/session/application_interface.h +++ b/src/vnet/session/application_interface.h @@ -39,9 +39,7 @@ typedef struct _vnet_app_attach_args_t /* * 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 dc3e4c9e648..c3a794b7fc4 100644 --- a/src/vnet/session/segment_manager.c +++ b/src/vnet/session/segment_manager.c @@ -49,6 +49,9 @@ segment_manager_properties_alloc (void) 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 @@ segment_manager_properties_index (segment_manager_properties_t * p) 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) + + /* Not configured for addition of new segments and not first */ + if (!props->add_segment && !segment_size) { - 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) + 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 @@ session_manager_add_segment_i (segment_manager_t * sm, u32 segment_size, 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 @@ segment_manager_new () */ 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 @@ segment_manager_del_segment (segment_manager_t * sm, u32 segment_index) 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 @@ segment_manager_del_sessions (segment_manager_t * sm) 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 @@ segment_manager_init_del (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, + 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 @@ segment_manager_alloc_session_fifos (segment_manager_t * sm, 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 @@ again: } /* 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 @@ again: 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 @@ again: /* 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 @@ segment_manager_show_fn (vlib_main_t * vm, unformat_input_t * input, { 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 @@ segment_manager_show_fn (vlib_main_t * vm, unformat_input_t * input, 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 41e2308928f..b2a792d206b 100644 --- a/src/vnet/session/segment_manager.h +++ b/src/vnet/session/segment_manager.h @@ -36,8 +36,8 @@ typedef struct _segment_manager_properties /** 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_index (segment_manager_t * sm) } 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 @@ segment_manager_alloc_session_fifos (segment_manager_t * sm, 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 adcbb2924d8..be98e712e9b 100644 --- a/src/vnet/session/session.c +++ b/src/vnet/session/session.c @@ -961,32 +961,66 @@ stream_session_cleanup (stream_session_t * s) } /** - * 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->configured_event_queue_length) + evt_q_length = smm->configured_event_queue_length; - if (smm->vpp_event_queues[thread_index] == 0) + 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 */ ); + 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); - svm_pop_heap (oldheap); + 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 @@ session_manager_main_enable (vlib_main_t * vm) 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 @@ session_manager_main_enable (vlib_main_t * vm) 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 @@ clib_error_t * 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 @@ session_config_fn (vlib_main_t * vm, unformat_input_t * input) 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 5e017c6c852..98e8acb79c1 100644 --- a/src/vnet/session/session.h +++ b/src/vnet/session/session.h @@ -149,6 +149,9 @@ struct _session_manager_main /** 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 @@ struct _session_manager_main * 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 stream_session_cleanup (stream_session_t * s); 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 eeda839a2fb..5201ec60751 100755 --- a/src/vnet/session/session_api.c +++ b/src/vnet/session/session_api.c @@ -58,25 +58,54 @@ _(SESSION_RULE_ADD_DEL, session_rule_add_del) \ _(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 @@ send_add_segment_callback (u32 api_client_index, const u8 * segment_name, 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 @@ send_session_accept_callback (stream_session_t * s) 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 @@ send_session_accept_callback (stream_session_t * s) 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); - - if (!q) - return; + 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_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); - - if (!q) - return; + 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_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 @@ send_session_connected_callback (u32 app_index, u32 api_context, 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); - - if (!q) - return -1; + 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; + } - 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 @@ send_session_connected_callback (u32 app_index, u32 api_context, 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 @@ static void 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 @@ done: 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 64657c11da0..a9a902d27bc 100644 --- a/src/vnet/session/session_test.c +++ b/src/vnet/session/session_test.c @@ -103,7 +103,6 @@ session_test_basic (vlib_main_t * vm, unformat_input_t * input) { 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 @@ session_test_basic (vlib_main_t * vm, unformat_input_t * input) .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 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input) 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 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input) .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 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) 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 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) .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 @@ session_test_proxy (vlib_main_t * vm, unformat_input_t * input) 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 @@ session_test_proxy (vlib_main_t * vm, unformat_input_t * input) .options = options, .namespace_id = 0, .session_cb_vft = &dummy_session_cbs, - .segment_name = segment_name, }; attach_args.api_client_index = dummy_server_api_index; |