blob: c7a06d8b6367c93dd09d4df5e828a8c5876a4f9d [file] [log] [blame]
Florin Coras6cf30ad2017-04-04 23:08:23 -07001/*
Florin Coras288eaab2019-02-03 15:26:14 -08002 * Copyright (c) 2017-2019 Cisco and/or its affiliates.
Florin Coras6cf30ad2017-04-04 23:08:23 -07003 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/session/segment_manager.h>
17#include <vnet/session/session.h>
18#include <vnet/session/application.h>
19
Florin Coras88001c62019-04-24 14:44:46 -070020typedef struct segment_manager_main_
21{
22 segment_manager_t *segment_managers; /**< Pool of segment managers */
Florin Coras88001c62019-04-24 14:44:46 -070023 u32 seg_name_counter; /**< Counter for segment names */
Florin Corasa332c462018-01-31 06:52:17 -080024
Florin Coras88001c62019-04-24 14:44:46 -070025 /*
26 * Configuration
27 */
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +000028 u32 default_fifo_size; /**< default rx/tx fifo size */
29 u32 default_segment_size; /**< default fifo segment size */
30 u32 default_app_mq_size; /**< default app msg q size */
31 u32 default_max_fifo_size; /**< default max fifo size */
32 u8 default_high_watermark; /**< default high watermark % */
33 u8 default_low_watermark; /**< default low watermark % */
Florin Coras88001c62019-04-24 14:44:46 -070034} segment_manager_main_t;
Florin Corasa5464812017-04-19 13:00:05 -070035
Florin Coras88001c62019-04-24 14:44:46 -070036static segment_manager_main_t sm_main;
Florin Coras6cf30ad2017-04-04 23:08:23 -070037
Florin Coras88001c62019-04-24 14:44:46 -070038#define segment_manager_foreach_segment_w_lock(VAR, SM, BODY) \
39do { \
40 clib_rwlock_reader_lock (&(SM)->segments_rwlock); \
Damjan Marionb2c31b62020-12-13 21:47:40 +010041 pool_foreach((VAR), ((SM)->segments)) (BODY); \
Florin Coras88001c62019-04-24 14:44:46 -070042 clib_rwlock_reader_unlock (&(SM)->segments_rwlock); \
43} while (0)
44
45static segment_manager_props_t *
Florin Corasa332c462018-01-31 06:52:17 -080046segment_manager_properties_get (segment_manager_t * sm)
Florin Corasad0c77f2017-11-09 18:00:15 -080047{
Florin Corasab2f6db2018-08-31 14:31:41 -070048 app_worker_t *app_wrk = app_worker_get (sm->app_wrk_index);
49 return application_get_segment_manager_properties (app_wrk->app_index);
Florin Corasa332c462018-01-31 06:52:17 -080050}
51
Florin Coras88001c62019-04-24 14:44:46 -070052segment_manager_props_t *
53segment_manager_props_init (segment_manager_props_t * props)
Florin Corasa332c462018-01-31 06:52:17 -080054{
Florin Coras88001c62019-04-24 14:44:46 -070055 props->add_segment_size = sm_main.default_segment_size;
56 props->rx_fifo_size = sm_main.default_fifo_size;
57 props->tx_fifo_size = sm_main.default_fifo_size;
58 props->evt_q_size = sm_main.default_app_mq_size;
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +000059 props->max_fifo_size = sm_main.default_max_fifo_size;
Ryujiro Shibuya234fe892019-12-25 07:40:54 +000060 props->high_watermark = sm_main.default_high_watermark;
61 props->low_watermark = sm_main.default_low_watermark;
Florin Coras62ddc032019-12-08 18:30:42 -080062 props->n_slices = vlib_num_workers () + 1;
Florin Corasad0c77f2017-11-09 18:00:15 -080063 return props;
64}
65
Florin Corasbf395972020-04-30 15:05:24 +000066u8
Florin Coras9d063042017-09-14 03:08:00 -040067segment_manager_app_detached (segment_manager_t * sm)
68{
Florin Corasc8e812f2020-05-14 05:32:18 +000069 return (sm->flags & SEG_MANAGER_F_DETACHED);
Dave Wallace7b749fe2017-07-05 14:30:46 -040070}
71
Florin Coras4e4531e2017-11-06 23:27:56 -080072void
73segment_manager_app_detach (segment_manager_t * sm)
74{
Florin Corasc8e812f2020-05-14 05:32:18 +000075 sm->flags |= SEG_MANAGER_F_DETACHED;
Florin Coras4e4531e2017-11-06 23:27:56 -080076}
77
Florin Corasa332c462018-01-31 06:52:17 -080078always_inline u32
Florin Coras88001c62019-04-24 14:44:46 -070079segment_manager_segment_index (segment_manager_t * sm, fifo_segment_t * seg)
Florin Corasc87c91d2017-08-16 19:55:49 -070080{
Florin Corasa332c462018-01-31 06:52:17 -080081 return (seg - sm->segments);
82}
83
84/**
Florin Coras88001c62019-04-24 14:44:46 -070085 * Adds segment to segment manager's pool
86 *
87 * If needed a writer's lock is acquired before allocating a new segment
88 * to avoid affecting any of the segments pool readers.
89 */
Florin Coras6973c732021-06-17 15:53:38 -070090static inline int
91segment_manager_add_segment_inline (segment_manager_t *sm, uword segment_size,
92 u8 notify_app, u8 flags)
Florin Coras88001c62019-04-24 14:44:46 -070093{
94 segment_manager_main_t *smm = &sm_main;
Florin Coras88001c62019-04-24 14:44:46 -070095 segment_manager_props_t *props;
96 fifo_segment_t *fs;
Florin Coras9a45bd82020-12-28 16:28:07 -080097 u32 fs_index = ~0;
Florin Coras88001c62019-04-24 14:44:46 -070098 u8 *seg_name;
99 int rv;
100
101 props = segment_manager_properties_get (sm);
102
103 /* Not configured for addition of new segments and not first */
104 if (!props->add_segment && !segment_size)
105 {
106 clib_warning ("cannot allocate new segment");
107 return VNET_API_ERROR_INVALID_VALUE;
108 }
109
110 /*
Florin Corasf9d4ab42019-05-11 16:55:53 -0700111 * Allocate fifo segment and grab lock if needed
Florin Coras88001c62019-04-24 14:44:46 -0700112 */
113 if (vlib_num_workers ())
114 clib_rwlock_writer_lock (&sm->segments_rwlock);
115
116 pool_get_zero (sm->segments, fs);
117
118 /*
Florin Corasf9d4ab42019-05-11 16:55:53 -0700119 * Allocate ssvm segment
Florin Coras88001c62019-04-24 14:44:46 -0700120 */
121 segment_size = segment_size ? segment_size : props->add_segment_size;
Florin Coras9a45bd82020-12-28 16:28:07 -0800122 segment_size = round_pow2 (segment_size, clib_mem_get_page_size ());
Florin Corasf9d4ab42019-05-11 16:55:53 -0700123
Florin Coras88001c62019-04-24 14:44:46 -0700124 if (props->segment_type != SSVM_SEGMENT_PRIVATE)
125 {
126 seg_name = format (0, "%d-%d%c", getpid (), smm->seg_name_counter++, 0);
Florin Coras88001c62019-04-24 14:44:46 -0700127 }
128 else
Florin Coras2a7c0b62020-09-28 23:40:28 -0700129 {
130 app_worker_t *app_wrk = app_worker_get (sm->app_wrk_index);
131 application_t *app = application_get (app_wrk->app_index);
132 seg_name = format (0, "%v segment%c", app->name, 0);
133 }
Florin Coras88001c62019-04-24 14:44:46 -0700134
135 fs->ssvm.ssvm_size = segment_size;
136 fs->ssvm.name = seg_name;
Florin Coras9a45bd82020-12-28 16:28:07 -0800137 fs->ssvm.requested_va = 0;
Florin Coras88001c62019-04-24 14:44:46 -0700138
Florin Coras5220a262020-09-29 18:11:24 -0700139 if ((rv = ssvm_server_init (&fs->ssvm, props->segment_type)))
Florin Coras88001c62019-04-24 14:44:46 -0700140 {
141 clib_warning ("svm_master_init ('%v', %u) failed", seg_name,
142 segment_size);
Florin Coras88001c62019-04-24 14:44:46 -0700143 pool_put (sm->segments, fs);
144 goto done;
145 }
146
Florin Corasf9d4ab42019-05-11 16:55:53 -0700147 /*
148 * Initialize fifo segment
149 */
Florin Coras62ddc032019-12-08 18:30:42 -0800150 fs->n_slices = props->n_slices;
Florin Coras88001c62019-04-24 14:44:46 -0700151 fifo_segment_init (fs);
152
153 /*
154 * Save segment index before dropping lock, if any held
155 */
156 fs_index = fs - sm->segments;
157
Ryujiro Shibuya234fe892019-12-25 07:40:54 +0000158 /*
159 * Set watermarks in segment
160 */
161 fs->h->high_watermark = sm->high_watermark;
162 fs->h->low_watermark = sm->low_watermark;
Florin Coras2de9c0f2020-02-02 19:30:39 +0000163 fs->h->pct_first_alloc = props->pct_first_alloc;
Florin Coras6973c732021-06-17 15:53:38 -0700164 fs->h->flags = flags;
Ryujiro Shibuya234fe892019-12-25 07:40:54 +0000165 fs->h->flags &= ~FIFO_SEGMENT_F_MEM_LIMIT;
166
liuyacan9f299032021-04-25 20:11:30 +0800167 if (notify_app)
168 {
169 app_worker_t *app_wrk;
170 u64 fs_handle;
171 fs_handle = segment_manager_segment_handle (sm, fs);
172 app_wrk = app_worker_get (sm->app_wrk_index);
173 rv = app_worker_add_segment_notify (app_wrk, fs_handle);
174 if (rv)
175 return rv;
176 }
Florin Coras88001c62019-04-24 14:44:46 -0700177done:
178
179 if (vlib_num_workers ())
180 clib_rwlock_writer_unlock (&sm->segments_rwlock);
181
182 return fs_index;
183}
184
Florin Coras6973c732021-06-17 15:53:38 -0700185int
186segment_manager_add_segment (segment_manager_t *sm, uword segment_size,
187 u8 notify_app)
188{
189 return segment_manager_add_segment_inline (sm, segment_size, notify_app, 0);
190}
191
192int
193segment_manager_add_segment2 (segment_manager_t *sm, uword segment_size,
194 u8 flags)
195{
196 return segment_manager_add_segment_inline (sm, segment_size, 0, flags);
197}
198
Florin Coras88001c62019-04-24 14:44:46 -0700199/**
Florin Corasa332c462018-01-31 06:52:17 -0800200 * Remove segment without lock
201 */
Florin Corasf8f516a2018-02-08 15:10:09 -0800202void
Florin Coras88001c62019-04-24 14:44:46 -0700203segment_manager_del_segment (segment_manager_t * sm, fifo_segment_t * fs)
Florin Corasa332c462018-01-31 06:52:17 -0800204{
Florin Corasa332c462018-01-31 06:52:17 -0800205 if (ssvm_type (&fs->ssvm) != SSVM_SEGMENT_PRIVATE)
Florin Corasa0dbf9e2019-03-01 17:12:02 -0800206 {
Florin Corasea7e7082020-07-07 17:57:28 -0700207 if (!segment_manager_app_detached (sm))
Florin Corasa0dbf9e2019-03-01 17:12:02 -0800208 {
209 app_worker_t *app_wrk;
210 u64 segment_handle;
211 app_wrk = app_worker_get (sm->app_wrk_index);
212 segment_handle = segment_manager_segment_handle (sm, fs);
213 app_worker_del_segment_notify (app_wrk, segment_handle);
214 }
215 }
Florin Corasa332c462018-01-31 06:52:17 -0800216
Florin Corasc547e912020-12-08 17:50:45 -0800217 fifo_segment_cleanup (fs);
Florin Corasa332c462018-01-31 06:52:17 -0800218 ssvm_delete (&fs->ssvm);
219
220 if (CLIB_DEBUG)
Dave Barachb7b92992018-10-17 10:38:51 -0400221 clib_memset (fs, 0xfb, sizeof (*fs));
Florin Corasa332c462018-01-31 06:52:17 -0800222 pool_put (sm->segments, fs);
223}
224
Florin Coras57660d92020-04-04 22:45:34 +0000225static fifo_segment_t *
226segment_manager_get_segment_if_valid (segment_manager_t * sm,
227 u32 segment_index)
228{
229 if (pool_is_free_index (sm->segments, segment_index))
230 return 0;
231 return pool_elt_at_index (sm->segments, segment_index);
232}
233
Florin Corasa332c462018-01-31 06:52:17 -0800234/**
235 * Removes segment after acquiring writer lock
236 */
Florin Coras99368312018-08-02 10:45:44 -0700237static inline void
Florin Coras2d0e3de2020-10-23 16:31:40 -0700238sm_lock_and_del_segment_inline (segment_manager_t * sm, u32 fs_index)
Florin Corasa332c462018-01-31 06:52:17 -0800239{
Florin Coras88001c62019-04-24 14:44:46 -0700240 fifo_segment_t *fs;
Florin Corasa332c462018-01-31 06:52:17 -0800241 u8 is_prealloc;
242
243 clib_rwlock_writer_lock (&sm->segments_rwlock);
Florin Coras57660d92020-04-04 22:45:34 +0000244
245 fs = segment_manager_get_segment_if_valid (sm, fs_index);
246 if (!fs)
247 goto done;
248
Florin Coras88001c62019-04-24 14:44:46 -0700249 is_prealloc = fifo_segment_flags (fs) & FIFO_SEGMENT_F_IS_PREALLOCATED;
Florin Corasa332c462018-01-31 06:52:17 -0800250 if (is_prealloc && !segment_manager_app_detached (sm))
Florin Coras57660d92020-04-04 22:45:34 +0000251 goto done;
Florin Corasa332c462018-01-31 06:52:17 -0800252
253 segment_manager_del_segment (sm, fs);
Florin Coras57660d92020-04-04 22:45:34 +0000254
255done:
Florin Corasa332c462018-01-31 06:52:17 -0800256 clib_rwlock_writer_unlock (&sm->segments_rwlock);
257}
258
Florin Coras2d0e3de2020-10-23 16:31:40 -0700259void
260segment_manager_lock_and_del_segment (segment_manager_t * sm, u32 fs_index)
261{
262 sm_lock_and_del_segment_inline (sm, fs_index);
263}
264
Florin Corasa332c462018-01-31 06:52:17 -0800265/**
266 * Reads a segment from the segment manager's pool without lock
267 */
Florin Coras88001c62019-04-24 14:44:46 -0700268fifo_segment_t *
Florin Corasa332c462018-01-31 06:52:17 -0800269segment_manager_get_segment (segment_manager_t * sm, u32 segment_index)
270{
271 return pool_elt_at_index (sm->segments, segment_index);
272}
273
Florin Corasfa76a762018-11-29 12:40:10 -0800274u64
275segment_manager_segment_handle (segment_manager_t * sm,
Florin Coras88001c62019-04-24 14:44:46 -0700276 fifo_segment_t * segment)
Florin Corasfa76a762018-11-29 12:40:10 -0800277{
278 u32 segment_index = segment_manager_segment_index (sm, segment);
279 return (((u64) segment_manager_index (sm) << 32) | segment_index);
280}
281
Florin Coras88001c62019-04-24 14:44:46 -0700282u64
283segment_manager_make_segment_handle (u32 segment_manager_index,
284 u32 segment_index)
285{
286 return (((u64) segment_manager_index << 32) | segment_index);
287}
288
289fifo_segment_t *
Florin Corasfa76a762018-11-29 12:40:10 -0800290segment_manager_get_segment_w_handle (u64 segment_handle)
291{
292 u32 sm_index, segment_index;
293 segment_manager_t *sm;
294
295 segment_manager_parse_segment_handle (segment_handle, &sm_index,
296 &segment_index);
297 sm = segment_manager_get (sm_index);
298 if (!sm || pool_is_free_index (sm->segments, segment_index))
299 return 0;
300 return pool_elt_at_index (sm->segments, segment_index);
301}
302
Florin Corasa332c462018-01-31 06:52:17 -0800303/**
304 * Reads a segment from the segment manager's pool and acquires reader lock
305 *
306 * Caller must drop the reader's lock by calling
307 * @ref segment_manager_segment_reader_unlock once it finishes working with
308 * the segment.
309 */
Florin Coras88001c62019-04-24 14:44:46 -0700310fifo_segment_t *
Florin Corasa332c462018-01-31 06:52:17 -0800311segment_manager_get_segment_w_lock (segment_manager_t * sm, u32 segment_index)
312{
313 clib_rwlock_reader_lock (&sm->segments_rwlock);
314 return pool_elt_at_index (sm->segments, segment_index);
315}
316
317void
Florin Coras75ccf7b2020-03-05 19:44:02 +0000318segment_manager_segment_reader_lock (segment_manager_t * sm)
319{
320 clib_rwlock_reader_lock (&sm->segments_rwlock);
321}
322
323void
Florin Corasa332c462018-01-31 06:52:17 -0800324segment_manager_segment_reader_unlock (segment_manager_t * sm)
325{
326 clib_rwlock_reader_unlock (&sm->segments_rwlock);
327}
328
329void
330segment_manager_segment_writer_unlock (segment_manager_t * sm)
331{
332 clib_rwlock_writer_unlock (&sm->segments_rwlock);
333}
334
Florin Corasa332c462018-01-31 06:52:17 -0800335segment_manager_t *
Florin Coras88001c62019-04-24 14:44:46 -0700336segment_manager_alloc (void)
Florin Corasa332c462018-01-31 06:52:17 -0800337{
Florin Coras88001c62019-04-24 14:44:46 -0700338 segment_manager_main_t *smm = &sm_main;
Florin Corasa332c462018-01-31 06:52:17 -0800339 segment_manager_t *sm;
Florin Coras88001c62019-04-24 14:44:46 -0700340
341 pool_get_zero (smm->segment_managers, sm);
Florin Corasa332c462018-01-31 06:52:17 -0800342 clib_rwlock_init (&sm->segments_rwlock);
343 return sm;
344}
345
Florin Corasa332c462018-01-31 06:52:17 -0800346int
Ryujiro Shibuya234fe892019-12-25 07:40:54 +0000347segment_manager_init (segment_manager_t * sm)
Florin Corasa332c462018-01-31 06:52:17 -0800348{
Florin Coras88001c62019-04-24 14:44:46 -0700349 segment_manager_props_t *props;
Florin Corasa332c462018-01-31 06:52:17 -0800350
351 props = segment_manager_properties_get (sm);
Ryujiro Shibuya234fe892019-12-25 07:40:54 +0000352
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000353 sm->max_fifo_size = props->max_fifo_size ?
354 props->max_fifo_size : sm_main.default_max_fifo_size;
355 sm->max_fifo_size = clib_max (sm->max_fifo_size, 4096);
356
Ryujiro Shibuya234fe892019-12-25 07:40:54 +0000357 segment_manager_set_watermarks (sm,
358 props->high_watermark,
359 props->low_watermark);
Florin Corasa107f402020-09-29 19:18:46 -0700360 return 0;
361}
362
363/**
364 * Initializes segment manager based on options provided.
365 * Returns error if ssvm segment(s) allocation fails.
366 */
367int
368segment_manager_init_first (segment_manager_t * sm)
369{
370 segment_manager_props_t *props;
371 uword first_seg_size;
372 fifo_segment_t *fs;
373 int fs_index, i;
374
375 segment_manager_init (sm);
376 props = segment_manager_properties_get (sm);
377 first_seg_size = clib_max (props->segment_size,
378 sm_main.default_segment_size);
Florin Corasa332c462018-01-31 06:52:17 -0800379
Florin Coras9845c202020-04-28 01:54:22 +0000380 if (props->prealloc_fifos)
Florin Corasa332c462018-01-31 06:52:17 -0800381 {
Florin Coras9845c202020-04-28 01:54:22 +0000382 u64 approx_total_size, max_seg_size = ((u64) 1 << 32) - (128 << 10);
383 u32 rx_rounded_data_size, tx_rounded_data_size;
384 u32 prealloc_fifo_pairs = props->prealloc_fifos;
385 u32 rx_fifo_size, tx_fifo_size, pair_size;
386 u32 approx_segment_count;
387
Florin Corasa332c462018-01-31 06:52:17 -0800388 /* Figure out how many segments should be preallocated */
389 rx_rounded_data_size = (1 << (max_log2 (props->rx_fifo_size)));
390 tx_rounded_data_size = (1 << (max_log2 (props->tx_fifo_size)));
391
392 rx_fifo_size = sizeof (svm_fifo_t) + rx_rounded_data_size;
393 tx_fifo_size = sizeof (svm_fifo_t) + tx_rounded_data_size;
394 pair_size = rx_fifo_size + tx_fifo_size;
395
396 approx_total_size = (u64) prealloc_fifo_pairs *pair_size;
397 if (first_seg_size > approx_total_size)
398 max_seg_size = first_seg_size;
399 approx_segment_count = (approx_total_size + (max_seg_size - 1))
400 / max_seg_size;
401
402 /* Allocate the segments */
403 for (i = 0; i < approx_segment_count + 1; i++)
404 {
liuyacan9f299032021-04-25 20:11:30 +0800405 fs_index = segment_manager_add_segment (sm, max_seg_size, 0);
Florin Coras9845c202020-04-28 01:54:22 +0000406 if (fs_index < 0)
Florin Corasa332c462018-01-31 06:52:17 -0800407 {
408 clib_warning ("Failed to preallocate segment %d", i);
Florin Coras9845c202020-04-28 01:54:22 +0000409 return fs_index;
Florin Corasa332c462018-01-31 06:52:17 -0800410 }
411
Florin Coras9845c202020-04-28 01:54:22 +0000412 fs = segment_manager_get_segment (sm, fs_index);
Florin Corasf8f516a2018-02-08 15:10:09 -0800413 if (i == 0)
Florin Coras9845c202020-04-28 01:54:22 +0000414 sm->event_queue = segment_manager_alloc_queue (fs, props);
Florin Corasf8f516a2018-02-08 15:10:09 -0800415
Florin Coras9845c202020-04-28 01:54:22 +0000416 fifo_segment_preallocate_fifo_pairs (fs,
Florin Coras88001c62019-04-24 14:44:46 -0700417 props->rx_fifo_size,
418 props->tx_fifo_size,
419 &prealloc_fifo_pairs);
Florin Coras9845c202020-04-28 01:54:22 +0000420 fifo_segment_flags (fs) = FIFO_SEGMENT_F_IS_PREALLOCATED;
Florin Corasa332c462018-01-31 06:52:17 -0800421 if (prealloc_fifo_pairs == 0)
422 break;
423 }
Florin Coras9845c202020-04-28 01:54:22 +0000424 return 0;
Florin Corasa332c462018-01-31 06:52:17 -0800425 }
Florin Coras9845c202020-04-28 01:54:22 +0000426
liuyacan9f299032021-04-25 20:11:30 +0800427 fs_index = segment_manager_add_segment (sm, first_seg_size, 0);
Florin Coras9845c202020-04-28 01:54:22 +0000428 if (fs_index < 0)
Florin Corasa332c462018-01-31 06:52:17 -0800429 {
Florin Coras9845c202020-04-28 01:54:22 +0000430 clib_warning ("Failed to allocate segment");
431 return fs_index;
432 }
433
434 fs = segment_manager_get_segment (sm, fs_index);
435 sm->event_queue = segment_manager_alloc_queue (fs, props);
436
437 if (props->prealloc_fifo_hdrs)
438 {
439 u32 hdrs_per_slice;
440
441 /* Do not preallocate on slice associated to main thread */
442 i = (vlib_num_workers ()? 1 : 0);
443 hdrs_per_slice = props->prealloc_fifo_hdrs / (fs->n_slices - i);
444
445 for (; i < fs->n_slices; i++)
Florin Corasa332c462018-01-31 06:52:17 -0800446 {
Florin Coras9845c202020-04-28 01:54:22 +0000447 if (fifo_segment_prealloc_fifo_hdrs (fs, i, hdrs_per_slice))
448 return VNET_API_ERROR_SVM_SEGMENT_CREATE_FAIL;
Florin Corasa332c462018-01-31 06:52:17 -0800449 }
Florin Corasa332c462018-01-31 06:52:17 -0800450 }
451
452 return 0;
453}
454
Florin Corasc8e812f2020-05-14 05:32:18 +0000455void
456segment_manager_cleanup_detached_listener (segment_manager_t * sm)
457{
458 app_worker_t *app_wrk;
459
460 app_wrk = app_worker_get_if_valid (sm->app_wrk_index);
461 if (!app_wrk)
462 return;
463
464 app_worker_del_detached_sm (app_wrk, segment_manager_index (sm));
465}
466
Florin Corasc87c91d2017-08-16 19:55:49 -0700467/**
Florin Coras88001c62019-04-24 14:44:46 -0700468 * Cleanup segment manager.
Florin Coras6cf30ad2017-04-04 23:08:23 -0700469 */
470void
Florin Coras88001c62019-04-24 14:44:46 -0700471segment_manager_free (segment_manager_t * sm)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700472{
Florin Coras88001c62019-04-24 14:44:46 -0700473 segment_manager_main_t *smm = &sm_main;
474 fifo_segment_t *fifo_segment;
Dave Wallace7b749fe2017-07-05 14:30:46 -0400475
Florin Coras506aa3c2020-12-13 21:09:59 -0800476 ASSERT (vlib_get_thread_index () == 0
477 && !segment_manager_has_fifos (sm)
Florin Coras9d063042017-09-14 03:08:00 -0400478 && segment_manager_app_detached (sm));
479
Florin Corasc8e812f2020-05-14 05:32:18 +0000480 if (sm->flags & SEG_MANAGER_F_DETACHED_LISTENER)
481 segment_manager_cleanup_detached_listener (sm);
482
Florin Coras9d063042017-09-14 03:08:00 -0400483 /* If we have empty preallocated segments that haven't been removed, remove
484 * them now. Apart from that, the first segment in the first segment manager
485 * is not removed when all fifos are removed. It can only be removed when
486 * the manager is explicitly deleted/detached by the app. */
Florin Corasa332c462018-01-31 06:52:17 -0800487 clib_rwlock_writer_lock (&sm->segments_rwlock);
488
489 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100490 pool_foreach (fifo_segment, sm->segments) {
Florin Corasa332c462018-01-31 06:52:17 -0800491 segment_manager_del_segment (sm, fifo_segment);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100492 }
Florin Corasa332c462018-01-31 06:52:17 -0800493 /* *INDENT-ON* */
494
Florin Corasf1af21c2021-02-26 19:19:11 -0800495 pool_free (sm->segments);
Florin Corasa332c462018-01-31 06:52:17 -0800496 clib_rwlock_writer_unlock (&sm->segments_rwlock);
497
498 clib_rwlock_free (&sm->segments_rwlock);
Florin Corasc87c91d2017-08-16 19:55:49 -0700499 if (CLIB_DEBUG)
Dave Barachb7b92992018-10-17 10:38:51 -0400500 clib_memset (sm, 0xfe, sizeof (*sm));
Florin Corasa332c462018-01-31 06:52:17 -0800501 pool_put (smm->segment_managers, sm);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700502}
503
Florin Coras506aa3c2020-12-13 21:09:59 -0800504static void
505sm_free_w_index_helper (void *arg)
506{
507 u32 sm_index = *(u32 *) arg;
508 segment_manager_t *sm;
509
510 ASSERT (vlib_get_thread_index () == 0);
511
512 if ((sm = segment_manager_get_if_valid (sm_index)))
513 segment_manager_free (sm);
514}
515
Florin Corasda78c5a2021-06-09 14:55:24 -0700516void
517segment_manager_free_safe (segment_manager_t *sm)
Florin Coras506aa3c2020-12-13 21:09:59 -0800518{
519 if (!vlib_thread_is_main_w_barrier ())
520 {
521 u32 sm_index = segment_manager_index (sm);
522 vlib_rpc_call_main_thread (sm_free_w_index_helper, (u8 *) & sm_index,
523 sizeof (sm_index));
524 }
525 else
526 {
527 segment_manager_free (sm);
528 }
529}
530
Florin Corasc87c91d2017-08-16 19:55:49 -0700531void
Florin Coras88001c62019-04-24 14:44:46 -0700532segment_manager_init_free (segment_manager_t * sm)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700533{
Florin Coras506aa3c2020-12-13 21:09:59 -0800534 ASSERT (vlib_get_thread_index () == 0);
535
Florin Coras4e4531e2017-11-06 23:27:56 -0800536 segment_manager_app_detach (sm);
Florin Corasc87c91d2017-08-16 19:55:49 -0700537 if (segment_manager_has_fifos (sm))
538 segment_manager_del_sessions (sm);
539 else
540 {
Florin Coras9d063042017-09-14 03:08:00 -0400541 ASSERT (!sm->first_is_protected || segment_manager_app_detached (sm));
Florin Coras88001c62019-04-24 14:44:46 -0700542 segment_manager_free (sm);
Florin Corasc87c91d2017-08-16 19:55:49 -0700543 }
Florin Coras6cf30ad2017-04-04 23:08:23 -0700544}
545
Florin Coras88001c62019-04-24 14:44:46 -0700546segment_manager_t *
547segment_manager_get (u32 index)
548{
549 return pool_elt_at_index (sm_main.segment_managers, index);
550}
551
552segment_manager_t *
553segment_manager_get_if_valid (u32 index)
554{
555 if (pool_is_free_index (sm_main.segment_managers, index))
556 return 0;
557 return pool_elt_at_index (sm_main.segment_managers, index);
558}
559
560u32
561segment_manager_index (segment_manager_t * sm)
562{
563 return sm - sm_main.segment_managers;
564}
565
566u8
567segment_manager_has_fifos (segment_manager_t * sm)
568{
569 fifo_segment_t *seg;
570 u8 first = 1;
571
572 /* *INDENT-OFF* */
573 segment_manager_foreach_segment_w_lock (seg, sm, ({
574 if (CLIB_DEBUG && !first && !fifo_segment_has_fifos (seg)
575 && !(fifo_segment_flags (seg) & FIFO_SEGMENT_F_IS_PREALLOCATED))
576 {
577 clib_warning ("segment %d has no fifos!",
578 segment_manager_segment_index (sm, seg));
579 first = 0;
580 }
581 if (fifo_segment_has_fifos (seg))
582 {
583 segment_manager_segment_reader_unlock (sm);
584 return 1;
585 }
586 }));
587 /* *INDENT-ON* */
588
589 return 0;
590}
591
592/**
593 * Initiate disconnects for all sessions 'owned' by a segment manager
594 */
595void
596segment_manager_del_sessions (segment_manager_t * sm)
597{
Florin Coras88001c62019-04-24 14:44:46 -0700598 session_handle_t *handles = 0, *handle;
Florin Coras62ddc032019-12-08 18:30:42 -0800599 fifo_segment_t *fs;
Florin Coras88001c62019-04-24 14:44:46 -0700600 session_t *session;
Florin Coras62ddc032019-12-08 18:30:42 -0800601 int slice_index;
602 svm_fifo_t *f;
Florin Coras88001c62019-04-24 14:44:46 -0700603
604 ASSERT (pool_elts (sm->segments) != 0);
605
606 /* Across all fifo segments used by the server */
607 /* *INDENT-OFF* */
Florin Coras62ddc032019-12-08 18:30:42 -0800608 segment_manager_foreach_segment_w_lock (fs, sm, ({
609 for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
Florin Coras88001c62019-04-24 14:44:46 -0700610 {
Florin Coras62ddc032019-12-08 18:30:42 -0800611 f = fifo_segment_get_slice_fifo_list (fs, slice_index);
612
613 /*
614 * Remove any residual sessions from the session lookup table
615 * Don't bother deleting the individual fifos, we're going to
616 * throw away the fifo segment in a minute.
617 */
618 while (f)
619 {
Florin Corasc547e912020-12-08 17:50:45 -0800620 session = session_get_if_valid (f->shr->master_session_index,
621 f->master_thread_index);
622 if (session)
623 vec_add1 (handles, session_handle (session));
624 f = f->next;
625 }
Florin Coras88001c62019-04-24 14:44:46 -0700626 }
627
628 /* Instead of removing the segment, test when cleaning up disconnected
629 * sessions if the segment can be removed.
630 */
631 }));
632 /* *INDENT-ON* */
633
634 vec_foreach (handle, handles)
Florin Coras77ea42b2020-04-14 23:52:12 +0000635 {
636 session = session_get_from_handle (*handle);
637 session_close (session);
638 /* Avoid propagating notifications back to the app */
639 session->app_wrk_index = APP_INVALID_INDEX;
640 }
Florin Corasf1af21c2021-02-26 19:19:11 -0800641 vec_free (handles);
Florin Coras88001c62019-04-24 14:44:46 -0700642}
643
liuyacan87d48ad2021-04-28 11:34:03 +0000644/**
645 * Initiate disconnects for sessions in specified state 'owned' by a segment
646 * manager
647 */
648void
649segment_manager_del_sessions_filter (segment_manager_t *sm,
650 session_state_t *states)
651{
652 session_handle_t *handles = 0, *handle;
653 fifo_segment_t *fs;
654 session_t *session;
655 int slice_index;
656 svm_fifo_t *f;
657
658 ASSERT (pool_elts (sm->segments) != 0);
659
660 /* Across all fifo segments used by the server */
661 segment_manager_foreach_segment_w_lock (
662 fs, sm, ({
663 for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
664 {
665 f = fifo_segment_get_slice_fifo_list (fs, slice_index);
666 while (f)
667 {
668 session = session_get_if_valid (f->shr->master_session_index,
669 f->master_thread_index);
670 if (session)
671 {
672 session_state_t *state;
673 vec_foreach (state, states)
674 {
675 if (session->session_state == *state)
676 {
677 vec_add1 (handles, session_handle (session));
678 break;
679 }
680 }
681 }
682 f = f->next;
683 }
684 }
685 }));
686
687 vec_foreach (handle, handles)
688 {
689 session = session_get_from_handle (*handle);
690 session_close (session);
691 /* Avoid propagating notifications back to the app */
692 session->app_wrk_index = APP_INVALID_INDEX;
693 }
694 vec_free (handles);
695}
696
Florin Corasf8f516a2018-02-08 15:10:09 -0800697int
Florin Coras88001c62019-04-24 14:44:46 -0700698segment_manager_try_alloc_fifos (fifo_segment_t * fifo_segment,
Florin Coras62ddc032019-12-08 18:30:42 -0800699 u32 thread_index,
Florin Corasf8f516a2018-02-08 15:10:09 -0800700 u32 rx_fifo_size, u32 tx_fifo_size,
701 svm_fifo_t ** rx_fifo, svm_fifo_t ** tx_fifo)
Florin Corasa332c462018-01-31 06:52:17 -0800702{
Florin Coras88001c62019-04-24 14:44:46 -0700703 rx_fifo_size = clib_max (rx_fifo_size, sm_main.default_fifo_size);
Florin Coras62ddc032019-12-08 18:30:42 -0800704 *rx_fifo = fifo_segment_alloc_fifo_w_slice (fifo_segment, thread_index,
705 rx_fifo_size,
706 FIFO_SEGMENT_RX_FIFO);
Florin Corasa332c462018-01-31 06:52:17 -0800707
Florin Coras88001c62019-04-24 14:44:46 -0700708 tx_fifo_size = clib_max (tx_fifo_size, sm_main.default_fifo_size);
Florin Coras62ddc032019-12-08 18:30:42 -0800709 *tx_fifo = fifo_segment_alloc_fifo_w_slice (fifo_segment, thread_index,
710 tx_fifo_size,
711 FIFO_SEGMENT_TX_FIFO);
Florin Corasa332c462018-01-31 06:52:17 -0800712
713 if (*rx_fifo == 0)
714 {
715 /* This would be very odd, but handle it... */
716 if (*tx_fifo != 0)
717 {
Florin Coras88001c62019-04-24 14:44:46 -0700718 fifo_segment_free_fifo (fifo_segment, *tx_fifo);
Florin Corasa332c462018-01-31 06:52:17 -0800719 *tx_fifo = 0;
720 }
721 return -1;
722 }
723 if (*tx_fifo == 0)
724 {
725 if (*rx_fifo != 0)
726 {
Florin Coras88001c62019-04-24 14:44:46 -0700727 fifo_segment_free_fifo (fifo_segment, *rx_fifo);
Florin Corasa332c462018-01-31 06:52:17 -0800728 *rx_fifo = 0;
729 }
730 return -1;
731 }
732
733 return 0;
734}
735
Florin Coras6cf30ad2017-04-04 23:08:23 -0700736int
737segment_manager_alloc_session_fifos (segment_manager_t * sm,
Florin Coras62ddc032019-12-08 18:30:42 -0800738 u32 thread_index,
Florin Corasb384b542018-01-15 01:08:33 -0800739 svm_fifo_t ** rx_fifo,
Florin Coras1219b2d2019-04-23 15:53:43 -0700740 svm_fifo_t ** tx_fifo)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700741{
Florin Corasa332c462018-01-31 06:52:17 -0800742 int alloc_fail = 1, rv = 0, new_fs_index;
Florin Coras75ccf7b2020-03-05 19:44:02 +0000743 uword free_bytes, max_free_bytes = 0;
Florin Coras88001c62019-04-24 14:44:46 -0700744 segment_manager_props_t *props;
Florin Coras75ccf7b2020-03-05 19:44:02 +0000745 fifo_segment_t *fs = 0, *cur;
Florin Coras88001c62019-04-24 14:44:46 -0700746 u32 sm_index, fs_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700747
Florin Corasa332c462018-01-31 06:52:17 -0800748 props = segment_manager_properties_get (sm);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700749
Florin Corasa332c462018-01-31 06:52:17 -0800750 /*
751 * Find the first free segment to allocate the fifos in
752 */
Florin Coras75ccf7b2020-03-05 19:44:02 +0000753
754 segment_manager_segment_reader_lock (sm);
755
Damjan Marionb2c31b62020-12-13 21:47:40 +0100756 pool_foreach (cur, sm->segments) {
Florin Corasda78c5a2021-06-09 14:55:24 -0700757 if (fifo_segment_flags (cur) & FIFO_SEGMENT_F_CUSTOM_USE)
758 continue;
759 free_bytes = fifo_segment_available_bytes (cur);
760 if (free_bytes > max_free_bytes)
761 {
762 max_free_bytes = free_bytes;
763 fs = cur;
764 }
Damjan Marionb2c31b62020-12-13 21:47:40 +0100765 }
Florin Corasa5464812017-04-19 13:00:05 -0700766
Ryujiro Shibuya234fe892019-12-25 07:40:54 +0000767 if (fs)
768 {
Ryujiro Shibuya234fe892019-12-25 07:40:54 +0000769 alloc_fail = segment_manager_try_alloc_fifos (fs, thread_index,
770 props->rx_fifo_size,
771 props->tx_fifo_size,
772 rx_fifo, tx_fifo);
773 /* On success, keep lock until fifos are initialized */
774 if (!alloc_fail)
775 goto alloc_success;
Florin Coras75ccf7b2020-03-05 19:44:02 +0000776 }
Ryujiro Shibuya234fe892019-12-25 07:40:54 +0000777
Florin Coras75ccf7b2020-03-05 19:44:02 +0000778 segment_manager_segment_reader_unlock (sm);
Florin Corasa332c462018-01-31 06:52:17 -0800779
Florin Corasa332c462018-01-31 06:52:17 -0800780 /*
781 * Allocation failed, see if we can add a new segment
782 */
783 if (props->add_segment)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700784 {
liuyacan9f299032021-04-25 20:11:30 +0800785 if ((new_fs_index = segment_manager_add_segment (sm, 0, 1)) < 0)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700786 {
Florin Corasa332c462018-01-31 06:52:17 -0800787 clib_warning ("Failed to add new segment");
Florin Coras00e01d32019-10-21 16:07:46 -0700788 return SESSION_E_SEG_CREATE;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700789 }
Florin Coras88001c62019-04-24 14:44:46 -0700790 fs = segment_manager_get_segment_w_lock (sm, new_fs_index);
Florin Coras62ddc032019-12-08 18:30:42 -0800791 alloc_fail = segment_manager_try_alloc_fifos (fs, thread_index,
792 props->rx_fifo_size,
Florin Corasf8f516a2018-02-08 15:10:09 -0800793 props->tx_fifo_size,
794 rx_fifo, tx_fifo);
liuyacan9f299032021-04-25 20:11:30 +0800795 if (alloc_fail)
796 {
797 clib_warning ("Added a segment, still can't allocate a fifo");
798 segment_manager_segment_reader_unlock (sm);
799 return SESSION_E_SEG_NO_SPACE2;
800 }
Florin Coras6cf30ad2017-04-04 23:08:23 -0700801 }
Florin Corasa332c462018-01-31 06:52:17 -0800802 else
803 {
Florin Coras47cb2482020-07-13 08:52:53 -0700804 SESSION_DBG ("Can't add new seg and no space to allocate fifos!");
Florin Coras00e01d32019-10-21 16:07:46 -0700805 return SESSION_E_SEG_NO_SPACE;
Florin Corasa332c462018-01-31 06:52:17 -0800806 }
liuyacan9f299032021-04-25 20:11:30 +0800807
808alloc_success:
809 ASSERT (rx_fifo && tx_fifo);
810
811 sm_index = segment_manager_index (sm);
812 fs_index = segment_manager_segment_index (sm, fs);
813 (*tx_fifo)->segment_manager = sm_index;
814 (*rx_fifo)->segment_manager = sm_index;
815 (*tx_fifo)->segment_index = fs_index;
816 (*rx_fifo)->segment_index = fs_index;
817
818 /* Drop the lock after app is notified */
819 segment_manager_segment_reader_unlock (sm);
820
821 return rv;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700822}
823
824void
Florin Coras19223e02019-03-03 14:56:05 -0800825segment_manager_dealloc_fifos (svm_fifo_t * rx_fifo, svm_fifo_t * tx_fifo)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700826{
Florin Corasa332c462018-01-31 06:52:17 -0800827 segment_manager_t *sm;
Florin Corasb095a3c2019-04-25 12:58:46 -0700828 fifo_segment_t *fs;
Florin Coras19223e02019-03-03 14:56:05 -0800829 u32 segment_index;
Florin Corasa5464812017-04-19 13:00:05 -0700830
Florin Coras58a93e82019-01-14 23:33:46 -0800831 if (!rx_fifo || !tx_fifo)
832 return;
833
Florin Corasa5464812017-04-19 13:00:05 -0700834 /* It's possible to have no segment manager if the session was removed
Florin Corasc87c91d2017-08-16 19:55:49 -0700835 * as result of a detach. */
Florin Corasa332c462018-01-31 06:52:17 -0800836 if (!(sm = segment_manager_get_if_valid (rx_fifo->segment_manager)))
Florin Corasa5464812017-04-19 13:00:05 -0700837 return;
838
Florin Coras19223e02019-03-03 14:56:05 -0800839 segment_index = rx_fifo->segment_index;
Florin Coras88001c62019-04-24 14:44:46 -0700840 fs = segment_manager_get_segment_w_lock (sm, segment_index);
841 fifo_segment_free_fifo (fs, rx_fifo);
842 fifo_segment_free_fifo (fs, tx_fifo);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700843
Florin Corasc87c91d2017-08-16 19:55:49 -0700844 /*
845 * Try to remove svm segment if it has no fifos. This can be done only if
846 * the segment is not the first in the segment manager or if it is first
847 * and it is not protected. Moreover, if the segment is first and the app
848 * has detached from the segment manager, remove the segment manager.
849 */
Florin Coras88001c62019-04-24 14:44:46 -0700850 if (!fifo_segment_has_fifos (fs))
Florin Coras6cf30ad2017-04-04 23:08:23 -0700851 {
Florin Corasa332c462018-01-31 06:52:17 -0800852 segment_manager_segment_reader_unlock (sm);
Florin Corasc87c91d2017-08-16 19:55:49 -0700853
854 /* Remove segment if it holds no fifos or first but not protected */
Florin Corasa332c462018-01-31 06:52:17 -0800855 if (segment_index != 0 || !sm->first_is_protected)
Florin Coras2d0e3de2020-10-23 16:31:40 -0700856 sm_lock_and_del_segment_inline (sm, segment_index);
Florin Corasc87c91d2017-08-16 19:55:49 -0700857
858 /* Remove segment manager if no sessions and detached from app */
Florin Coras9d063042017-09-14 03:08:00 -0400859 if (segment_manager_app_detached (sm)
860 && !segment_manager_has_fifos (sm))
Florin Coras506aa3c2020-12-13 21:09:59 -0800861 segment_manager_free_safe (sm);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700862 }
Florin Corasa332c462018-01-31 06:52:17 -0800863 else
864 segment_manager_segment_reader_unlock (sm);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700865}
866
Florin Coras6d7552c2020-04-09 01:49:45 +0000867void
Florin Coras0bc78d82021-01-09 14:34:01 -0800868segment_manager_detach_fifo (segment_manager_t *sm, svm_fifo_t **f)
Florin Coras6d7552c2020-04-09 01:49:45 +0000869{
870 fifo_segment_t *fs;
871
Florin Coras0bc78d82021-01-09 14:34:01 -0800872 fs = segment_manager_get_segment_w_lock (sm, (*f)->segment_index);
Florin Coras6d7552c2020-04-09 01:49:45 +0000873 fifo_segment_detach_fifo (fs, f);
874 segment_manager_segment_reader_unlock (sm);
875}
876
877void
Florin Coras0bc78d82021-01-09 14:34:01 -0800878segment_manager_attach_fifo (segment_manager_t *sm, svm_fifo_t **f,
879 session_t *s)
Florin Coras6d7552c2020-04-09 01:49:45 +0000880{
881 fifo_segment_t *fs;
882
Florin Coras0bc78d82021-01-09 14:34:01 -0800883 fs = segment_manager_get_segment_w_lock (sm, (*f)->segment_index);
Florin Coras6d7552c2020-04-09 01:49:45 +0000884 fifo_segment_attach_fifo (fs, f, s->thread_index);
885 segment_manager_segment_reader_unlock (sm);
886
Florin Coras0bc78d82021-01-09 14:34:01 -0800887 (*f)->shr->master_session_index = s->session_index;
888 (*f)->master_thread_index = s->thread_index;
Florin Coras6d7552c2020-04-09 01:49:45 +0000889}
890
Florin Coras3c2fed52018-07-04 04:15:05 -0700891u32
892segment_manager_evt_q_expected_size (u32 q_len)
893{
894 u32 fifo_evt_size, notif_q_size, q_hdrs;
895 u32 msg_q_sz, fifo_evt_ring_sz, session_ntf_ring_sz;
896
Florin Coras52207f12018-07-12 14:48:06 -0700897 fifo_evt_size = 1 << max_log2 (sizeof (session_event_t));
Florin Coras3c2fed52018-07-04 04:15:05 -0700898 notif_q_size = clib_max (16, q_len >> 4);
899
900 msg_q_sz = q_len * sizeof (svm_msg_q_msg_t);
901 fifo_evt_ring_sz = q_len * fifo_evt_size;
902 session_ntf_ring_sz = notif_q_size * 256;
903 q_hdrs = sizeof (svm_queue_t) + sizeof (svm_msg_q_t);
904
905 return (msg_q_sz + fifo_evt_ring_sz + session_ntf_ring_sz + q_hdrs);
906}
907
Florin Corasa5464812017-04-19 13:00:05 -0700908/**
909 * Allocates shm queue in the first segment
Florin Corasa332c462018-01-31 06:52:17 -0800910 *
911 * Must be called with lock held
Florin Corasa5464812017-04-19 13:00:05 -0700912 */
Florin Coras3c2fed52018-07-04 04:15:05 -0700913svm_msg_q_t *
Florin Coras88001c62019-04-24 14:44:46 -0700914segment_manager_alloc_queue (fifo_segment_t * segment,
915 segment_manager_props_t * props)
Florin Corasa5464812017-04-19 13:00:05 -0700916{
Florin Coras3c2fed52018-07-04 04:15:05 -0700917 u32 fifo_evt_size, session_evt_size = 256, notif_q_size;
918 svm_msg_q_cfg_t _cfg, *cfg = &_cfg;
919 svm_msg_q_t *q;
Florin Corasa5464812017-04-19 13:00:05 -0700920
Florin Coras52207f12018-07-12 14:48:06 -0700921 fifo_evt_size = sizeof (session_event_t);
Florin Coras99368312018-08-02 10:45:44 -0700922 notif_q_size = clib_max (16, props->evt_q_size >> 4);
Florin Coras3c2fed52018-07-04 04:15:05 -0700923 /* *INDENT-OFF* */
924 svm_msg_q_ring_cfg_t rc[SESSION_MQ_N_RINGS] = {
Florin Coras99368312018-08-02 10:45:44 -0700925 {props->evt_q_size, fifo_evt_size, 0},
Florin Coras3c2fed52018-07-04 04:15:05 -0700926 {notif_q_size, session_evt_size, 0}
927 };
928 /* *INDENT-ON* */
929 cfg->consumer_pid = 0;
930 cfg->n_rings = 2;
Florin Coras99368312018-08-02 10:45:44 -0700931 cfg->q_nitems = props->evt_q_size;
Florin Coras3c2fed52018-07-04 04:15:05 -0700932 cfg->ring_cfgs = rc;
Florin Corasa5464812017-04-19 13:00:05 -0700933
Florin Corasb4624182020-12-11 13:58:12 -0800934 q = fifo_segment_msg_q_alloc (segment, 0, cfg);
Florin Coras99368312018-08-02 10:45:44 -0700935
936 if (props->use_mq_eventfd)
937 {
Florin Coras86f12322021-01-22 15:05:14 -0800938 if (svm_msg_q_alloc_eventfd (q))
Florin Coras99368312018-08-02 10:45:44 -0700939 clib_warning ("failed to alloc eventfd");
940 }
Florin Corasa5464812017-04-19 13:00:05 -0700941 return q;
942}
943
Florin Coras88001c62019-04-24 14:44:46 -0700944svm_msg_q_t *
945segment_manager_event_queue (segment_manager_t * sm)
946{
947 return sm->event_queue;
948}
949
Florin Corasa5464812017-04-19 13:00:05 -0700950/**
951 * Frees shm queue allocated in the first segment
952 */
953void
Florin Corase86a8ed2018-01-05 03:20:25 -0800954segment_manager_dealloc_queue (segment_manager_t * sm, svm_queue_t * q)
Florin Corasa5464812017-04-19 13:00:05 -0700955{
Florin Coras88001c62019-04-24 14:44:46 -0700956 fifo_segment_t *segment;
Florin Corasa332c462018-01-31 06:52:17 -0800957 ssvm_shared_header_t *sh;
Florin Corasa5464812017-04-19 13:00:05 -0700958 void *oldheap;
959
Florin Corasa332c462018-01-31 06:52:17 -0800960 ASSERT (!pool_is_free_index (sm->segments, 0));
Florin Corasa5464812017-04-19 13:00:05 -0700961
Florin Corasa332c462018-01-31 06:52:17 -0800962 segment = segment_manager_get_segment_w_lock (sm, 0);
Florin Corasa5464812017-04-19 13:00:05 -0700963 sh = segment->ssvm.sh;
964
965 oldheap = ssvm_push_heap (sh);
Florin Corase86a8ed2018-01-05 03:20:25 -0800966 svm_queue_free (q);
Florin Corasa5464812017-04-19 13:00:05 -0700967 ssvm_pop_heap (oldheap);
Florin Corasa332c462018-01-31 06:52:17 -0800968 segment_manager_segment_reader_unlock (sm);
969}
970
971/*
972 * Init segment vm address allocator
973 */
974void
Florin Coras9a45bd82020-12-28 16:28:07 -0800975segment_manager_main_init (void)
Florin Corasa332c462018-01-31 06:52:17 -0800976{
Florin Coras88001c62019-04-24 14:44:46 -0700977 segment_manager_main_t *sm = &sm_main;
Florin Coras88001c62019-04-24 14:44:46 -0700978
979 sm->default_fifo_size = 1 << 12;
980 sm->default_segment_size = 1 << 20;
981 sm->default_app_mq_size = 128;
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000982 sm->default_max_fifo_size = 4 << 20;
Ryujiro Shibuya234fe892019-12-25 07:40:54 +0000983 sm->default_high_watermark = 80;
984 sm->default_low_watermark = 50;
Florin Corasa5464812017-04-19 13:00:05 -0700985}
986
Florin Corasc87c91d2017-08-16 19:55:49 -0700987static clib_error_t *
988segment_manager_show_fn (vlib_main_t * vm, unformat_input_t * input,
989 vlib_cli_command_t * cmd)
990{
Florin Coras88001c62019-04-24 14:44:46 -0700991 segment_manager_main_t *smm = &sm_main;
Florin Corasb384b542018-01-15 01:08:33 -0800992 u8 show_segments = 0, verbose = 0;
Ryujiro Shibuya65c30ce2020-03-26 07:29:09 +0000993 uword max_fifo_size;
Florin Coras5368bb02019-06-09 09:24:33 -0700994 segment_manager_t *sm;
995 fifo_segment_t *seg;
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000996 app_worker_t *app_wrk;
997 application_t *app;
998 u8 custom_logic;
Dave Barach91f3e742017-09-01 19:12:11 -0400999
Florin Corasc87c91d2017-08-16 19:55:49 -07001000 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1001 {
1002 if (unformat (input, "segments"))
1003 show_segments = 1;
1004 else if (unformat (input, "verbose"))
1005 verbose = 1;
1006 else
1007 return clib_error_return (0, "unknown input `%U'",
1008 format_unformat_error, input);
1009 }
1010 vlib_cli_output (vm, "%d segment managers allocated",
Florin Corasa332c462018-01-31 06:52:17 -08001011 pool_elts (smm->segment_managers));
1012 if (verbose && pool_elts (smm->segment_managers))
Florin Corasc87c91d2017-08-16 19:55:49 -07001013 {
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +00001014 vlib_cli_output (vm, "%-6s%=10s%=10s%=13s%=11s%=11s%=12s",
1015 "Index", "AppIndex", "Segments", "MaxFifoSize",
1016 "HighWater", "LowWater", "FifoTuning");
Florin Corasc87c91d2017-08-16 19:55:49 -07001017
1018 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +01001019 pool_foreach (sm, smm->segment_managers) {
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +00001020 app_wrk = app_worker_get_if_valid (sm->app_wrk_index);
1021 app = app_wrk ? application_get (app_wrk->app_index) : 0;
1022 custom_logic = (app && (app->cb_fns.fifo_tuning_callback)) ? 1 : 0;
Ryujiro Shibuya65c30ce2020-03-26 07:29:09 +00001023 max_fifo_size = sm->max_fifo_size;
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +00001024
1025 vlib_cli_output (vm, "%-6d%=10d%=10d%=13U%=11d%=11d%=12s",
1026 segment_manager_index (sm),
1027 sm->app_wrk_index, pool_elts (sm->segments),
Ryujiro Shibuya65c30ce2020-03-26 07:29:09 +00001028 format_memory_size, max_fifo_size,
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +00001029 sm->high_watermark, sm->low_watermark,
1030 custom_logic ? "custom" : "none");
Damjan Marionb2c31b62020-12-13 21:47:40 +01001031 }
Florin Corasc87c91d2017-08-16 19:55:49 -07001032 /* *INDENT-ON* */
1033
Florin Coras2a7c0b62020-09-28 23:40:28 -07001034 vlib_cli_output (vm, "\n");
Florin Corasc87c91d2017-08-16 19:55:49 -07001035 }
1036 if (show_segments)
1037 {
Florin Coras5368bb02019-06-09 09:24:33 -07001038 vlib_cli_output (vm, "%U", format_fifo_segment, 0, verbose);
Florin Corasc87c91d2017-08-16 19:55:49 -07001039
1040 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +01001041 pool_foreach (sm, smm->segment_managers) {
Florin Corasa332c462018-01-31 06:52:17 -08001042 segment_manager_foreach_segment_w_lock (seg, sm, ({
Florin Coras5368bb02019-06-09 09:24:33 -07001043 vlib_cli_output (vm, "%U", format_fifo_segment, seg, verbose);
Florin Corasa332c462018-01-31 06:52:17 -08001044 }));
Damjan Marionb2c31b62020-12-13 21:47:40 +01001045 }
Florin Corasc87c91d2017-08-16 19:55:49 -07001046 /* *INDENT-ON* */
1047
1048 }
1049 return 0;
1050}
1051
Florin Corasad0c77f2017-11-09 18:00:15 -08001052/* *INDENT-OFF* */
Florin Corasc87c91d2017-08-16 19:55:49 -07001053VLIB_CLI_COMMAND (segment_manager_show_command, static) =
1054{
1055 .path = "show segment-manager",
Dave Barach91f3e742017-09-01 19:12:11 -04001056 .short_help = "show segment-manager [segments][verbose]",
Florin Corasc87c91d2017-08-16 19:55:49 -07001057 .function = segment_manager_show_fn,
1058};
1059/* *INDENT-ON* */
1060
Florin Coras88001c62019-04-24 14:44:46 -07001061void
1062segment_manager_format_sessions (segment_manager_t * sm, int verbose)
1063{
Florin Coras88001c62019-04-24 14:44:46 -07001064 vlib_main_t *vm = vlib_get_main ();
1065 app_worker_t *app_wrk;
Florin Coras62ddc032019-12-08 18:30:42 -08001066 fifo_segment_t *fs;
Florin Coras88001c62019-04-24 14:44:46 -07001067 const u8 *app_name;
Florin Coras62ddc032019-12-08 18:30:42 -08001068 int slice_index;
1069 u8 *s = 0, *str;
1070 svm_fifo_t *f;
Florin Coras88001c62019-04-24 14:44:46 -07001071
1072 if (!sm)
1073 {
1074 if (verbose)
Xiaoming Jiang806709f2021-06-23 09:07:57 +00001075 vlib_cli_output (vm, "%-" SESSION_CLI_ID_LEN "s%-20s%-15s%-10s",
1076 "Connection", "App", "API Client", "SegManager");
Florin Coras88001c62019-04-24 14:44:46 -07001077 else
Xiaoming Jiang806709f2021-06-23 09:07:57 +00001078 vlib_cli_output (vm, "%-" SESSION_CLI_ID_LEN "s%-20s", "Connection",
1079 "App");
Florin Coras88001c62019-04-24 14:44:46 -07001080 return;
1081 }
1082
1083 app_wrk = app_worker_get (sm->app_wrk_index);
1084 app_name = application_name_from_index (app_wrk->app_index);
1085
1086 clib_rwlock_reader_lock (&sm->segments_rwlock);
1087
1088 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +01001089 pool_foreach (fs, sm->segments) {
Florin Coras62ddc032019-12-08 18:30:42 -08001090 for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
Florin Coras88001c62019-04-24 14:44:46 -07001091 {
Florin Coras62ddc032019-12-08 18:30:42 -08001092 f = fifo_segment_get_slice_fifo_list (fs, slice_index);
1093 while (f)
1094 {
1095 u32 session_index, thread_index;
1096 session_t *session;
Florin Coras88001c62019-04-24 14:44:46 -07001097
Florin Corasc547e912020-12-08 17:50:45 -08001098 session_index = f->shr->master_session_index;
1099 thread_index = f->master_thread_index;
Florin Coras88001c62019-04-24 14:44:46 -07001100
Florin Corasc547e912020-12-08 17:50:45 -08001101 session = session_get (session_index, thread_index);
1102 str = format (0, "%U", format_session, session, verbose);
Florin Coras88001c62019-04-24 14:44:46 -07001103
Florin Corasc547e912020-12-08 17:50:45 -08001104 if (verbose)
Xiaoming Jiang806709f2021-06-23 09:07:57 +00001105 s = format (s, "%-" SESSION_CLI_ID_LEN "v%-20v%-15u%-10u", str,
1106 app_name, app_wrk->api_client_index,
Florin Corasc547e912020-12-08 17:50:45 -08001107 app_wrk->connects_seg_manager);
1108 else
Xiaoming Jiang806709f2021-06-23 09:07:57 +00001109 s = format (s, "%-" SESSION_CLI_ID_LEN "v%-20v", str, app_name);
Florin Coras88001c62019-04-24 14:44:46 -07001110
Florin Corasc547e912020-12-08 17:50:45 -08001111 vlib_cli_output (vm, "%v", s);
1112 vec_reset_length (s);
1113 vec_free (str);
Florin Coras88001c62019-04-24 14:44:46 -07001114
Florin Corasc547e912020-12-08 17:50:45 -08001115 f = f->next;
1116 }
1117 vec_free (s);
Florin Coras88001c62019-04-24 14:44:46 -07001118 }
Damjan Marionb2c31b62020-12-13 21:47:40 +01001119 }
Florin Coras88001c62019-04-24 14:44:46 -07001120 /* *INDENT-ON* */
1121
1122 clib_rwlock_reader_unlock (&sm->segments_rwlock);
1123}
1124
Ryujiro Shibuya234fe892019-12-25 07:40:54 +00001125void
1126segment_manager_set_watermarks (segment_manager_t * sm,
1127 u8 high_watermark, u8 low_watermark)
1128{
Florin Coras8c79a4e2020-02-25 22:28:27 +00001129 ASSERT (high_watermark <= 100 && low_watermark <= 100 &&
Ryujiro Shibuya234fe892019-12-25 07:40:54 +00001130 low_watermark <= high_watermark);
1131
1132 sm->high_watermark = high_watermark;
1133 sm->low_watermark = low_watermark;
1134}
1135
Florin Coras6cf30ad2017-04-04 23:08:23 -07001136/*
1137 * fd.io coding-style-patch-verification: ON
1138 *
1139 * Local Variables:
1140 * eval: (c-set-style "gnu")
1141 * End:
1142 */