24 #include <sys/types.h> 39 #define TRACE_VLIB_MEMORY_QUEUE 0 48 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) 56 vl_print(handle,
"vl_api_memclnt_create_t:\n");
67 vl_print(handle,
"vl_api_memclnt_delete_t:\n");
79 __attribute__((weak));
87 clib_warning (
"need to link against -lvlibsocket, msg not sent!");
100 __attribute__((weak));
151 pthread_mutex_lock (&svm->
mutex);
156 memset(regp, 0,
sizeof(*regp));
166 pthread_mutex_unlock(&svm->
mutex);
170 rp->_vl_msg_id = ntohs(VL_API_MEMCLNT_CREATE_REPLY);
183 __attribute__((weak));
199 u32 handle, client_index, epoch;
211 (
"Stale clnt delete index %d old epoch %d cur epoch %d",
226 rp->_vl_msg_id = ntohs(VL_API_MEMCLNT_DELETE_REPLY);
245 pthread_mutex_lock (&svm->
mutex);
248 memset (regp, 0xF1,
sizeof (*regp));
250 pthread_mutex_unlock(&svm->
mutex);
265 u16 first_msg_id = ~0;
275 strncpy ((
char *)name, (
char *) mp->
name,
ARRAY_LEN(name)-1);
289 rmp->_vl_msg_id = ntohs(VL_API_GET_FIRST_MSG_ID_REPLY);
296 #define foreach_vlib_api_msg \ 297 _(MEMCLNT_CREATE, memclnt_create) \ 298 _(MEMCLNT_DELETE, memclnt_delete) \ 299 _(GET_FIRST_MSG_ID, get_first_msg_id) 313 #define _(N,n) do { \ 314 c->id = VL_API_##N; \ 316 c->handler = vl_api_##n##_t_handler; \ 317 c->cleanup = vl_noop_handler; \ 318 c->endian = vl_api_##n##_t_endian; \ 319 c->print = vl_api_##n##_t_print; \ 320 c->size = sizeof(vl_api_##n##_t); \ 323 vl_msg_api_config(c);} while (0); 331 #define foreach_histogram_bucket \ 338 #define _(n) SLEEP_##n##_US, 359 f64 dead_client_scan_time;
360 f64 sleep_time, start_time;
366 clib_warning(
"memory_api_init returned %d, wait for godot...", rv);
385 uword event_type __attribute__((unused));
402 pthread_mutex_lock (&q->mutex);
403 if (q->cursize == 0) {
405 pthread_mutex_unlock (&q->mutex);
410 .format =
"q-underflow: len %d",
413 struct {
u32 len; } * ed;
421 headp = (
i8 *) (q->data +
sizeof(
uword)*q->head);
425 need_broadcast = (q->cursize == q->maxsize/2);
430 pthread_mutex_unlock(&q->mutex);
432 (
void) pthread_cond_broadcast(&q->condvar);
438 int index = SLEEP_400_US;
439 if (vector_rate > 40.0)
441 else if (vector_rate > 20.0) {
442 index = SLEEP_200_US;
444 }
else if (vector_rate >= 1.0) {
445 index = SLEEP_100_US;
452 vector_rate_histogram[index] += 1;
465 static u32 * dead_indices;
466 static u32 * confused_indices;
476 q = regp->vl_input_queue;
477 if (kill (q->consumer_pid, 0) < 0) {
478 vec_add1(dead_indices, regpp - am->vl_clients);
481 clib_warning (
"NULL client registration index %d",
482 regpp - am->vl_clients);
483 vec_add1 (confused_indices, regpp - am->vl_clients);
489 for (i = 0; i <
vec_len (confused_indices); i++) {
500 for (i = 0; i <
vec_len(dead_indices); i++) {
512 pthread_mutex_lock (&svm->
mutex);
515 for (i = 0; i <
vec_len(dead_indices); i++) {
519 memset (*regpp, 0xF3,
sizeof (**regpp));
533 pthread_mutex_unlock(&svm->
mutex);
535 for (i = 0; i <
vec_len (dead_indices); i++)
545 .format =
"q-awake: len %d",
548 struct {
u32 len; } * ed;
550 ed->len = q->cursize;
562 u64 total_counts = 0;
569 if (total_counts == 0) {
577 percent = ((f64) vector_rate_histogram[SLEEP_##n##_US]) \ 578 / (f64) total_counts; \ 580 vlib_cli_output (vm, "Sleep %3d us: %llu, %.2f%%",n, \ 581 vector_rate_histogram[SLEEP_##n##_US], \ 591 .path =
"show api histogram",
592 .short_help =
"show api histogram",
609 .path =
"clear api histogram",
610 .short_help =
"clear api histogram",
618 .name =
"api-rx-from-ring",
619 .state = VLIB_NODE_STATE_DISABLED,
625 static volatile int * cursizep;
639 cursizep = &q->cursize;
655 ? VLIB_NODE_STATE_POLLING
656 : VLIB_NODE_STATE_DISABLED));
667 static u8 * long_msg;
673 while (n_left_from > 0) {
688 _vec_len (long_msg) = 0;
689 vec_add (long_msg, msg, msg_len);
694 vec_add (long_msg, msg, msg_len);
711 .name =
"api-rx-from-node",
736 if (shmem_hdr == 0) {
742 "Owner",
"Size",
"Nitems",
"Hits",
"Misses");
770 __attribute__((weak));
785 u32 * confused_indices = 0;
791 "Name",
"PID",
"Queue Length",
"Queue VA",
"Health");
798 q = regp->vl_input_queue;
799 if (kill (q->consumer_pid, 0) < 0) {
804 vlib_cli_output (vm,
"%16s %8d %14d 0x%016llx %s\n",
805 regp->name, q->consumer_pid, q->cursize,
808 clib_warning (
"NULL client registration index %d",
809 regpp - am->vl_clients);
810 vec_add1 (confused_indices, regpp - am->vl_clients);
817 for (i = 0; i <
vec_len (confused_indices); i++) {
834 .short_help =
"Show API information",
838 .path =
"show api ring-stats",
839 .short_help =
"Message ring statistics",
844 .path =
"show api clients",
845 .short_help =
"Client information",
885 .path =
"show api message-table",
886 .short_help =
"Message Table",
898 static u8 *msg_buf=0;
899 void (*endian_fp)(
void *);
900 u8 *(*print_fp)(
void *,
void *);
920 fp = fopen ((
char *)filename,
"r");
929 if (fread(tp,
sizeof(*tp), 1, fp) != 1) {
940 for (i = 0; i <=
last; i++) {
942 if (fread(&msg_id,
sizeof(
u16), 1, fp) != 1) {
945 msg_id = ntohs(msg_id);
947 fseek(fp, -2, SEEK_CUR);
959 if (fread(msg_buf, size, 1, fp) != 1) {
970 (*endian_fp)(msg_buf);
977 (*print_fp)(msg_buf, vm);
996 if (
unformat (input,
"rx nitems %u", &nitems)
999 else if (
unformat (input,
"tx nitems %u", &nitems)
1003 }
else if (
unformat (input,
"on rx")) {
1005 }
else if (
unformat (input,
"on tx")) {
1007 }
else if (
unformat (input,
"on")) {
1009 }
else if (
unformat (input,
"off")) {
1012 }
else if (
unformat (input,
"free")) {
1017 }
else if (
unformat (input,
"print %s from %d to %d", &filename,
1019 ||
unformat (input,
"print %s", &filename)) {
1021 }
else if (
unformat (input,
"debug on")) {
1023 }
else if (
unformat (input,
"debug off")) {
1047 .path =
"set api-trace",
1048 .short_help =
"API trace",
1072 int len0, len1, clen;
1076 clen = len0 < len1 ? len0 : len1;
1077 return (strncmp ((
char *) a0->
name, (
char *)a1->
name, clen));
1085 s =
format (s,
"%-20s%9s%9s",
"Name",
"First-ID",
"Last-ID");
1114 for (i = 0; i <
vec_len (rp); i++)
1121 .path =
"show api plugin",
1122 .short_help =
"show api plugin",
1158 rmp->_vl_msg_id = ntohs (VL_API_RPC_REPLY);
1180 memset (mp, 0,
sizeof (*mp));
1182 mp->_vl_msg_id = ntohs (VL_API_RPC_CALL);
1190 #define foreach_rpc_api_msg \ 1191 _(RPC_CALL,rpc_call) \ 1192 _(RPC_REPLY,rpc_reply) 1198 vl_msg_api_set_handlers(VL_API_##N, #n, \ 1199 vl_api_##n##_t_handler, \ 1202 vl_api_##n##_t_print, \ 1203 sizeof(vl_api_##n##_t), 0 ); #define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
#define TRACE_VLIB_MEMORY_QUEUE
#define vl_print(handle,...)
sll srl srl sll sra u16x4 i
void vl_api_memclnt_delete_t_handler(vl_api_memclnt_delete_t *mp)
static void svm_pop_heap(void *oldheap)
always_inline uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
static void(BVT(clib_bihash)*h, BVT(clib_bihash_value)*v)
static clib_error_t * setup_memclnt_exit(vlib_main_t *vm)
always_inline void clib_mem_free(void *p)
unix_shared_memory_queue_t * vl_input_queue
vlib_node_registration_t api_rx_from_node_node
(constructor) VLIB_REGISTER_NODE (api_rx_from_node_node)
static clib_error_t * vl_api_client_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
static clib_error_t * vl_api_message_table_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
static clib_error_t * vl_api_show_plugin_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
always_inline void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
ring_alloc_t * client_rings
static clib_error_t * vl_api_clear_histogram_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
void vl_msg_api_send(vl_api_registration_t *rp, u8 *elem)
#define pool_is_free(P, E)
#define clib_error_report(e)
always_inline uword vlib_process_suspend(vlib_main_t *vm, f64 dt)
void vl_api_get_first_msg_id_t_handler(vl_api_get_first_msg_id_t *mp)
int vl_api_memclnt_delete_callback(u32 client_index)
void vl_enable_disable_memory_api(vlib_main_t *vm, int enable)
trace_cfg_t * api_trace_cfg
always_inline vlib_main_t * vlib_get_main(void)
vlib_cli_command_t cli_show_api_clients_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_clients_command)
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
void vl_set_memory_region_name(char *name)
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
_vlib_init_function_list_elt_t * api_init_function_registrations
#define pool_foreach(VAR, POOL, BODY)
static int range_compare(vl_api_msg_range_t *a0, vl_api_msg_range_t *a1)
always_inline heap_elt_t * last(heap_header_t *h)
#define VLIB_INIT_FUNCTION(x)
void vl_unmap_shmem(void)
static void * svm_push_data_heap(svm_region_t *rp)
void vl_msg_api_free(void *)
vl_api_registration_t ** vl_clients
vlib_cli_command_t cli_show_api_message_table_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_message_table_command)
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
always_inline void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
always_inline uword pool_elts(void *v)
#define clib_warning(format, args...)
struct vl_shmem_hdr_ * shmem_hdr
static void * vl_api_memclnt_create_t_print(vl_api_memclnt_create_t *a, void *handle)
void vl_socket_api_send(vl_api_registration_t *rp, u8 *elem)
static uword pointer_to_uword(const void *p)
static void memclnt_queue_callback(vlib_main_t *vm)
#define VLIB_BUFFER_NEXT_PRESENT
always_inline heap_elt_t * first(heap_header_t *h)
vl_shmem_hdr_t * shmem_hdr
int vl_msg_api_trace_free(api_main_t *am, vl_api_trace_which_t which)
vl_registration_type_t registration_type
#define pool_elt_at_index(p, i)
#define foreach_rpc_api_msg
void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
vlib_node_registration_t memclnt_node
(constructor) VLIB_REGISTER_NODE (memclnt_node)
static clib_error_t * vl_api_ring_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
u16 current_length
Nbytes between current data and the end of this buffer.
void(** msg_print_handlers)(void *, void *)
vlib_cli_command_t cli_show_api_ring_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_ring_command)
#define vec_dup(V)
Return copy of vector (no header, no alignment)
always_inline f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
always_inline f64 vlib_last_vector_length_per_node(vlib_main_t *vm)
static void vl_api_rpc_call_t_handler(vl_api_rpc_call_t *mp)
static u32 vl_msg_api_handle_get_index(u32 index)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
#define foreach_vlib_api_msg
void vl_msg_api_handler_with_vm_node(api_main_t *am, void *the_msg, vlib_main_t *vm, vlib_node_runtime_t *node)
always_inline void * vlib_frame_args(vlib_frame_t *f)
volatile u32 queue_signal_pending
#define uword_to_pointer(u, type)
#define clib_arch_is_big_endian
int vl_msg_api_trace_onoff(api_main_t *am, vl_api_trace_which_t which, int onoff)
void * vl_msg_api_alloc(int nbytes)
always_inline void * clib_mem_alloc(uword size)
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
#define vec_free(V)
Free vector's memory (no header).
unix_shared_memory_queue_t * vl_input_queue
vl_api_msg_range_t * msg_ranges
#define clib_memcpy(a, b, c)
#define foreach_histogram_bucket
#define ELOG_TYPE_DECLARE(f)
void svm_region_init_chroot_uid_gid(char *root_path, int uid, int gid)
always_inline void vlib_set_queue_signal_callback(vlib_main_t *vm, void(*fp)(vlib_main_t *))
vlib_cli_command_t cli_show_api_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_command)
static clib_error_t * vl_api_trace_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
#define VLIB_CLI_COMMAND(x,...)
void vl_msg_api_handler_no_trace_no_free(void *the_msg)
static uword api_rx_from_node(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
vlib_cli_command_t cli_show_api_plugin_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_plugin_command)
#define pool_put_index(p, i)
#define VL_API_EPOCH_MASK
void vlib_worker_thread_barrier_sync(vlib_main_t *vm)
clib_error_t * vlibmemory_init(vlib_main_t *vm)
int vl_msg_api_version_check(vl_api_memclnt_create_t *mp)
static u64 vector_rate_histogram[SLEEP_N_BUCKETS]
static uword memclnt_process(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *f)
clib_error_t * vlib_call_init_exit_functions(vlib_main_t *vm, _vlib_init_function_list_elt_t *head, int call_once)
VLIB_API_INIT_FUNCTION(rpc_api_hookup)
u32 next_buffer
Next buffer for this linked-list of buffers.
void dump_socket_clients(vlib_main_t *vm, api_main_t *am)
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
static u8 * format_api_msg_range(u8 *s, va_list *args)
static clib_error_t * rpc_api_hookup(vlib_main_t *vm)
static void vl_api_rpc_reply_t_handler(vl_api_rpc_reply_t *mp)
void vl_api_memclnt_create_t_handler(vl_api_memclnt_create_t *mp)
void(** msg_endian_handlers)(void *)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
int vl_map_shmem(char *region_name, int is_vlib)
u32 vl_api_registration_pool_index
void svm_client_scan_this_region_nolock(svm_region_t *rp)
static clib_error_t * vl_api_show_histogram_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
volatile u32 api_queue_nonempty
#define hash_get_mem(h, key)
void(** msg_handlers)(void *)
#define VLIB_REGISTER_NODE(x,...)
always_inline f64 vlib_time_now(vlib_main_t *vm)
static int memory_api_init(char *region_name)
static void * vl_api_memclnt_delete_t_print(vl_api_memclnt_delete_t *a, void *handle)
void * vl_msg_api_alloc_as_if_client(int nbytes)
#define clib_error_return(e, args...)
static u32 vl_msg_api_handle_get_epoch(u32 index)
#define CLIB_CACHE_LINE_BYTES
int vl_msg_api_trace_configure(api_main_t *am, vl_api_trace_which_t which, u32 nitems)
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
uword * msg_range_by_name
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
static u32 vl_msg_api_handle_from_index_and_epoch(u32 index, u32 epoch)
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
struct _unix_shared_memory_queue unix_shared_memory_queue_t
void vl_api_trace_print_file_cmd(vlib_main_t *vm, u32 first, u32 last, u8 *filename)