From c8e812f6fb88dcd537e4de9333b5acf32e6f1ca0 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Thu, 14 May 2020 05:32:18 +0000 Subject: session: track detached listener segment managers Type: fix Signed-off-by: Florin Coras Change-Id: Iae734a526d2e7befd9738054d028df0062b67000 --- src/vnet/session/application.h | 7 +++++ src/vnet/session/application_worker.c | 50 +++++++++++++++++++++++++++++++---- src/vnet/session/segment_manager.c | 19 +++++++++++-- src/vnet/session/segment_manager.h | 8 ++++++ 4 files changed, 77 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/vnet/session/application.h b/src/vnet/session/application.h index 377ea1ef4ac..b6f957ab871 100644 --- a/src/vnet/session/application.h +++ b/src/vnet/session/application.h @@ -66,6 +66,12 @@ typedef struct app_worker_ /** Per transport proto hash tables of half-open connection handles */ uword **half_open_table; + + /** Protects detached seg managers */ + clib_spinlock_t detached_seg_managers_lock; + + /** Vector of detached listener segment managers */ + u32 *detached_seg_managers; } app_worker_t; typedef struct app_worker_map_ @@ -292,6 +298,7 @@ int app_worker_lock_and_send_event (app_worker_t * app, session_t * s, u8 evt_type); session_t *app_worker_proxy_listener (app_worker_t * app, u8 fib_proto, u8 transport_proto); +void app_worker_del_detached_sm (app_worker_t * app_wrk, u32 sm_index); u8 *format_app_worker (u8 * s, va_list * args); u8 *format_app_worker_listener (u8 * s, va_list * args); u8 *format_crypto_engine (u8 * s, va_list * args); diff --git a/src/vnet/session/application_worker.c b/src/vnet/session/application_worker.c index f9740a300c2..17aeb57d49b 100644 --- a/src/vnet/session/application_worker.c +++ b/src/vnet/session/application_worker.c @@ -33,6 +33,7 @@ app_worker_alloc (application_t * app) app_wrk->wrk_map_index = ~0; app_wrk->connects_seg_manager = APP_INVALID_SEGMENT_MANAGER_INDEX; app_wrk->first_segment_manager = APP_INVALID_SEGMENT_MANAGER_INDEX; + clib_spinlock_init (&app_wrk->detached_seg_managers_lock); APP_DBG ("New app %v worker %u", app->name, app_wrk->wrk_index); return app_wrk; } @@ -131,17 +132,26 @@ app_worker_free (app_worker_t * app_wrk) vec_free (app_wrk->half_open_table); vec_free (handles); + /* + * Detached listener segment managers cleanup + */ + for (i = 0; i < vec_len (app_wrk->detached_seg_managers); i++) + { + sm = segment_manager_get (app_wrk->detached_seg_managers[i]); + segment_manager_init_free (sm); + } + vec_free (app_wrk->detached_seg_managers); + clib_spinlock_free (&app_wrk->detached_seg_managers_lock); + /* If first segment manager is used by a listener that recently * stopped listening, mark it as detached */ if (app_wrk->first_segment_manager != app_wrk->connects_seg_manager - && (sm = segment_manager_get_if_valid (app_wrk->first_segment_manager))) + && (sm = segment_manager_get_if_valid (app_wrk->first_segment_manager)) + && !segment_manager_app_detached (sm)) { sm->first_is_protected = 0; sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX; - /* .. and has no fifos, e.g. it might be used for redirected sessions, - * remove it */ - if (!segment_manager_has_fifos (sm)) - segment_manager_free (sm); + segment_manager_init_free (sm); } if (CLIB_DEBUG) @@ -253,6 +263,29 @@ app_worker_start_listen (app_worker_t * app_wrk, return 0; } +static void +app_worker_add_detached_sm (app_worker_t * app_wrk, u32 sm_index) +{ + vec_add1 (app_wrk->detached_seg_managers, sm_index); +} + +void +app_worker_del_detached_sm (app_worker_t * app_wrk, u32 sm_index) +{ + u32 i; + + clib_spinlock_lock (&app_wrk->detached_seg_managers_lock); + for (i = 0; i < vec_len (app_wrk->detached_seg_managers); i++) + { + if (app_wrk->detached_seg_managers[i] == sm_index) + { + vec_del1 (app_wrk->detached_seg_managers, i); + break; + } + } + clib_spinlock_unlock (&app_wrk->detached_seg_managers_lock); +} + static void app_worker_stop_listen_session (app_worker_t * app_wrk, session_t * ls) { @@ -279,6 +312,13 @@ app_worker_stop_listen_session (app_worker_t * app_wrk, session_t * ls) segment_manager_app_detach (sm); if (!segment_manager_has_fifos (sm)) segment_manager_free (sm); + else + { + /* Track segment manager in case app detaches and all the + * outstanding sessions need to be closed */ + app_worker_add_detached_sm (app_wrk, *sm_indexp); + sm->flags |= SEG_MANAGER_F_DETACHED_LISTENER; + } } hash_unset (app_wrk->listeners_table, handle); diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c index 7734a3eef81..4c4f0b4b3cf 100644 --- a/src/vnet/session/segment_manager.c +++ b/src/vnet/session/segment_manager.c @@ -67,13 +67,13 @@ segment_manager_props_init (segment_manager_props_t * props) u8 segment_manager_app_detached (segment_manager_t * sm) { - return (sm->app_wrk_index == SEGMENT_MANAGER_INVALID_APP_INDEX); + return (sm->flags & SEG_MANAGER_F_DETACHED); } void segment_manager_app_detach (segment_manager_t * sm) { - sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX; + sm->flags |= SEG_MANAGER_F_DETACHED; } always_inline u32 @@ -425,6 +425,18 @@ segment_manager_init (segment_manager_t * sm) return 0; } +void +segment_manager_cleanup_detached_listener (segment_manager_t * sm) +{ + app_worker_t *app_wrk; + + app_wrk = app_worker_get_if_valid (sm->app_wrk_index); + if (!app_wrk) + return; + + app_worker_del_detached_sm (app_wrk, segment_manager_index (sm)); +} + /** * Cleanup segment manager. */ @@ -437,6 +449,9 @@ segment_manager_free (segment_manager_t * sm) ASSERT (!segment_manager_has_fifos (sm) && segment_manager_app_detached (sm)); + if (sm->flags & SEG_MANAGER_F_DETACHED_LISTENER) + segment_manager_cleanup_detached_listener (sm); + /* If we have empty preallocated segments that haven't been removed, remove * them now. Apart from that, the first segment in the first segment manager * is not removed when all fifos are removed. It can only be removed when diff --git a/src/vnet/session/segment_manager.h b/src/vnet/session/segment_manager.h index 1710b7b7697..1e6b14d2586 100644 --- a/src/vnet/session/segment_manager.h +++ b/src/vnet/session/segment_manager.h @@ -42,6 +42,12 @@ typedef struct _segment_manager_props u8 pct_first_alloc; /**< pct of fifo size to alloc */ } segment_manager_props_t; +typedef enum seg_manager_flag_ +{ + SEG_MANAGER_F_DETACHED = 1 << 0, + SEG_MANAGER_F_DETACHED_LISTENER = 1 << 1, +} seg_manager_flag_t; + typedef struct _segment_manager { /** Pool of segments allocated by this manager */ @@ -65,6 +71,8 @@ typedef struct _segment_manager */ svm_msg_q_t *event_queue; + u8 flags; + u32 max_fifo_size; u8 high_watermark; u8 low_watermark; -- cgit 1.2.3-korg