39 #define segment_manager_foreach_segment_w_lock(VAR, SM, BODY) \ 41 clib_rwlock_reader_lock (&(SM)->segments_rwlock); \ 42 pool_foreach((VAR), ((SM)->segments)) (BODY); \ 43 clib_rwlock_reader_unlock (&(SM)->segments_rwlock); \ 82 return (seg - sm->segments);
94 uword baseva = (
uword) ~ 0ULL, alloc_size, page_size;
95 u32 rnd_margin = 128 << 10, fs_index = ~0;
105 if (!props->add_segment && !segment_size)
108 return VNET_API_ERROR_INVALID_VALUE;
122 segment_size = segment_size ? segment_size : props->add_segment_size;
125 segment_size =
clib_max (segment_size + page_size - 1, segment_size);
126 segment_size = segment_size & ~(page_size - 1);
131 alloc_size = (
uword) segment_size + rnd_margin;
144 seg_name =
format (0,
"%v segment%c", app->
name, 0);
154 clib_warning (
"svm_master_init ('%v', %u) failed", seg_name,
172 fs_index = fs - sm->segments;
282 return (((
u64) segment_manager_index << 32) | segment_index);
288 u32 sm_index, segment_index;
349 sm->max_fifo_size = props->max_fifo_size ?
351 sm->max_fifo_size =
clib_max (sm->max_fifo_size, 4096);
354 props->high_watermark,
355 props->low_watermark);
367 uword first_seg_size;
373 first_seg_size =
clib_max (props->segment_size,
376 if (props->prealloc_fifos)
378 u64 approx_total_size, max_seg_size = ((
u64) 1 << 32) - (128 << 10);
379 u32 rx_rounded_data_size, tx_rounded_data_size;
380 u32 prealloc_fifo_pairs = props->prealloc_fifos;
381 u32 rx_fifo_size, tx_fifo_size, pair_size;
382 u32 approx_segment_count;
385 rx_rounded_data_size = (1 << (
max_log2 (props->rx_fifo_size)));
386 tx_rounded_data_size = (1 << (
max_log2 (props->tx_fifo_size)));
388 rx_fifo_size =
sizeof (
svm_fifo_t) + rx_rounded_data_size;
389 tx_fifo_size =
sizeof (
svm_fifo_t) + tx_rounded_data_size;
390 pair_size = rx_fifo_size + tx_fifo_size;
392 approx_total_size = (
u64) prealloc_fifo_pairs *pair_size;
393 if (first_seg_size > approx_total_size)
394 max_seg_size = first_seg_size;
395 approx_segment_count = (approx_total_size + (max_seg_size - 1))
399 for (i = 0; i < approx_segment_count + 1; i++)
415 &prealloc_fifo_pairs);
417 if (prealloc_fifo_pairs == 0)
433 if (props->prealloc_fifo_hdrs)
439 hdrs_per_slice = props->prealloc_fifo_hdrs / (fs->
n_slices -
i);
444 return VNET_API_ERROR_SVM_SEGMENT_CREATE_FAIL;
502 u32 sm_index = *(
u32 *) arg;
604 for (slice_index = 0; slice_index < fs->
n_slices; slice_index++)
616 f->master_thread_index);
641 u32 rx_fifo_size,
u32 tx_fifo_size,
683 int alloc_fail = 1, rv = 0, new_fs_index;
684 uword free_bytes, max_free_bytes = 0;
687 u32 sm_index, fs_index;
688 u8 added_a_segment = 0;
702 if (free_bytes > max_free_bytes)
704 max_free_bytes = free_bytes;
730 ASSERT (rx_fifo && tx_fifo);
733 (*tx_fifo)->segment_manager = sm_index;
734 (*rx_fifo)->segment_manager = sm_index;
735 (*tx_fifo)->segment_index = fs_index;
736 (*rx_fifo)->segment_index = fs_index;
753 if (props->add_segment)
757 clib_warning (
"Added a segment, still can't allocate a fifo");
759 return SESSION_E_SEG_NO_SPACE2;
764 return SESSION_E_SEG_CREATE;
776 SESSION_DBG (
"Can't add new seg and no space to allocate fifos!");
777 return SESSION_E_SEG_NO_SPACE;
788 if (!rx_fifo || !tx_fifo)
796 segment_index = rx_fifo->segment_index;
812 if (segment_index != 0 || !sm->first_is_protected)
851 u32 fifo_evt_size, notif_q_size, q_hdrs;
852 u32 msg_q_sz, fifo_evt_ring_sz, session_ntf_ring_sz;
854 fifo_evt_size = 1 <<
max_log2 (
sizeof (session_event_t));
855 notif_q_size =
clib_max (16, q_len >> 4);
858 fifo_evt_ring_sz = q_len * fifo_evt_size;
859 session_ntf_ring_sz = notif_q_size * 256;
862 return (msg_q_sz + fifo_evt_ring_sz + session_ntf_ring_sz + q_hdrs);
874 u32 fifo_evt_size, session_evt_size = 256, notif_q_size;
879 fifo_evt_size =
sizeof (session_event_t);
880 notif_q_size =
clib_max (16, props->evt_q_size >> 4);
883 {props->evt_q_size, fifo_evt_size, 0},
884 {notif_q_size, session_evt_size, 0}
897 if (props->use_mq_eventfd)
908 return sm->event_queue;
959 u8 show_segments = 0, verbose = 0;
971 else if (
unformat (input,
"verbose"))
982 "Index",
"AppIndex",
"Segments",
"MaxFifoSize",
983 "HighWater",
"LowWater",
"FifoTuning");
990 max_fifo_size = sm->max_fifo_size;
994 sm->app_wrk_index,
pool_elts (sm->segments),
996 sm->high_watermark, sm->low_watermark,
997 custom_logic ?
"custom" :
"none");
1022 .path =
"show segment-manager",
1023 .short_help =
"show segment-manager [segments][verbose]",
1043 "API Client",
"SegManager");
1056 for (slice_index = 0; slice_index < fs->
n_slices; slice_index++)
1061 u32 session_index, thread_index;
1064 session_index = f->master_session_index;
1065 thread_index = f->master_thread_index;
1067 session =
session_get (session_index, thread_index);
1071 s =
format (s,
"%-40v%-20v%-15u%-10u", str, app_name,
1074 s =
format (s,
"%-40v%-20v", str, app_name);
1092 u8 high_watermark,
u8 low_watermark)
1094 ASSERT (high_watermark <= 100 && low_watermark <= 100 &&
1095 low_watermark <= high_watermark);
1097 sm->high_watermark = high_watermark;
1098 sm->low_watermark = low_watermark;
u32 segment_manager_index(segment_manager_t *sm)
static void clib_rwlock_reader_lock(clib_rwlock_t *p)
fifo_segment_header_t * h
fifo segment data
void segment_manager_segment_reader_unlock(segment_manager_t *sm)
u32 default_max_fifo_size
default max fifo size
u64 segment_manager_segment_handle(segment_manager_t *sm, fifo_segment_t *segment)
static void sm_free_w_index_helper(void *arg)
svm_msg_q_t * segment_manager_alloc_queue(fifo_segment_t *segment, segment_manager_props_t *props)
Allocates shm queue in the first segment.
u8 * format_session(u8 *s, va_list *args)
Format stream session as per the following format.
static void clib_rwlock_writer_lock(clib_rwlock_t *p)
int segment_manager_add_segment(segment_manager_t *sm, uword segment_size)
Adds segment to segment manager's pool.
svm_fifo_t * fifo_segment_get_slice_fifo_list(fifo_segment_t *fs, u32 slice_index)
fifo_segment_t * segment_manager_get_segment(segment_manager_t *sm, u32 segment_index)
Reads a segment from the segment manager's pool without lock.
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
#define pool_foreach(VAR, POOL)
Iterate through pool.
u32 session_index
Index in thread pool where session was allocated.
static void segment_manager_free_safe(segment_manager_t *sm)
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
struct segment_manager_main_ segment_manager_main_t
svm_fifo_t * fifo_segment_alloc_fifo_w_slice(fifo_segment_t *fs, u32 slice_index, u32 data_bytes, fifo_segment_ftype_t ftype)
Allocate fifo in fifo segment.
int segment_manager_init_first(segment_manager_t *sm)
Initializes segment manager based on options provided.
static void clib_rwlock_free(clib_rwlock_t *p)
static session_t * session_get_if_valid(u64 si, u32 thread_index)
fifo_segment_t * segment_manager_get_segment_w_handle(u64 segment_handle)
__clib_export void clib_valloc_init(clib_valloc_main_t *vam, clib_valloc_chunk_t *template, int need_lock)
Initialize a virtual memory allocation arena.
void segment_manager_format_sessions(segment_manager_t *sm, int verbose)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
clib_valloc_main_t va_allocator
Virtual address allocator.
static segment_manager_main_t sm_main
void segment_manager_free(segment_manager_t *sm)
Cleanup segment manager.
ssvm_shared_header_t * sh
int app_worker_add_segment_notify(app_worker_t *app_wrk, u64 segment_handle)
Send an API message to the external app, to map new segment.
static void segment_manager_parse_segment_handle(u64 segment_handle, u32 *sm_index, u32 *segment_index)
static session_t * session_get(u32 si, u32 thread_index)
u8 default_low_watermark
default low watermark %
u32 connects_seg_manager
Segment manager used for outgoing connects issued by the app.
segment_manager_t * segment_managers
Pool of segment managers.
static_always_inline uword clib_mem_get_page_size(void)
u32 segment_manager_evt_q_expected_size(u32 q_len)
static u32 segment_manager_segment_index(segment_manager_t *sm, fifo_segment_t *seg)
void ssvm_delete(ssvm_private_t *ssvm)
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
void segment_manager_cleanup_detached_listener(segment_manager_t *sm)
static session_handle_t session_handle(session_t *s)
void segment_manager_segment_reader_lock(segment_manager_t *sm)
#define fifo_segment_flags(_fs)
void segment_manager_attach_fifo(segment_manager_t *sm, svm_fifo_t *f, session_t *s)
u64 segment_manager_make_segment_handle(u32 segment_manager_index, u32 segment_index)
int ssvm_server_init(ssvm_private_t *ssvm, ssvm_segment_type_t type)
svm_msg_q_t * svm_msg_q_alloc(svm_msg_q_cfg_t *cfg)
Allocate message queue.
void segment_manager_dealloc_fifos(svm_fifo_t *rx_fifo, svm_fifo_t *tx_fifo)
description fragment has unexpected format
static void * ssvm_push_heap(ssvm_shared_header_t *sh)
#define clib_error_return(e, args...)
u32 default_fifo_size
default rx/tx fifo size
static void ssvm_pop_heap(void *oldheap)
static heap_elt_t * first(heap_header_t *h)
void fifo_segment_preallocate_fifo_pairs(fifo_segment_t *fs, u32 rx_fifo_size, u32 tx_fifo_size, u32 *n_fifo_pairs)
Pre-allocates fifo pairs in fifo segment.
u32 seg_name_counter
Counter for segment names.
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
static void clib_rwlock_init(clib_rwlock_t *p)
static void clib_rwlock_reader_unlock(clib_rwlock_t *p)
void segment_manager_app_detach(segment_manager_t *sm)
u32 default_app_mq_size
default app msg q size
static session_t * session_get_from_handle(session_handle_t handle)
void segment_manager_del_segment(segment_manager_t *sm, fifo_segment_t *fs)
Remove segment without lock.
__clib_export uword clib_valloc_free(clib_valloc_main_t *vam, uword baseva)
Free virtual space.
void segment_manager_dealloc_queue(segment_manager_t *sm, svm_queue_t *q)
Frees shm queue allocated in the first segment.
const u8 * application_name_from_index(u32 app_index)
Returns app name for app-index.
#define pool_put(P, E)
Free an object E in pool P.
#define APP_INVALID_INDEX
void segment_manager_init_free(segment_manager_t *sm)
Initiate segment manager cleanup.
struct _segment_manager_props segment_manager_props_t
u8 segment_manager_has_fifos(segment_manager_t *sm)
uword size
size in bytes of this chunk
app_worker_t * app_worker_get_if_valid(u32 wrk_index)
void segment_manager_set_watermarks(segment_manager_t *sm, u8 high_watermark, u8 low_watermark)
void fifo_segment_detach_fifo(fifo_segment_t *fs, svm_fifo_t *f)
uword baseva
base VA for this chunk
#define SESSION_DBG(_fmt, _args...)
static void clib_rwlock_writer_unlock(clib_rwlock_t *p)
u32 n_rings
number of msg rings
svm_msg_q_t * segment_manager_event_queue(segment_manager_t *sm)
ssvm_private_t ssvm
ssvm segment data
static_always_inline uword vlib_get_thread_index(void)
segment_manager_t * segment_manager_alloc(void)
void segment_manager_detach_fifo(segment_manager_t *sm, svm_fifo_t *f)
sll srl srl sll sra u16x4 i
static void sm_lock_and_del_segment_inline(segment_manager_t *sm, u32 fs_index)
Removes segment after acquiring writer lock.
#define vec_free(V)
Free vector's memory (no header).
static segment_manager_props_t * segment_manager_properties_get(segment_manager_t *sm)
#define clib_warning(format, args...)
u8 segment_manager_app_detached(segment_manager_t *sm)
#define segment_manager_foreach_segment_w_lock(VAR, SM, BODY)
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
static u8 vlib_thread_is_main_w_barrier(void)
int segment_manager_alloc_session_fifos(segment_manager_t *sm, u32 thread_index, svm_fifo_t **rx_fifo, svm_fifo_t **tx_fifo)
application_t * application_get(u32 app_index)
int segment_manager_init(segment_manager_t *sm)
void svm_queue_free(svm_queue_t *q)
#define VLIB_CLI_COMMAND(x,...)
u8 n_slices
number of fifo segment slices
segment_manager_props_t * application_get_segment_manager_properties(u32 app_index)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
void app_worker_del_detached_sm(app_worker_t *app_wrk, u32 sm_index)
segment_manager_props_t * segment_manager_props_init(segment_manager_props_t *props)
void fifo_segment_free_fifo(fifo_segment_t *fs, svm_fifo_t *f)
Free fifo allocated in fifo segment.
u8 default_high_watermark
default high watermark %
fifo_segment_t * segment_manager_get_segment_w_lock(segment_manager_t *sm, u32 segment_index)
Reads a segment from the segment manager's pool and acquires reader lock.
void segment_manager_main_init(segment_manager_main_init_args_t *a)
session_cb_vft_t cb_fns
Callbacks: shoulder-taps for the server/client.
void segment_manager_lock_and_del_segment(segment_manager_t *sm, u32 fs_index)
svm_msg_q_ring_cfg_t * ring_cfgs
array of ring cfgs
static vlib_main_t * vlib_get_main(void)
u8 thread_index
Index of the thread that allocated the session.
int app_worker_del_segment_notify(app_worker_t *app_wrk, u64 segment_handle)
void segment_manager_segment_writer_unlock(segment_manager_t *sm)
app_worker_t * app_worker_get(u32 wrk_index)
u32 q_nitems
msg queue size (not rings)
void vlib_rpc_call_main_thread(void *callback, u8 *args, u32 arg_size)
u8 * name
Name registered by builtin apps.
static uword max_log2(uword x)
void session_close(session_t *s)
Initialize session closing procedure.
void segment_manager_del_sessions(segment_manager_t *sm)
Initiate disconnects for all sessions 'owned' by a segment manager.
struct _segment_manager segment_manager_t
u32 default_segment_size
default fifo segment size
segment_manager_t * segment_manager_get(u32 index)
int fifo_segment_prealloc_fifo_hdrs(fifo_segment_t *fs, u32 slice_index, u32 batch_size)
Try to preallocate fifo headers.
struct _svm_queue svm_queue_t
void fifo_segment_update_free_bytes(fifo_segment_t *fs)
Update fifo segment free bytes estimate.
u8 fifo_segment_has_fifos(fifo_segment_t *fs)
u32 app_index
Index of owning app.
int segment_manager_try_alloc_fifos(fifo_segment_t *fifo_segment, u32 thread_index, u32 rx_fifo_size, u32 tx_fifo_size, svm_fifo_t **rx_fifo, svm_fifo_t **tx_fifo)
static u32 vlib_num_workers()
int(* fifo_tuning_callback)(session_t *s, svm_fifo_t *f, session_ft_action_t act, u32 bytes)
Delegate fifo-tuning-logic to application.
#define vec_foreach(var, vec)
Vector iterator.
u32 app_wrk_index
Index of the app worker that owns the session.
static clib_error_t * segment_manager_show_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
__clib_export uword clib_valloc_alloc(clib_valloc_main_t *vam, uword size, int os_out_of_memory_on_failure)
Allocate virtual space.
void fifo_segment_attach_fifo(fifo_segment_t *fs, svm_fifo_t *f, u32 slice_index)
static fifo_segment_t * segment_manager_get_segment_if_valid(segment_manager_t *sm, u32 segment_index)
u32 api_client_index
API index for the worker.
uword fifo_segment_available_bytes(fifo_segment_t *fs)
int consumer_pid
pid of msg consumer
int svm_msg_q_alloc_producer_eventfd(svm_msg_q_t *mq)
Allocate event fd for queue consumer.
format_function_t format_fifo_segment
int fifo_segment_init(fifo_segment_t *fs)
Initialize fifo segment shared header.
struct _svm_fifo svm_fifo_t
segment_manager_t * segment_manager_get_if_valid(u32 index)
ssvm_segment_type_t ssvm_type(const ssvm_private_t *ssvm)
static uword pool_elts(void *v)
Number of active elements in a pool.