X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fsession%2Fsegment_manager.c;h=a55f7d3472c0c0a45c9372e64de541304757117e;hb=2711ca710affe0c52bf63e08e0cf0588094e6198;hp=2d20d9cc1e4fc2a6e63bc9668f839f562dd657fe;hpb=9a45bd84d9f8e37f7914eb36d2ffdcd209aa15cb;p=vpp.git diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c index 2d20d9cc1e4..a55f7d3472c 100644 --- a/src/vnet/session/segment_manager.c +++ b/src/vnet/session/segment_manager.c @@ -87,8 +87,9 @@ segment_manager_segment_index (segment_manager_t * sm, fifo_segment_t * seg) * If needed a writer's lock is acquired before allocating a new segment * to avoid affecting any of the segments pool readers. */ -int -segment_manager_add_segment (segment_manager_t * sm, uword segment_size) +static inline int +segment_manager_add_segment_inline (segment_manager_t *sm, uword segment_size, + u8 notify_app, u8 flags) { segment_manager_main_t *smm = &sm_main; segment_manager_props_t *props; @@ -118,6 +119,12 @@ segment_manager_add_segment (segment_manager_t * sm, uword segment_size) * Allocate ssvm segment */ segment_size = segment_size ? segment_size : props->add_segment_size; + /* add overhead to ensure the result segment size is at least + * of that requested */ + segment_size += + sizeof (fifo_segment_header_t) + + vlib_thread_main.n_vlib_mains * sizeof (fifo_segment_slice_t) + + FIFO_SEGMENT_ALLOC_OVERHEAD; segment_size = round_pow2 (segment_size, clib_mem_get_page_size ()); if (props->segment_type != SSVM_SEGMENT_PRIVATE) @@ -157,11 +164,22 @@ segment_manager_add_segment (segment_manager_t * sm, uword segment_size) /* * Set watermarks in segment */ - fs->h->high_watermark = sm->high_watermark; - fs->h->low_watermark = sm->low_watermark; + fs->high_watermark = sm->high_watermark; + fs->low_watermark = sm->low_watermark; + fs->flags = flags; + fs->flags &= ~FIFO_SEGMENT_F_MEM_LIMIT; fs->h->pct_first_alloc = props->pct_first_alloc; - fs->h->flags &= ~FIFO_SEGMENT_F_MEM_LIMIT; + if (notify_app) + { + app_worker_t *app_wrk; + u64 fs_handle; + fs_handle = segment_manager_segment_handle (sm, fs); + app_wrk = app_worker_get (sm->app_wrk_index); + rv = app_worker_add_segment_notify (app_wrk, fs_handle); + if (rv) + return rv; + } done: if (vlib_num_workers ()) @@ -170,6 +188,20 @@ done: return fs_index; } +int +segment_manager_add_segment (segment_manager_t *sm, uword segment_size, + u8 notify_app) +{ + return segment_manager_add_segment_inline (sm, segment_size, notify_app, 0); +} + +int +segment_manager_add_segment2 (segment_manager_t *sm, uword segment_size, + u8 flags) +{ + return segment_manager_add_segment_inline (sm, segment_size, 0, flags); +} + /** * Remove segment without lock */ @@ -376,7 +408,7 @@ segment_manager_init_first (segment_manager_t * sm) /* Allocate the segments */ for (i = 0; i < approx_segment_count + 1; i++) { - fs_index = segment_manager_add_segment (sm, max_seg_size); + fs_index = segment_manager_add_segment (sm, max_seg_size, 0); if (fs_index < 0) { clib_warning ("Failed to preallocate segment %d", i); @@ -398,7 +430,7 @@ segment_manager_init_first (segment_manager_t * sm) return 0; } - fs_index = segment_manager_add_segment (sm, first_seg_size); + fs_index = segment_manager_add_segment (sm, first_seg_size, 0); if (fs_index < 0) { clib_warning ("Failed to allocate segment"); @@ -466,6 +498,7 @@ segment_manager_free (segment_manager_t * sm) } /* *INDENT-ON* */ + pool_free (sm->segments); clib_rwlock_writer_unlock (&sm->segments_rwlock); clib_rwlock_free (&sm->segments_rwlock); @@ -486,8 +519,8 @@ sm_free_w_index_helper (void *arg) segment_manager_free (sm); } -static void -segment_manager_free_safe (segment_manager_t * sm) +void +segment_manager_free_safe (segment_manager_t *sm) { if (!vlib_thread_is_main_w_barrier ()) { @@ -611,6 +644,60 @@ segment_manager_del_sessions (segment_manager_t * sm) /* Avoid propagating notifications back to the app */ session->app_wrk_index = APP_INVALID_INDEX; } + vec_free (handles); +} + +/** + * Initiate disconnects for sessions in specified state 'owned' by a segment + * manager + */ +void +segment_manager_del_sessions_filter (segment_manager_t *sm, + session_state_t *states) +{ + session_handle_t *handles = 0, *handle; + fifo_segment_t *fs; + session_t *session; + int slice_index; + svm_fifo_t *f; + + ASSERT (pool_elts (sm->segments) != 0); + + /* Across all fifo segments used by the server */ + segment_manager_foreach_segment_w_lock ( + fs, sm, ({ + for (slice_index = 0; slice_index < fs->n_slices; slice_index++) + { + f = fifo_segment_get_slice_fifo_list (fs, slice_index); + while (f) + { + session = session_get_if_valid (f->shr->master_session_index, + f->master_thread_index); + if (session) + { + session_state_t *state; + vec_foreach (state, states) + { + if (session->session_state == *state) + { + vec_add1 (handles, session_handle (session)); + break; + } + } + } + f = f->next; + } + } + })); + + vec_foreach (handle, handles) + { + session = session_get_from_handle (*handle); + session_close (session); + /* Avoid propagating notifications back to the app */ + session->app_wrk_index = APP_INVALID_INDEX; + } + vec_free (handles); } int @@ -663,8 +750,6 @@ segment_manager_alloc_session_fifos (segment_manager_t * sm, segment_manager_props_t *props; fifo_segment_t *fs = 0, *cur; u32 sm_index, fs_index; - u8 added_a_segment = 0; - u64 fs_handle; props = segment_manager_properties_get (sm); @@ -674,16 +759,16 @@ segment_manager_alloc_session_fifos (segment_manager_t * sm, segment_manager_segment_reader_lock (sm); - /* *INDENT-OFF* */ pool_foreach (cur, sm->segments) { - free_bytes = fifo_segment_available_bytes (cur); - if (free_bytes > max_free_bytes) - { - max_free_bytes = free_bytes; - fs = cur; - } + if (fifo_segment_flags (cur) & FIFO_SEGMENT_F_CUSTOM_USE) + continue; + free_bytes = fifo_segment_available_bytes (cur); + if (free_bytes > max_free_bytes) + { + max_free_bytes = free_bytes; + fs = cur; + } } - /* *INDENT-ON* */ if (fs) { @@ -698,45 +783,12 @@ segment_manager_alloc_session_fifos (segment_manager_t * sm, segment_manager_segment_reader_unlock (sm); -alloc_check: - - if (!alloc_fail) - { - - alloc_success: - - ASSERT (rx_fifo && tx_fifo); - sm_index = segment_manager_index (sm); - fs_index = segment_manager_segment_index (sm, fs); - (*tx_fifo)->segment_manager = sm_index; - (*rx_fifo)->segment_manager = sm_index; - (*tx_fifo)->segment_index = fs_index; - (*rx_fifo)->segment_index = fs_index; - - if (added_a_segment) - { - app_worker_t *app_wrk; - fs_handle = segment_manager_segment_handle (sm, fs); - app_wrk = app_worker_get (sm->app_wrk_index); - rv = app_worker_add_segment_notify (app_wrk, fs_handle); - } - /* Drop the lock after app is notified */ - segment_manager_segment_reader_unlock (sm); - return rv; - } - /* * Allocation failed, see if we can add a new segment */ if (props->add_segment) { - if (added_a_segment) - { - clib_warning ("Added a segment, still can't allocate a fifo"); - segment_manager_segment_reader_unlock (sm); - return SESSION_E_SEG_NO_SPACE2; - } - if ((new_fs_index = segment_manager_add_segment (sm, 0)) < 0) + if ((new_fs_index = segment_manager_add_segment (sm, 0, 1)) < 0) { clib_warning ("Failed to add new segment"); return SESSION_E_SEG_CREATE; @@ -746,14 +798,33 @@ alloc_check: props->rx_fifo_size, props->tx_fifo_size, rx_fifo, tx_fifo); - added_a_segment = 1; - goto alloc_check; + if (alloc_fail) + { + clib_warning ("Added a segment, still can't allocate a fifo"); + segment_manager_segment_reader_unlock (sm); + return SESSION_E_SEG_NO_SPACE2; + } } else { SESSION_DBG ("Can't add new seg and no space to allocate fifos!"); return SESSION_E_SEG_NO_SPACE; } + +alloc_success: + ASSERT (rx_fifo && tx_fifo); + + sm_index = segment_manager_index (sm); + fs_index = segment_manager_segment_index (sm, fs); + (*tx_fifo)->segment_manager = sm_index; + (*rx_fifo)->segment_manager = sm_index; + (*tx_fifo)->segment_index = fs_index; + (*rx_fifo)->segment_index = fs_index; + + /* Drop the lock after app is notified */ + segment_manager_segment_reader_unlock (sm); + + return rv; } void @@ -800,27 +871,27 @@ segment_manager_dealloc_fifos (svm_fifo_t * rx_fifo, svm_fifo_t * tx_fifo) } void -segment_manager_detach_fifo (segment_manager_t * sm, svm_fifo_t * f) +segment_manager_detach_fifo (segment_manager_t *sm, svm_fifo_t **f) { fifo_segment_t *fs; - fs = segment_manager_get_segment_w_lock (sm, f->segment_index); + fs = segment_manager_get_segment_w_lock (sm, (*f)->segment_index); fifo_segment_detach_fifo (fs, f); segment_manager_segment_reader_unlock (sm); } void -segment_manager_attach_fifo (segment_manager_t * sm, svm_fifo_t * f, - session_t * s) +segment_manager_attach_fifo (segment_manager_t *sm, svm_fifo_t **f, + session_t *s) { fifo_segment_t *fs; - fs = segment_manager_get_segment_w_lock (sm, f->segment_index); + fs = segment_manager_get_segment_w_lock (sm, (*f)->segment_index); fifo_segment_attach_fifo (fs, f, s->thread_index); segment_manager_segment_reader_unlock (sm); - f->shr->master_session_index = s->session_index; - f->master_thread_index = s->thread_index; + (*f)->shr->master_session_index = s->session_index; + (*f)->master_thread_index = s->thread_index; } u32 @@ -870,7 +941,7 @@ segment_manager_alloc_queue (fifo_segment_t * segment, if (props->use_mq_eventfd) { - if (svm_msg_q_alloc_producer_eventfd (q)) + if (svm_msg_q_alloc_eventfd (q)) clib_warning ("failed to alloc eventfd"); } return q; @@ -1007,10 +1078,11 @@ segment_manager_format_sessions (segment_manager_t * sm, int verbose) if (!sm) { if (verbose) - vlib_cli_output (vm, "%-40s%-20s%-15s%-10s", "Connection", "App", - "API Client", "SegManager"); + vlib_cli_output (vm, "%-" SESSION_CLI_ID_LEN "s%-20s%-15s%-10s", + "Connection", "App", "API Client", "SegManager"); else - vlib_cli_output (vm, "%-40s%-20s", "Connection", "App"); + vlib_cli_output (vm, "%-" SESSION_CLI_ID_LEN "s%-20s", "Connection", + "App"); return; } @@ -1036,11 +1108,11 @@ segment_manager_format_sessions (segment_manager_t * sm, int verbose) str = format (0, "%U", format_session, session, verbose); if (verbose) - s = format (s, "%-40v%-20v%-15u%-10u", str, app_name, - app_wrk->api_client_index, + s = format (s, "%-" SESSION_CLI_ID_LEN "v%-20v%-15u%-10u", str, + app_name, app_wrk->api_client_index, app_wrk->connects_seg_manager); else - s = format (s, "%-40v%-20v", str, app_name); + s = format (s, "%-" SESSION_CLI_ID_LEN "v%-20v", str, app_name); vlib_cli_output (vm, "%v", s); vec_reset_length (s);