diff options
Diffstat (limited to 'src/vlibmemory')
-rw-r--r-- | src/vlibmemory/CMakeLists.txt | 16 | ||||
-rw-r--r-- | src/vlibmemory/api.h | 1 | ||||
-rw-r--r-- | src/vlibmemory/memclnt.api | 39 | ||||
-rw-r--r-- | src/vlibmemory/memclnt_api.c | 111 | ||||
-rw-r--r-- | src/vlibmemory/memory_api.c | 266 | ||||
-rw-r--r-- | src/vlibmemory/memory_api.h | 2 | ||||
-rw-r--r-- | src/vlibmemory/memory_client.c | 78 | ||||
-rw-r--r-- | src/vlibmemory/memory_client.h | 3 | ||||
-rw-r--r-- | src/vlibmemory/memory_shared.c | 818 | ||||
-rw-r--r-- | src/vlibmemory/memory_shared.h | 147 | ||||
-rw-r--r-- | src/vlibmemory/socket_api.c | 51 | ||||
-rw-r--r-- | src/vlibmemory/socket_client.c | 91 | ||||
-rw-r--r-- | src/vlibmemory/socket_client.h | 3 | ||||
-rw-r--r-- | src/vlibmemory/vlib_api.c | 5 | ||||
-rw-r--r-- | src/vlibmemory/vlib_api_cli.c | 234 | ||||
-rw-r--r-- | src/vlibmemory/vlibapi_test.c | 2 |
16 files changed, 586 insertions, 1281 deletions
diff --git a/src/vlibmemory/CMakeLists.txt b/src/vlibmemory/CMakeLists.txt index 6d6483dc61f..2ee4dd08ba9 100644 --- a/src/vlibmemory/CMakeLists.txt +++ b/src/vlibmemory/CMakeLists.txt @@ -14,19 +14,13 @@ add_vpp_library (vlibmemory SOURCES memory_api.c - memory_shared.c - memory_client.c - socket_client.c socket_api.c memclnt_api.c vlib_api_cli.c vlib_api.c - ../vlibapi/api_shared.c - ../vlibapi/node_serialize.c INSTALL_HEADERS vl_memory_msg_enum.h - memory_shared.h vl_memory_api_h.h socket_client.h memory_api.h @@ -38,19 +32,16 @@ add_vpp_library (vlibmemory memclnt.api vlib.api - LINK_LIBRARIES vppinfra svm vlib + LINK_LIBRARIES vppinfra svm vlib vlibapi ) add_dependencies(vlibmemory vlibmemory_api_headers) add_vpp_library (vlibmemoryclient SOURCES - memory_shared.c memory_client.c socket_client.c - ../vlibapi/api_shared.c - ../vlibapi/node_serialize.c - LINK_LIBRARIES vppinfra svm + LINK_LIBRARIES vppinfra svm vlibapi ) add_dependencies(vlibmemoryclient vlibmemory_api_headers) @@ -63,3 +54,6 @@ add_vat_test_library(vlib add_vpp_test_library(vlibmemoryclient memclnt.api ) +add_vpp_test_library(vlibmemory + vlib.api +) diff --git a/src/vlibmemory/api.h b/src/vlibmemory/api.h index 662805373ba..273cd2cee10 100644 --- a/src/vlibmemory/api.h +++ b/src/vlibmemory/api.h @@ -28,7 +28,6 @@ void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length); void vl_api_force_rpc_call_main_thread (void *fp, u8 * data, u32 data_length); u16 vl_client_get_first_plugin_msg_id (const char *plugin_name); -void vl_api_send_pending_rpc_requests (vlib_main_t * vm); u8 *vl_api_serialize_message_table (api_main_t * am, u8 * vector); always_inline void diff --git a/src/vlibmemory/memclnt.api b/src/vlibmemory/memclnt.api index bd999b51dd0..dc0f4e1c8a7 100644 --- a/src/vlibmemory/memclnt.api +++ b/src/vlibmemory/memclnt.api @@ -27,9 +27,11 @@ service { }; /* - * Create a client registration + * Create a client registration */ define memclnt_create { + option deprecated; + u32 context; /* opaque value to be returned in the reply */ i32 ctx_quota; /* requested punt context quota */ u64 input_queue; /* client's queue */ @@ -38,6 +40,8 @@ define memclnt_create { }; define memclnt_create_reply { + option deprecated; + u32 context; /* opaque value from the create request */ i32 response; /* Non-negative = success */ u64 handle; /* handle by which vlib knows this client */ @@ -46,7 +50,7 @@ define memclnt_create_reply { }; /* - * Delete a client registration + * Delete a client registration */ define memclnt_delete { u32 index; /* index, used e.g. by API trace replay */ @@ -151,7 +155,7 @@ typedef message_table_entry }; /* - * Create a socket client registration. + * Create a socket client registration. */ define sockclnt_create { u32 context; /* opaque value to be returned in the reply */ @@ -168,7 +172,7 @@ define sockclnt_create_reply { }; /* - * Delete a client registration + * Delete a client registration */ define sockclnt_delete { u32 client_index; @@ -232,3 +236,30 @@ define control_ping_reply u32 vpe_pid; }; +define memclnt_create_v2 { + u32 context; /* opaque value to be returned in the reply */ + i32 ctx_quota; /* requested punt context quota */ + u64 input_queue; /* client's queue */ + string name[64]; /* for show, find by name, whatever */ + u32 api_versions[8]; /* client-server pairs use as desired */ + bool keepalive[default=true]; /* dead client scan keepalives */ +}; + +define memclnt_create_v2_reply { + u32 context; /* opaque value from the create request */ + i32 response; /* Non-negative = success */ + u64 handle; /* handle by which vlib knows this client */ + u32 index; /* index, used e.g. by API trace replay */ + u64 message_table; /* serialized message table in shmem */ +}; + +define get_api_json { + u32 client_index; + u32 context; +}; + +define get_api_json_reply { + u32 context; + i32 retval; + string json[]; +}; diff --git a/src/vlibmemory/memclnt_api.c b/src/vlibmemory/memclnt_api.c index 2b4a2393db3..b0b0c72eae0 100644 --- a/src/vlibmemory/memclnt_api.c +++ b/src/vlibmemory/memclnt_api.c @@ -48,7 +48,6 @@ #undef vl_typedefs /* instantiate all the print functions we know about */ -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) #define vl_printfun #include <vlibmemory/vl_memory_api_h.h> #undef vl_printfun @@ -58,6 +57,10 @@ #include <vlibmemory/vl_memory_api_h.h> #undef vl_endianfun +#define vl_calcsizefun +#include <vlibmemory/vl_memory_api_h.h> +#undef vl_calcsizefun + static void vl_api_get_first_msg_id_t_handler (vl_api_get_first_msg_id_t *mp) { @@ -142,10 +145,44 @@ vl_api_control_ping_t_handler (vl_api_control_ping_t *mp) ({ rmp->vpe_pid = ntohl (getpid ()); })); } +static void +vl_api_get_api_json_t_handler (vl_api_get_api_json_t *mp) +{ + vl_api_get_api_json_reply_t *rmp; + api_main_t *am = vlibapi_get_main (); + int rv = 0, n = 0; + u8 *s = 0; + + vl_api_registration_t *rp = + vl_api_client_index_to_registration (mp->client_index); + if (rp == 0) + return; + + s = format (s, "[\n"); + u8 **ptr; + vec_foreach (ptr, am->json_api_repr) + { + s = format (s, "%s,", ptr[0]); + } + s[vec_len (s) - 1] = ']'; // Replace last comma with a bracket + vec_terminate_c_string (s); + n = vec_len (s); + +done: + REPLY_MACRO3 (VL_API_GET_API_JSON_REPLY, n, ({ + if (rv == 0) + { + vl_api_c_string_to_api_string ((char *) s, &rmp->json); + } + })); + vec_free (s); +} + #define foreach_vlib_api_msg \ _ (GET_FIRST_MSG_ID, get_first_msg_id) \ _ (API_VERSIONS, api_versions) \ - _ (CONTROL_PING, control_ping) + _ (CONTROL_PING, control_ping) \ + _ (GET_API_JSON, get_api_json) /* * vl_api_init @@ -160,6 +197,7 @@ vlib_api_init (void) cJSON_Hooks cjson_hooks = { .malloc_fn = clib_mem_alloc, .free_fn = clib_mem_free, + .realloc_fn = clib_mem_realloc, }; cJSON_InitHooks (&cjson_hooks); @@ -171,12 +209,11 @@ vlib_api_init (void) c->id = VL_API_##N; \ c->name = #n; \ c->handler = vl_api_##n##_t_handler; \ - c->cleanup = vl_noop_handler; \ c->endian = vl_api_##n##_t_endian; \ - c->print = vl_api_##n##_t_print; \ - c->print_json = vl_api_##n##_t_print_json; \ + c->format_fn = vl_api_##n##_t_format; \ c->tojson = vl_api_##n##_t_tojson; \ c->fromjson = vl_api_##n##_t_fromjson; \ + c->calc_size = vl_api_##n##_t_calc_size; \ c->size = sizeof (vl_api_##n##_t); \ c->traced = 1; /* trace, so these msgs print */ \ c->replay = 0; /* don't replay client create/delete msgs */ \ @@ -188,8 +225,11 @@ vlib_api_init (void) foreach_vlib_api_msg; #undef _ - am->is_mp_safe[VL_API_CONTROL_PING] = 1; - am->is_mp_safe[VL_API_CONTROL_PING_REPLY] = 1; + /* Mark messages as mp safe */ + vl_api_set_msg_thread_safe (am, VL_API_GET_FIRST_MSG_ID, 1); + vl_api_set_msg_thread_safe (am, VL_API_API_VERSIONS, 1); + vl_api_set_msg_thread_safe (am, VL_API_CONTROL_PING, 1); + vl_api_set_msg_thread_safe (am, VL_API_CONTROL_PING_REPLY, 1); return 0; } @@ -495,7 +535,7 @@ api_rx_from_node (vlib_main_t *vm, vlib_node_runtime_t *node, if (b0->flags & VLIB_BUFFER_NEXT_PRESENT) { ASSERT (long_msg != 0); - _vec_len (long_msg) = 0; + vec_set_len (long_msg, 0); vec_add (long_msg, msg, msg_len); while (b0->flags & VLIB_BUFFER_NEXT_PRESENT) { @@ -505,8 +545,9 @@ api_rx_from_node (vlib_main_t *vm, vlib_node_runtime_t *node, vec_add (long_msg, msg, msg_len); } msg = long_msg; + msg_len = vec_len (long_msg); } - vl_msg_api_handler_no_trace_no_free (msg); + vl_msg_api_handler_no_trace_no_free (msg, msg_len); } /* Free what we've been given. */ @@ -572,19 +613,6 @@ vl_api_rpc_call_reply_t_handler (vl_api_rpc_call_reply_t *mp) clib_warning ("unimplemented"); } -void -vl_api_send_pending_rpc_requests (vlib_main_t *vm) -{ - vlib_main_t *vm_global = vlib_get_first_main (); - - ASSERT (vm != vm_global); - - clib_spinlock_lock_if_init (&vm_global->pending_rpc_lock); - vec_append (vm_global->pending_rpc_requests, vm->pending_rpc_requests); - vec_reset_length (vm->pending_rpc_requests); - clib_spinlock_unlock_if_init (&vm_global->pending_rpc_lock); -} - always_inline void vl_api_rpc_call_main_thread_inline (void *fp, u8 *data, u32 data_length, u8 force_rpc) @@ -704,27 +732,40 @@ rpc_api_hookup (vlib_main_t *vm) { api_main_t *am = vlibapi_get_main (); #define _(N, n) \ - vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \ - vl_noop_handler, vl_noop_handler, \ - vl_api_##n##_t_print, sizeof (vl_api_##n##_t), \ - 0 /* do not trace */, vl_api_##n##_t_print_json, \ - vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson); + vl_msg_api_config (&(vl_msg_api_msg_config_t){ \ + .id = VL_API_##N, \ + .name = #n, \ + .handler = vl_api_##n##_t_handler, \ + .format_fn = vl_api_##n##_t_format, \ + .size = sizeof (vl_api_##n##_t), \ + .traced = 0, \ + .tojson = vl_api_##n##_t_tojson, \ + .fromjson = vl_api_##n##_t_fromjson, \ + .calc_size = vl_api_##n##_t_calc_size, \ + }); foreach_rpc_api_msg; #undef _ #define _(N, n) \ - vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \ - vl_noop_handler, vl_noop_handler, \ - vl_api_##n##_t_print, sizeof (vl_api_##n##_t), \ - 1 /* do trace */, vl_api_##n##_t_print_json, \ - vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson); - foreach_plugin_trace_msg; + vl_msg_api_config (&(vl_msg_api_msg_config_t){ \ + .id = VL_API_##N, \ + .name = #n, \ + .handler = vl_api_##n##_t_handler, \ + .endian = vl_api_##n##_t_endian, \ + .format_fn = vl_api_##n##_t_format, \ + .size = sizeof (vl_api_##n##_t), \ + .traced = 1, \ + .tojson = vl_api_##n##_t_tojson, \ + .fromjson = vl_api_##n##_t_fromjson, \ + .calc_size = vl_api_##n##_t_calc_size, \ + }); + foreach_plugin_trace_msg #undef _ - am->api_trace_cfg[VL_API_TRACE_PLUGIN_MSG_IDS].replay_enable = 0; + vl_api_allow_msg_replay (am, VL_API_TRACE_PLUGIN_MSG_IDS, 0); /* No reason to halt the parade to create a trace record... */ - am->is_mp_safe[VL_API_TRACE_PLUGIN_MSG_IDS] = 1; + vl_api_set_msg_thread_safe (am, VL_API_TRACE_PLUGIN_MSG_IDS, 1); rpc_call_main_thread_cb_fn = vl_api_rpc_call_main_thread; return 0; } diff --git a/src/vlibmemory/memory_api.c b/src/vlibmemory/memory_api.c index 6c066a152f4..57373b91e31 100644 --- a/src/vlibmemory/memory_api.c +++ b/src/vlibmemory/memory_api.c @@ -28,7 +28,6 @@ #undef vl_typedefs /* instantiate all the print functions we know about */ -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) #define vl_printfun #include <vlibmemory/vl_memory_api_h.h> #undef vl_printfun @@ -192,6 +191,7 @@ vl_api_memclnt_create_t_handler (vl_api_memclnt_create_t * mp) regp->name = format (0, "%s", mp->name); vec_add1 (regp->name, 0); + regp->keepalive = true; if (am->serialized_message_table_in_shmem == 0) am->serialized_message_table_in_shmem = @@ -218,6 +218,87 @@ vl_api_memclnt_create_t_handler (vl_api_memclnt_create_t * mp) } void +vl_api_memclnt_create_v2_t_handler (vl_api_memclnt_create_v2_t *mp) +{ + vl_api_registration_t **regpp; + vl_api_registration_t *regp; + vl_api_memclnt_create_v2_reply_t *rp; + svm_queue_t *q; + int rv = 0; + void *oldheap; + api_main_t *am = vlibapi_get_main (); + u8 *msg_table; + + /* + * This is tortured. Maintain a vlib-address-space private + * pool of client registrations. We use the shared-memory virtual + * address of client structure as a handle, to allow direct + * manipulation of context quota vbls from the client library. + * + * This scheme causes trouble w/ API message trace replay, since + * some random VA from clib_mem_alloc() certainly won't + * occur in the Linux sim. The (very) few places + * that care need to use the pool index. + * + * Putting the registration object(s) into a pool in shared memory and + * using the pool index as a handle seems like a great idea. + * Unfortunately, each and every reference to that pool would need + * to be protected by a mutex: + * + * Client VLIB + * ------ ---- + * convert pool index to + * pointer. + * <deschedule> + * expand pool + * <deschedule> + * kaboom! + */ + + pool_get (am->vl_clients, regpp); + + oldheap = vl_msg_push_heap (); + *regpp = clib_mem_alloc (sizeof (vl_api_registration_t)); + + regp = *regpp; + clib_memset (regp, 0, sizeof (*regp)); + regp->registration_type = REGISTRATION_TYPE_SHMEM; + regp->vl_api_registration_pool_index = regpp - am->vl_clients; + regp->vlib_rp = am->vlib_rp; + regp->shmem_hdr = am->shmem_hdr; + regp->clib_file_index = am->shmem_hdr->clib_file_index; + + q = regp->vl_input_queue = (svm_queue_t *) (uword) mp->input_queue; + VL_MSG_API_SVM_QUEUE_UNPOISON (q); + + regp->name = format (0, "%s", mp->name); + vec_add1 (regp->name, 0); + regp->keepalive = mp->keepalive; + + if (am->serialized_message_table_in_shmem == 0) + am->serialized_message_table_in_shmem = + vl_api_serialize_message_table (am, 0); + + if (am->vlib_rp != am->vlib_primary_rp) + msg_table = vl_api_serialize_message_table (am, 0); + else + msg_table = am->serialized_message_table_in_shmem; + + vl_msg_pop_heap (oldheap); + + rp = vl_msg_api_alloc (sizeof (*rp)); + rp->_vl_msg_id = ntohs (VL_API_MEMCLNT_CREATE_V2_REPLY); + rp->handle = (uword) regp; + rp->index = vl_msg_api_handle_from_index_and_epoch ( + regp->vl_api_registration_pool_index, am->shmem_hdr->application_restarts); + rp->context = mp->context; + rp->response = ntohl (rv); + rp->message_table = pointer_to_uword (msg_table); + + vl_msg_api_send_shmem (q, (u8 *) &rp); +} + +void vl_api_call_reaper_functions (u32 client_index) { clib_error_t *error = 0; @@ -399,6 +480,7 @@ vl_api_memclnt_keepalive_t_handler (vl_api_memclnt_keepalive_t * mp) #define foreach_vlib_api_msg \ _ (MEMCLNT_CREATE, memclnt_create, 0) \ + _ (MEMCLNT_CREATE_V2, memclnt_create_v2, 0) \ _ (MEMCLNT_DELETE, memclnt_delete, 0) \ _ (MEMCLNT_KEEPALIVE, memclnt_keepalive, 0) \ _ (MEMCLNT_KEEPALIVE_REPLY, memclnt_keepalive_reply, 0) @@ -421,18 +503,21 @@ vl_mem_api_init (const char *region_name) if ((rv = vl_map_shmem (region_name, 1 /* is_vlib */ )) < 0) return rv; -#define _(N,n,t) do { \ - c->id = VL_API_##N; \ - c->name = #n; \ - c->handler = vl_api_##n##_t_handler; \ - c->cleanup = vl_noop_handler; \ - c->endian = vl_api_##n##_t_endian; \ - c->print = vl_api_##n##_t_print; \ - c->size = sizeof(vl_api_##n##_t); \ - c->traced = t; /* trace, so these msgs print */ \ - c->replay = 0; /* don't replay client create/delete msgs */ \ - c->message_bounce = 0; /* don't bounce this message */ \ - vl_msg_api_config(c);} while (0); +#define _(N, n, t) \ + do \ + { \ + c->id = VL_API_##N; \ + c->name = #n; \ + c->handler = vl_api_##n##_t_handler; \ + c->endian = vl_api_##n##_t_endian; \ + c->format_fn = vl_api_##n##_t_format; \ + c->size = sizeof (vl_api_##n##_t); \ + c->traced = t; /* trace, so these msgs print */ \ + c->replay = 0; /* don't replay client create/delete msgs */ \ + c->message_bounce = 0; /* don't bounce this message */ \ + vl_msg_api_config (c); \ + } \ + while (0); foreach_vlib_api_msg; #undef _ @@ -449,9 +534,9 @@ vl_mem_api_init (const char *region_name) * special-case freeing of memclnt_delete messages, so we can * simply munmap pairwise / private API segments... */ - am->message_bounce[VL_API_MEMCLNT_DELETE] = 1; - am->is_mp_safe[VL_API_MEMCLNT_KEEPALIVE_REPLY] = 1; - am->is_mp_safe[VL_API_MEMCLNT_KEEPALIVE] = 1; + am->msg_data[VL_API_MEMCLNT_DELETE].bounce = 1; + vl_api_set_msg_thread_safe (am, VL_API_MEMCLNT_KEEPALIVE_REPLY, 1); + vl_api_set_msg_thread_safe (am, VL_API_MEMCLNT_KEEPALIVE, 1); vlib_set_queue_signal_callback (vm, memclnt_queue_callback); @@ -576,12 +661,12 @@ vl_mem_api_dead_client_scan (api_main_t * am, vl_shmem_hdr_t * shm, f64 now) vec_reset_length (dead_indices); vec_reset_length (confused_indices); - /* *INDENT-OFF* */ pool_foreach (regpp, am->vl_clients) { + if (!(*regpp)->keepalive) + continue; vl_mem_send_client_keepalive_w_reg (am, now, regpp, &dead_indices, - &confused_indices); + &confused_indices); } - /* *INDENT-ON* */ /* This should "never happen," but if it does, fix it... */ if (PREDICT_FALSE (vec_len (confused_indices) > 0)) @@ -674,6 +759,139 @@ vl_mem_api_dead_client_scan (api_main_t * am, vl_shmem_hdr_t * shm, f64 now) } } +void (*vl_mem_api_fuzz_hook) (u16, void *); + +/* This is only to be called from a vlib/vnet app */ +static void +vl_mem_api_handler_with_vm_node (api_main_t *am, svm_region_t *vlib_rp, + void *the_msg, vlib_main_t *vm, + vlib_node_runtime_t *node, u8 is_private) +{ + u16 id = clib_net_to_host_u16 (*((u16 *) the_msg)); + vl_api_msg_data_t *m = vl_api_get_msg_data (am, id); + u8 *(*handler) (void *, void *, void *); + svm_region_t *old_vlib_rp; + void *save_shmem_hdr; + int is_mp_safe = 1; + + if (PREDICT_FALSE (am->elog_trace_api_messages)) + { + ELOG_TYPE_DECLARE (e) = { + .format = "api-msg: %s", + .format_args = "T4", + }; + struct + { + u32 c; + } * ed; + ed = ELOG_DATA (am->elog_main, e); + if (m && m->name) + ed->c = elog_string (am->elog_main, (char *) m->name); + else + ed->c = elog_string (am->elog_main, "BOGUS"); + } + + if (m && m->handler) + { + handler = (void *) m->handler; + + if (PREDICT_FALSE (am->rx_trace && am->rx_trace->enabled)) + vl_msg_api_trace (am, am->rx_trace, the_msg); + + if (PREDICT_FALSE (am->msg_print_flag)) + { + fformat (stdout, "[%d]: %s\n", id, m->name); + fformat (stdout, "%U", format_vl_api_msg_text, am, id, the_msg); + } + is_mp_safe = am->msg_data[id].is_mp_safe; + + if (!is_mp_safe) + { + vl_msg_api_barrier_trace_context (am->msg_data[id].name); + vl_msg_api_barrier_sync (); + } + if (is_private) + { + old_vlib_rp = am->vlib_rp; + save_shmem_hdr = am->shmem_hdr; + am->vlib_rp = vlib_rp; + am->shmem_hdr = (void *) vlib_rp->user_ctx; + } + + if (PREDICT_FALSE (vl_mem_api_fuzz_hook != 0)) + (*vl_mem_api_fuzz_hook) (id, the_msg); + + if (m->is_autoendian) + { + void (*endian_fp) (void *, bool); + endian_fp = am->msg_data[id].endian_handler; + (*endian_fp) (the_msg, 0); + } + if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0)) + clib_call_callbacks (am->perf_counter_cbs, am, id, 0 /* before */); + + (*handler) (the_msg, vm, node); + + if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0)) + clib_call_callbacks (am->perf_counter_cbs, am, id, 1 /* after */); + if (is_private) + { + am->vlib_rp = old_vlib_rp; + am->shmem_hdr = save_shmem_hdr; + } + if (!is_mp_safe) + vl_msg_api_barrier_release (); + } + else + { + clib_warning ("no handler for msg id %d", id); + } + + /* + * Special-case, so we can e.g. bounce messages off the vnet + * main thread without copying them... + */ + if (!m || !m->bounce) + { + if (is_private) + { + old_vlib_rp = am->vlib_rp; + save_shmem_hdr = am->shmem_hdr; + am->vlib_rp = vlib_rp; + am->shmem_hdr = (void *) vlib_rp->user_ctx; + } + vl_msg_api_free (the_msg); + if (is_private) + { + am->vlib_rp = old_vlib_rp; + am->shmem_hdr = save_shmem_hdr; + } + } + + if (PREDICT_FALSE (am->elog_trace_api_messages)) + { + ELOG_TYPE_DECLARE (e) = { .format = "api-msg-done(%s): %s", + .format_args = "t4T4", + .n_enum_strings = 2, + .enum_strings = { + "barrier", + "mp-safe", + } }; + + struct + { + u32 barrier; + u32 c; + } * ed; + ed = ELOG_DATA (am->elog_main, e); + if (m && m->name) + ed->c = elog_string (am->elog_main, (char *) m->name); + else + ed->c = elog_string (am->elog_main, "BOGUS"); + ed->barrier = is_mp_safe; + } +} + static inline int void_mem_api_handle_msg_i (api_main_t * am, svm_region_t * vlib_rp, vlib_main_t * vm, vlib_node_runtime_t * node, @@ -687,7 +905,7 @@ void_mem_api_handle_msg_i (api_main_t * am, svm_region_t * vlib_rp, if (!svm_queue_sub2 (q, (u8 *) & mp)) { VL_MSG_API_UNPOISON ((void *) mp); - vl_msg_api_handler_with_vm_node (am, vlib_rp, (void *) mp, vm, node, + vl_mem_api_handler_with_vm_node (am, vlib_rp, (void *) mp, vm, node, is_private); return 0; } @@ -737,8 +955,8 @@ vl_mem_api_handle_rpc (vlib_main_t * vm, vlib_node_runtime_t * node) for (i = 0; i < vec_len (vm->processing_rpc_requests); i++) { mp = vm->processing_rpc_requests[i]; - vl_msg_api_handler_with_vm_node (am, am->vlib_rp, (void *) mp, vm, - node, 0 /* is_private */ ); + vl_mem_api_handler_with_vm_node (am, am->vlib_rp, (void *) mp, vm, + node, 0 /* is_private */); } vl_msg_api_barrier_release (); } @@ -886,7 +1104,6 @@ vl_api_ring_command (vlib_main_t * vm, vl_api_registration_t *regp = 0; /* For horizontal scaling, add a hash table... */ - /* *INDENT-OFF* */ pool_foreach (regpp, am->vl_clients) { regp = *regpp; @@ -898,7 +1115,6 @@ vl_api_ring_command (vlib_main_t * vm, } vlib_cli_output (vm, "regp %llx not found?", regp); continue; - /* *INDENT-ON* */ found: vlib_cli_output (vm, "%U", format_api_message_rings, am, 0 /* print header */ , 0 /* notused */ ); @@ -912,14 +1128,12 @@ vl_api_ring_command (vlib_main_t * vm, /*? * Display binary api message allocation ring statistics ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (cli_show_api_ring_command, static) = { .path = "show api ring-stats", .short_help = "Message ring statistics", .function = vl_api_ring_command, }; -/* *INDENT-ON* */ clib_error_t * vlibmemory_init (vlib_main_t * vm) diff --git a/src/vlibmemory/memory_api.h b/src/vlibmemory/memory_api.h index 843bf8935b2..4a1573c6544 100644 --- a/src/vlibmemory/memory_api.h +++ b/src/vlibmemory/memory_api.h @@ -23,7 +23,7 @@ #include <svm/queue.h> #include <vlib/vlib.h> #include <vlibapi/api.h> -#include <vlibmemory/memory_shared.h> +#include <vlibapi/memory_shared.h> svm_queue_t *vl_api_client_index_to_input_queue (u32 index); int vl_mem_api_init (const char *region_name); diff --git a/src/vlibmemory/memory_client.c b/src/vlibmemory/memory_client.c index f0b05b70695..8bce069f97b 100644 --- a/src/vlibmemory/memory_client.c +++ b/src/vlibmemory/memory_client.c @@ -39,8 +39,11 @@ #include <vlibmemory/vl_memory_api_h.h> #undef vl_endianfun +#define vl_calcsizefun +#include <vlibmemory/vl_memory_api_h.h> +#undef vl_calcsizefun + /* instantiate all the print functions we know about */ -#define vl_print(handle, ...) clib_warning (__VA_ARGS__) #define vl_printfun #include <vlibmemory/vl_memory_api_h.h> #undef vl_printfun @@ -98,23 +101,21 @@ vl_api_name_and_crc_free (void) if (!am->msg_index_by_name_and_crc) return; - /* *INDENT-OFF* */ hash_foreach_pair (hp, am->msg_index_by_name_and_crc, ({ vec_add1 (keys, (u8 *) hp->key); })); - /* *INDENT-ON* */ for (i = 0; i < vec_len (keys); i++) vec_free (keys[i]); vec_free (keys); hash_free (am->msg_index_by_name_and_crc); } -CLIB_NOSANITIZE_ADDR static void +__clib_nosanitize_addr static void VL_API_VEC_UNPOISON (const void *v) { const vec_header_t *vh = &((vec_header_t *) v)[-1]; - CLIB_MEM_UNPOISON (vh, sizeof (*vh) + vec_len (v)); + clib_mem_unpoison (vh, sizeof (*vh) + vec_len (v)); } static void @@ -151,11 +152,6 @@ vl_api_memclnt_create_reply_t_handler (vl_api_memclnt_create_reply_t * mp) } } -static void -noop_handler (void *notused) -{ -} - void vl_msg_api_send_shmem (svm_queue_t * q, u8 * elem); int vl_client_connect (const char *name, int ctx_quota, int input_queue_size) @@ -188,7 +184,7 @@ vl_client_connect (const char *name, int ctx_quota, int input_queue_size) return -1; } - CLIB_MEM_UNPOISON (shmem_hdr, sizeof (*shmem_hdr)); + clib_mem_unpoison (shmem_hdr, sizeof (*shmem_hdr)); VL_MSG_API_SVM_QUEUE_UNPOISON (shmem_hdr->vl_input_queue); oldheap = vl_msg_push_heap (); @@ -240,7 +236,8 @@ vl_client_connect (const char *name, int ctx_quota, int input_queue_size) } rv = clib_net_to_host_u32 (rp->response); - vl_msg_api_handler ((void *) rp); + msgbuf_t *msgbuf = (msgbuf_t *) ((u8 *) rp - offsetof (msgbuf_t, data)); + vl_msg_api_handler ((void *) rp, ntohl (msgbuf->data_len)); break; } return (rv); @@ -289,6 +286,7 @@ vl_client_disconnect (void) svm_queue_t *vl_input_queue; api_main_t *am = vlibapi_get_main (); time_t begin; + msgbuf_t *msgbuf; vl_input_queue = am->vl_input_queue; vl_client_send_disconnect (0 /* wait for reply */ ); @@ -321,10 +319,12 @@ vl_client_disconnect (void) if (ntohs (rp->_vl_msg_id) != VL_API_MEMCLNT_DELETE_REPLY) { clib_warning ("queue drain: %d", ntohs (rp->_vl_msg_id)); - vl_msg_api_handler ((void *) rp); + msgbuf = (msgbuf_t *) ((u8 *) rp - offsetof (msgbuf_t, data)); + vl_msg_api_handler ((void *) rp, ntohl (msgbuf->data_len)); continue; } - vl_msg_api_handler ((void *) rp); + msgbuf = (msgbuf_t *) ((u8 *) rp - offsetof (msgbuf_t, data)); + vl_msg_api_handler ((void *) rp, ntohl (msgbuf->data_len)); break; } @@ -364,12 +364,19 @@ vl_client_install_client_message_handlers (void) { api_main_t *am = vlibapi_get_main (); #define _(N, n) \ - vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \ - noop_handler, vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0, \ - vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \ - vl_api_##n##_t_fromjson); \ - am->api_trace_cfg[VL_API_##N].replay_enable = 0; + vl_msg_api_config (&(vl_msg_api_msg_config_t){ \ + .id = VL_API_##N, \ + .name = #n, \ + .handler = vl_api_##n##_t_handler, \ + .endian = vl_api_##n##_t_endian, \ + .format_fn = vl_api_##n##_t_format, \ + .size = sizeof (vl_api_##n##_t), \ + .traced = 0, \ + .tojson = vl_api_##n##_t_tojson, \ + .fromjson = vl_api_##n##_t_fromjson, \ + .calc_size = vl_api_##n##_t_calc_size, \ + }); \ + am->msg_data[VL_API_##N].replay_allowed = 0; foreach_api_msg; #undef _ } @@ -501,6 +508,14 @@ vl_client_connect_to_vlib_thread_fn (const char *svm_name, thread_fn, arg, 1 /* do map */ ); } +void +vl_client_stop_rx_thread (svm_queue_t *vl_input_queue) +{ + vl_api_rx_thread_exit_t *ep; + ep = vl_msg_api_alloc (sizeof (*ep)); + ep->_vl_msg_id = ntohs (VL_API_RX_THREAD_EXIT); + vl_msg_api_send_shmem (vl_input_queue, (u8 *) &ep); +} static void disconnect_from_vlib_internal (u8 do_unmap) @@ -511,10 +526,7 @@ disconnect_from_vlib_internal (u8 do_unmap) if (mm->rx_thread_jmpbuf_valid) { - vl_api_rx_thread_exit_t *ep; - ep = vl_msg_api_alloc (sizeof (*ep)); - ep->_vl_msg_id = ntohs (VL_API_RX_THREAD_EXIT); - vl_msg_api_send_shmem (am->vl_input_queue, (u8 *) & ep); + vl_client_stop_rx_thread (am->vl_input_queue); pthread_join (mm->rx_thread_handle, (void **) &junk); } if (mm->connected_to_vlib) @@ -554,6 +566,8 @@ vl_client_get_first_plugin_msg_id (const char *plugin_name) vl_api_get_first_msg_id_t *mp; api_main_t *am = vlibapi_get_main (); memory_client_main_t *mm = vlibapi_get_memory_client_main (); + vl_api_msg_data_t *m = + vl_api_get_msg_data (am, VL_API_GET_FIRST_MSG_ID_REPLY); f64 timeout; void *old_handler; clib_time_t clib_time; @@ -566,9 +580,13 @@ vl_client_get_first_plugin_msg_id (const char *plugin_name) clib_time_init (&clib_time); /* Push this plugin's first_msg_id_reply handler */ - old_handler = am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY]; - am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = (void *) - vl_api_get_first_msg_id_reply_t_handler; + old_handler = m->handler; + m->handler = (void *) vl_api_get_first_msg_id_reply_t_handler; + if (!m->calc_size_func) + { + m->calc_size_func = + (uword (*) (void *)) vl_api_get_first_msg_id_reply_t_calc_size; + } /* Ask the data-plane for the message-ID base of the indicated plugin */ mm->first_msg_id_reply_ready = 0; @@ -595,7 +613,7 @@ vl_client_get_first_plugin_msg_id (const char *plugin_name) sock_err: /* Restore old handler */ - am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = old_handler; + m->handler = old_handler; return -1; } @@ -620,7 +638,7 @@ vl_client_get_first_plugin_msg_id (const char *plugin_name) } } /* Restore old handler */ - am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = old_handler; + m->handler = old_handler; return rv; } @@ -628,7 +646,7 @@ vl_client_get_first_plugin_msg_id (const char *plugin_name) result: /* Restore the old handler */ - am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = old_handler; + m->handler = old_handler; if (rv == (u16) ~ 0) clib_warning ("plugin '%s' not registered", plugin_name); diff --git a/src/vlibmemory/memory_client.h b/src/vlibmemory/memory_client.h index a0168693a4b..3b9b2d8d959 100644 --- a/src/vlibmemory/memory_client.h +++ b/src/vlibmemory/memory_client.h @@ -18,7 +18,7 @@ #ifndef SRC_VLIBMEMORY_MEMORY_CLIENT_H_ #define SRC_VLIBMEMORY_MEMORY_CLIENT_H_ -#include <vlibmemory/memory_shared.h> +#include <vlibapi/memory_shared.h> #include <setjmp.h> /* @@ -62,6 +62,7 @@ int vl_client_connect_to_vlib_no_rx_pthread_no_map (const char *svm_name, int rx_queue_size); void vl_client_install_client_message_handlers (void); u8 vl_mem_client_is_connected (void); +void vl_client_stop_rx_thread (svm_queue_t *vl_input_queue); always_inline memory_client_main_t * vlibapi_get_memory_client_main (void) diff --git a/src/vlibmemory/memory_shared.c b/src/vlibmemory/memory_shared.c deleted file mode 100644 index 1716f271466..00000000000 --- a/src/vlibmemory/memory_shared.c +++ /dev/null @@ -1,818 +0,0 @@ -/* - *------------------------------------------------------------------ - * memclnt_shared.c - API message handling, common code for both clients - * and the vlib process itself. - * - * - * Copyright (c) 2009 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <unistd.h> -#include <signal.h> - -#include <vppinfra/format.h> -#include <vppinfra/byte_order.h> -#include <vppinfra/error.h> -#include <vppinfra/elog.h> -#include <svm/queue.h> -#include <vlib/vlib.h> -#include <vlib/unix/unix.h> -#include <vlibmemory/memory_api.h> -#include <vlibmemory/vl_memory_msg_enum.h> -#include <vlibapi/api_common.h> - -#define vl_typedefs -#include <vlibmemory/vl_memory_api_h.h> -#undef vl_typedefs - -#define DEBUG_MESSAGE_BUFFER_OVERRUN 0 - -CLIB_NOSANITIZE_ADDR static inline void * -vl_msg_api_alloc_internal (svm_region_t * vlib_rp, int nbytes, int pool, - int may_return_null) -{ - int i; - msgbuf_t *rv; - ring_alloc_t *ap; - svm_queue_t *q; - void *oldheap; - vl_shmem_hdr_t *shmem_hdr; - api_main_t *am = vlibapi_get_main (); - - shmem_hdr = (void *) vlib_rp->user_ctx; - -#if DEBUG_MESSAGE_BUFFER_OVERRUN > 0 - nbytes += 4; -#endif - - ASSERT (pool == 0 || vlib_get_thread_index () == 0); - - if (shmem_hdr == 0) - { - clib_warning ("shared memory header NULL"); - return 0; - } - - /* account for the msgbuf_t header */ - nbytes += sizeof (msgbuf_t); - - if (shmem_hdr->vl_rings == 0) - { - clib_warning ("vl_rings NULL"); - ASSERT (0); - abort (); - } - - if (shmem_hdr->client_rings == 0) - { - clib_warning ("client_rings NULL"); - ASSERT (0); - abort (); - } - - ap = pool ? shmem_hdr->vl_rings : shmem_hdr->client_rings; - for (i = 0; i < vec_len (ap); i++) - { - /* Too big? */ - if (nbytes > ap[i].size) - { - continue; - } - - q = ap[i].rp; - if (pool == 0) - { - pthread_mutex_lock (&q->mutex); - } - rv = (msgbuf_t *) (&q->data[0] + q->head * q->elsize); - /* - * Is this item still in use? - */ - if (rv->q) - { - u32 now = (u32) time (0); - - if (PREDICT_TRUE (rv->gc_mark_timestamp == 0)) - rv->gc_mark_timestamp = now; - else - { - if (now - rv->gc_mark_timestamp > 10) - { - if (CLIB_DEBUG > 0) - { - u16 *msg_idp, msg_id; - clib_warning - ("garbage collect pool %d ring %d index %d", pool, i, - q->head); - msg_idp = (u16 *) (rv->data); - msg_id = clib_net_to_host_u16 (*msg_idp); - if (msg_id < vec_len (vlibapi_get_main ()->msg_names)) - clib_warning ("msg id %d name %s", (u32) msg_id, - vlibapi_get_main ()->msg_names[msg_id]); - } - shmem_hdr->garbage_collects++; - goto collected; - } - } - - - /* yes, loser; try next larger pool */ - ap[i].misses++; - if (pool == 0) - pthread_mutex_unlock (&q->mutex); - continue; - } - collected: - - /* OK, we have a winner */ - ap[i].hits++; - /* - * Remember the source queue, although we - * don't need to know the queue to free the item. - */ - rv->q = q; - rv->gc_mark_timestamp = 0; - q->head++; - if (q->head == q->maxsize) - q->head = 0; - - if (pool == 0) - pthread_mutex_unlock (&q->mutex); - goto out; - } - - /* - * Request too big, or head element of all size-compatible rings - * still in use. Fall back to shared-memory malloc. - */ - am->ring_misses++; - - oldheap = vl_msg_push_heap_w_region (vlib_rp); - if (may_return_null) - { - rv = clib_mem_alloc_or_null (nbytes); - if (PREDICT_FALSE (rv == 0)) - { - vl_msg_pop_heap_w_region (vlib_rp, oldheap); - return 0; - } - } - else - rv = clib_mem_alloc (nbytes); - - rv->q = 0; - rv->gc_mark_timestamp = 0; - vl_msg_pop_heap_w_region (vlib_rp, oldheap); - -out: -#if DEBUG_MESSAGE_BUFFER_OVERRUN > 0 - { - nbytes -= 4; - u32 *overrun; - overrun = (u32 *) (rv->data + nbytes - sizeof (msgbuf_t)); - *overrun = 0x1badbabe; - } -#endif - rv->data_len = htonl (nbytes - sizeof (msgbuf_t)); - - VL_MSG_API_UNPOISON (rv->data); - return (rv->data); -} - -void * -vl_msg_api_alloc (int nbytes) -{ - int pool; - api_main_t *am = vlibapi_get_main (); - vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr; - - /* - * Clients use pool-0, vlib proc uses pool 1 - */ - pool = (am->our_pid == shmem_hdr->vl_pid); - return vl_msg_api_alloc_internal (am->vlib_rp, nbytes, pool, - 0 /* may_return_null */ ); -} - -void * -vl_msg_api_alloc_zero (int nbytes) -{ - void *ret; - - ret = vl_msg_api_alloc (nbytes); - clib_memset (ret, 0, nbytes); - return ret; -} - -void * -vl_msg_api_alloc_or_null (int nbytes) -{ - int pool; - api_main_t *am = vlibapi_get_main (); - vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr; - - pool = (am->our_pid == shmem_hdr->vl_pid); - return vl_msg_api_alloc_internal (am->vlib_rp, nbytes, pool, - 1 /* may_return_null */ ); -} - -void * -vl_msg_api_alloc_as_if_client (int nbytes) -{ - api_main_t *am = vlibapi_get_main (); - return vl_msg_api_alloc_internal (am->vlib_rp, nbytes, 0, - 0 /* may_return_null */ ); -} - -void * -vl_msg_api_alloc_zero_as_if_client (int nbytes) -{ - void *ret; - - ret = vl_msg_api_alloc_as_if_client (nbytes); - clib_memset (ret, 0, nbytes); - return ret; -} - -void * -vl_msg_api_alloc_as_if_client_or_null (int nbytes) -{ - api_main_t *am = vlibapi_get_main (); - return vl_msg_api_alloc_internal (am->vlib_rp, nbytes, 0, - 1 /* may_return_null */ ); -} - -void * -vl_mem_api_alloc_as_if_client_w_reg (vl_api_registration_t * reg, int nbytes) -{ - return vl_msg_api_alloc_internal (reg->vlib_rp, nbytes, 0, - 0 /* may_return_null */ ); -} - -void -vl_msg_api_free_w_region (svm_region_t * vlib_rp, void *a) -{ - msgbuf_t *rv; - void *oldheap; - - rv = (msgbuf_t *) (((u8 *) a) - offsetof (msgbuf_t, data)); - - /* - * Here's the beauty of the scheme. Only one proc/thread has - * control of a given message buffer. To free a buffer, we just clear the - * queue field, and leave. No locks, no hits, no errors... - */ - if (rv->q) - { - rv->q = 0; - rv->gc_mark_timestamp = 0; -#if DEBUG_MESSAGE_BUFFER_OVERRUN > 0 - { - u32 *overrun; - overrun = (u32 *) (rv->data + ntohl (rv->data_len)); - ASSERT (*overrun == 0x1badbabe); - } -#endif - VL_MSG_API_POISON (rv->data); - return; - } - - oldheap = vl_msg_push_heap_w_region (vlib_rp); - -#if DEBUG_MESSAGE_BUFFER_OVERRUN > 0 - { - u32 *overrun; - overrun = (u32 *) (rv->data + ntohl (rv->data_len)); - ASSERT (*overrun == 0x1badbabe); - } -#endif - - clib_mem_free (rv); - vl_msg_pop_heap_w_region (vlib_rp, oldheap); -} - -void -vl_msg_api_free (void *a) -{ - api_main_t *am = vlibapi_get_main (); - vl_msg_api_free_w_region (am->vlib_rp, a); -} - -static void -vl_msg_api_free_nolock (void *a) -{ - msgbuf_t *rv; - void *oldheap; - api_main_t *am = vlibapi_get_main (); - - rv = (msgbuf_t *) (((u8 *) a) - offsetof (msgbuf_t, data)); - /* - * Here's the beauty of the scheme. Only one proc/thread has - * control of a given message buffer. To free a buffer, we just clear the - * queue field, and leave. No locks, no hits, no errors... - */ - if (rv->q) - { - rv->q = 0; - VL_MSG_API_POISON (rv->data); - return; - } - - oldheap = svm_push_data_heap (am->vlib_rp); - clib_mem_free (rv); - svm_pop_heap (oldheap); -} - -void -vl_set_memory_root_path (const char *name) -{ - api_main_t *am = vlibapi_get_main (); - - am->root_path = name; -} - -void -vl_set_memory_uid (int uid) -{ - api_main_t *am = vlibapi_get_main (); - - am->api_uid = uid; -} - -void -vl_set_memory_gid (int gid) -{ - api_main_t *am = vlibapi_get_main (); - - am->api_gid = gid; -} - -void -vl_set_global_memory_baseva (u64 baseva) -{ - api_main_t *am = vlibapi_get_main (); - - am->global_baseva = baseva; -} - -void -vl_set_global_memory_size (u64 size) -{ - api_main_t *am = vlibapi_get_main (); - - am->global_size = size; -} - -void -vl_set_api_memory_size (u64 size) -{ - api_main_t *am = vlibapi_get_main (); - - am->api_size = size; -} - -void -vl_set_global_pvt_heap_size (u64 size) -{ - api_main_t *am = vlibapi_get_main (); - - am->global_pvt_heap_size = size; -} - -void -vl_set_api_pvt_heap_size (u64 size) -{ - api_main_t *am = vlibapi_get_main (); - - am->api_pvt_heap_size = size; -} - -static void -vl_api_default_mem_config (vl_shmem_hdr_t * shmem_hdr) -{ - api_main_t *am = vlibapi_get_main (); - u32 vlib_input_queue_length; - - /* vlib main input queue */ - vlib_input_queue_length = 1024; - if (am->vlib_input_queue_length) - vlib_input_queue_length = am->vlib_input_queue_length; - - shmem_hdr->vl_input_queue = - svm_queue_alloc_and_init (vlib_input_queue_length, sizeof (uword), - getpid ()); - -#define _(sz,n) \ - do { \ - ring_alloc_t _rp; \ - _rp.rp = svm_queue_alloc_and_init ((n), (sz), 0); \ - _rp.size = (sz); \ - _rp.nitems = n; \ - _rp.hits = 0; \ - _rp.misses = 0; \ - vec_add1(shmem_hdr->vl_rings, _rp); \ - } while (0); - - foreach_vl_aring_size; -#undef _ - -#define _(sz,n) \ - do { \ - ring_alloc_t _rp; \ - _rp.rp = svm_queue_alloc_and_init ((n), (sz), 0); \ - _rp.size = (sz); \ - _rp.nitems = n; \ - _rp.hits = 0; \ - _rp.misses = 0; \ - vec_add1(shmem_hdr->client_rings, _rp); \ - } while (0); - - foreach_clnt_aring_size; -#undef _ -} - -void -vl_api_mem_config (vl_shmem_hdr_t * hdr, vl_api_shm_elem_config_t * config) -{ - vl_api_shm_elem_config_t *c; - ring_alloc_t *rp; - u32 size; - - if (!config) - { - vl_api_default_mem_config (hdr); - return; - } - - vec_foreach (c, config) - { - switch (c->type) - { - case VL_API_QUEUE: - hdr->vl_input_queue = svm_queue_alloc_and_init (c->count, c->size, - getpid ()); - continue; - case VL_API_VLIB_RING: - vec_add2 (hdr->vl_rings, rp, 1); - break; - case VL_API_CLIENT_RING: - vec_add2 (hdr->client_rings, rp, 1); - break; - default: - clib_warning ("unknown config type: %d", c->type); - continue; - } - - size = sizeof (ring_alloc_t) + c->size; - rp->rp = svm_queue_alloc_and_init (c->count, size, 0); - rp->size = size; - rp->nitems = c->count; - rp->hits = 0; - rp->misses = 0; - } -} - -void -vl_init_shmem (svm_region_t * vlib_rp, vl_api_shm_elem_config_t * config, - int is_vlib, int is_private_region) -{ - api_main_t *am = vlibapi_get_main (); - vl_shmem_hdr_t *shmem_hdr = 0; - void *oldheap; - ASSERT (vlib_rp); - - /* $$$$ need private region config parameters */ - - oldheap = svm_push_data_heap (vlib_rp); - - vec_validate (shmem_hdr, 0); - shmem_hdr->version = VL_SHM_VERSION; - shmem_hdr->clib_file_index = VL_API_INVALID_FI; - - /* Set up the queue and msg ring allocator */ - vl_api_mem_config (shmem_hdr, config); - - if (is_private_region == 0) - { - am->shmem_hdr = shmem_hdr; - am->vlib_rp = vlib_rp; - am->our_pid = getpid (); - if (is_vlib) - am->shmem_hdr->vl_pid = am->our_pid; - } - else - shmem_hdr->vl_pid = am->our_pid; - - svm_pop_heap (oldheap); - - /* - * After absolutely everything that a client might see is set up, - * declare the shmem region valid - */ - vlib_rp->user_ctx = shmem_hdr; - - pthread_mutex_unlock (&vlib_rp->mutex); -} - -int -vl_map_shmem (const char *region_name, int is_vlib) -{ - svm_map_region_args_t _a, *a = &_a; - svm_region_t *vlib_rp, *root_rp; - api_main_t *am = vlibapi_get_main (); - int i; - struct timespec ts, tsrem; - char *vpe_api_region_suffix = "-vpe-api"; - - clib_memset (a, 0, sizeof (*a)); - - if (strstr (region_name, vpe_api_region_suffix)) - { - u8 *root_path = format (0, "%s", region_name); - _vec_len (root_path) = (vec_len (root_path) - - strlen (vpe_api_region_suffix)); - vec_terminate_c_string (root_path); - a->root_path = (const char *) root_path; - am->root_path = (const char *) root_path; - } - - if (is_vlib == 0) - { - int tfd; - u8 *api_name; - /* - * Clients wait for vpp to set up the root / API regioins - */ - if (am->root_path) - api_name = format (0, "/dev/shm/%s-%s%c", am->root_path, - region_name + 1, 0); - else - api_name = format (0, "/dev/shm%s%c", region_name, 0); - - /* Wait up to 100 seconds... */ - for (i = 0; i < 10000; i++) - { - ts.tv_sec = 0; - ts.tv_nsec = 10000 * 1000; /* 10 ms */ - while (nanosleep (&ts, &tsrem) < 0) - ts = tsrem; - tfd = open ((char *) api_name, O_RDWR); - if (tfd >= 0) - break; - } - vec_free (api_name); - if (tfd < 0) - { - clib_warning ("region init fail"); - return -2; - } - close (tfd); - svm_region_init_chroot_uid_gid (am->root_path, getuid (), getgid ()); - } - - if (a->root_path != NULL) - { - a->name = "/vpe-api"; - } - else - a->name = region_name; - a->size = am->api_size ? am->api_size : (16 << 20); - a->flags = SVM_FLAGS_MHEAP; - a->uid = am->api_uid; - a->gid = am->api_gid; - a->pvt_heap_size = am->api_pvt_heap_size; - - vlib_rp = svm_region_find_or_create (a); - - if (vlib_rp == 0) - return (-2); - - pthread_mutex_lock (&vlib_rp->mutex); - /* Has someone else set up the shared-memory variable table? */ - if (vlib_rp->user_ctx) - { - am->shmem_hdr = (void *) vlib_rp->user_ctx; - am->our_pid = getpid (); - if (is_vlib) - { - svm_queue_t *q; - uword old_msg; - /* - * application restart. Reset cached pids, API message - * rings, list of clients; otherwise, various things - * fail. (e.g. queue non-empty notification) - */ - - /* ghosts keep the region from disappearing properly */ - svm_client_scan_this_region_nolock (vlib_rp); - am->shmem_hdr->application_restarts++; - q = am->shmem_hdr->vl_input_queue; - am->shmem_hdr->vl_pid = getpid (); - q->consumer_pid = am->shmem_hdr->vl_pid; - /* Drain the input queue, freeing msgs */ - for (i = 0; i < 10; i++) - { - if (pthread_mutex_trylock (&q->mutex) == 0) - { - pthread_mutex_unlock (&q->mutex); - goto mutex_ok; - } - ts.tv_sec = 0; - ts.tv_nsec = 10000 * 1000; /* 10 ms */ - while (nanosleep (&ts, &tsrem) < 0) - ts = tsrem; - } - /* Mutex buggered, "fix" it */ - clib_memset (&q->mutex, 0, sizeof (q->mutex)); - clib_warning ("forcibly release main input queue mutex"); - - mutex_ok: - am->vlib_rp = vlib_rp; - while (svm_queue_sub (q, (u8 *) & old_msg, SVM_Q_NOWAIT, 0) - != -2 /* queue underflow */ ) - { - vl_msg_api_free_nolock ((void *) old_msg); - am->shmem_hdr->restart_reclaims++; - } - pthread_mutex_unlock (&vlib_rp->mutex); - root_rp = svm_get_root_rp (); - ASSERT (root_rp); - /* Clean up the root region client list */ - pthread_mutex_lock (&root_rp->mutex); - svm_client_scan_this_region_nolock (root_rp); - pthread_mutex_unlock (&root_rp->mutex); - } - else - { - pthread_mutex_unlock (&vlib_rp->mutex); - } - am->vlib_rp = vlib_rp; - vec_add1 (am->mapped_shmem_regions, vlib_rp); - return 0; - } - /* Clients simply have to wait... */ - if (!is_vlib) - { - pthread_mutex_unlock (&vlib_rp->mutex); - - /* Wait up to 100 seconds... */ - for (i = 0; i < 10000; i++) - { - ts.tv_sec = 0; - ts.tv_nsec = 10000 * 1000; /* 10 ms */ - while (nanosleep (&ts, &tsrem) < 0) - ts = tsrem; - if (vlib_rp->user_ctx) - goto ready; - } - /* Clean up and leave... */ - svm_region_unmap (vlib_rp); - clib_warning ("region init fail"); - return (-2); - - ready: - am->shmem_hdr = (void *) vlib_rp->user_ctx; - am->our_pid = getpid (); - am->vlib_rp = vlib_rp; - vec_add1 (am->mapped_shmem_regions, vlib_rp); - return 0; - } - - /* Nope, it's our problem... */ - vl_init_shmem (vlib_rp, 0 /* default config */ , 1 /* is vlib */ , - 0 /* is_private_region */ ); - - vec_add1 (am->mapped_shmem_regions, vlib_rp); - return 0; -} - -void -vl_register_mapped_shmem_region (svm_region_t * rp) -{ - api_main_t *am = vlibapi_get_main (); - - vec_add1 (am->mapped_shmem_regions, rp); -} - -static void -vl_unmap_shmem_internal (u8 is_client) -{ - svm_region_t *rp; - int i; - api_main_t *am = vlibapi_get_main (); - - if (!svm_get_root_rp ()) - return; - - for (i = 0; i < vec_len (am->mapped_shmem_regions); i++) - { - rp = am->mapped_shmem_regions[i]; - is_client ? svm_region_unmap_client (rp) : svm_region_unmap (rp); - } - - vec_free (am->mapped_shmem_regions); - am->shmem_hdr = 0; - - is_client ? svm_region_exit_client () : svm_region_exit (); - - /* $$$ more careful cleanup, valgrind run... */ - vec_free (am->msg_handlers); - vec_free (am->msg_endian_handlers); - vec_free (am->msg_print_handlers); -} - -void -vl_unmap_shmem (void) -{ - vl_unmap_shmem_internal (0); -} - -void -vl_unmap_shmem_client (void) -{ - vl_unmap_shmem_internal (1); -} - -void -vl_msg_api_send_shmem (svm_queue_t * q, u8 * elem) -{ - api_main_t *am = vlibapi_get_main (); - void *msg = (void *) *(uword *) elem; - - if (am->tx_trace && am->tx_trace->enabled) - vl_msg_api_trace (am, am->tx_trace, msg); - - /* - * Announce a probable binary API client bug: - * some client's input queue is stuffed. - * The situation may be recoverable, or not. - */ - if (PREDICT_FALSE - (am->vl_clients /* vpp side */ && (q->cursize == q->maxsize))) - { - if (PREDICT_FALSE (am->elog_trace_api_messages)) - { - /* *INDENT-OFF* */ - ELOG_TYPE_DECLARE (e) = - { - .format = "api-client-queue-stuffed: %x%x", - .format_args = "i4i4", - }; - /* *INDENT-ON* */ - struct - { - u32 hi, low; - } *ed; - ed = ELOG_DATA (am->elog_main, e); - ed->hi = (uword) q >> 32; - ed->low = (uword) q & 0xFFFFFFFF; - clib_warning ("WARNING: client input queue at %llx is stuffed...", - q); - } - } - VL_MSG_API_POISON (msg); - (void) svm_queue_add (q, elem, 0 /* nowait */ ); -} - -int -vl_mem_api_can_send (svm_queue_t * q) -{ - return (q->cursize < q->maxsize); -} - -void -vl_msg_api_send_shmem_nolock (svm_queue_t * q, u8 * elem) -{ - api_main_t *am = vlibapi_get_main (); - void *msg = (void *) *(uword *) elem; - - if (am->tx_trace && am->tx_trace->enabled) - vl_msg_api_trace (am, am->tx_trace, msg); - - (void) svm_queue_add_nolock (q, elem); - VL_MSG_API_POISON (msg); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vlibmemory/memory_shared.h b/src/vlibmemory/memory_shared.h deleted file mode 100644 index 4c4773d060b..00000000000 --- a/src/vlibmemory/memory_shared.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#ifndef SRC_VLIBMEMORY_MEMORY_SHARED_H_ -#define SRC_VLIBMEMORY_MEMORY_SHARED_H_ - -#include <vlibapi/api_common.h> -#include <vppinfra/error.h> - -/* Allocated in shared memory */ - -/* - * Ring-allocation scheme for client API messages - * - * Only one proc/thread has control of a given message buffer. - * To free a buffer allocated from one of these rings, we clear - * a field in the buffer (header), and leave. - * - * No locks, no hits, no errors... - */ -typedef struct ring_alloc_ -{ - svm_queue_t *rp; - u16 size; - u16 nitems; - u32 hits; - u32 misses; -} ring_alloc_t; - -typedef enum -{ - VL_API_VLIB_RING, - VL_API_CLIENT_RING, - VL_API_QUEUE -} vl_api_shm_config_type_t; - -typedef struct vl_api_shm_elem_config_ -{ - u8 type; - u8 _pad; - u16 count; - u32 size; -} vl_api_shm_elem_config_t; - -STATIC_ASSERT (sizeof (vl_api_shm_elem_config_t) == 8, - "Size must be exactly 8 bytes"); - -/* - * Initializers for the (shared-memory) rings - * _(size, n). Note: each msg has space for a header. - */ -#define foreach_vl_aring_size \ -_(64+sizeof(ring_alloc_t), 1024) \ -_(256+sizeof(ring_alloc_t), 128) \ -_(1024+sizeof(ring_alloc_t), 64) - -#define foreach_clnt_aring_size \ - _(1024+sizeof(ring_alloc_t), 1024) \ - _(2048+sizeof(ring_alloc_t), 128) \ - _(4096+sizeof(ring_alloc_t), 8) - -typedef struct vl_shmem_hdr_ -{ - int version; - - /* getpid () for the VLIB client process */ - volatile int vl_pid; - - /* Client sends VLIB msgs here. */ - svm_queue_t *vl_input_queue; - - /* Vector of rings; one for each size. */ - - /* VLIB allocates buffers to send msgs to clients here. */ - ring_alloc_t *vl_rings; - - /* Clients allocate buffer to send msgs to VLIB here. */ - ring_alloc_t *client_rings; - - /* Number of detected application restarts */ - u32 application_restarts; - - /* Number of messages reclaimed during application restart */ - u32 restart_reclaims; - - /* Number of garbage-collected messages */ - u32 garbage_collects; - - /* Socket file index used to bootstrap shmem region */ - u32 clib_file_index; -} vl_shmem_hdr_t; - -#define VL_SHM_VERSION 2 -#define VL_API_EPOCH_MASK 0xFF -#define VL_API_EPOCH_SHIFT 8 - -void *vl_msg_api_alloc (int nbytes); -void *vl_msg_api_alloc_zero (int nbytes); -void *vl_msg_api_alloc_or_null (int nbytes); -void *vl_msg_api_alloc_as_if_client (int nbytes); -void *vl_msg_api_alloc_zero_as_if_client (int nbytes); -void *vl_msg_api_alloc_as_if_client_or_null (int nbytes); -void *vl_mem_api_alloc_as_if_client_w_reg (vl_api_registration_t * reg, - int nbytes); -void vl_msg_api_free (void *a); -void vl_msg_api_free_w_region (svm_region_t * vlib_rp, void *a); -int vl_map_shmem (const char *region_name, int is_vlib); -void vl_unmap_shmem (void); -void vl_unmap_shmem_client (void); -void vl_register_mapped_shmem_region (svm_region_t * rp); -void vl_msg_api_send_shmem (svm_queue_t * q, u8 * elem); -int vl_mem_api_can_send (svm_queue_t * q); -void vl_set_memory_region_name (const char *name); -void vl_set_memory_root_path (const char *root_path); -void vl_set_memory_uid (int uid); -void vl_set_memory_gid (int gid); -void vl_set_global_memory_baseva (u64 baseva); -void vl_set_global_memory_size (u64 size); -void vl_set_api_memory_size (u64 size); -void vl_set_global_pvt_heap_size (u64 size); -void vl_set_api_pvt_heap_size (u64 size); -void vl_init_shmem (svm_region_t * vlib_rp, vl_api_shm_elem_config_t * config, - int is_vlib, int is_private_region); - -#endif /* SRC_VLIBMEMORY_MEMORY_SHARED_H_ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vlibmemory/socket_api.c b/src/vlibmemory/socket_api.c index ce834a70aac..26be8d09522 100644 --- a/src/vlibmemory/socket_api.c +++ b/src/vlibmemory/socket_api.c @@ -35,7 +35,6 @@ #undef vl_typedefs /* instantiate all the print functions we know about */ -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) #define vl_printfun #include <vlibmemory/vl_memory_api_h.h> #undef vl_printfun @@ -45,6 +44,10 @@ #include <vlibmemory/vl_memory_api_h.h> #undef vl_endianfun +#define vl_calcsizefun +#include <vlibmemory/vl_memory_api_h.h> +#undef vl_calcsizefun + socket_main_t socket_main; #define SOCK_API_REG_HANDLE_BIT (1<<31) @@ -84,7 +87,6 @@ vl_sock_api_dump_clients (vlib_main_t * vm, api_main_t * am) vlib_cli_output (vm, "Socket clients"); vlib_cli_output (vm, "%20s %8s", "Name", "Fildesc"); - /* *INDENT-OFF* */ pool_foreach (reg, sm->registration_pool) { if (reg->registration_type == REGISTRATION_TYPE_SOCKET_SERVER) { @@ -92,7 +94,6 @@ vl_sock_api_dump_clients (vlib_main_t * vm, api_main_t * am) vlib_cli_output (vm, "%20s %8d", reg->name, f->file_descriptor); } } -/* *INDENT-ON* */ } vl_api_registration_t * @@ -128,7 +129,7 @@ vl_socket_api_send (vl_api_registration_t * rp, u8 * elem) cf = vl_api_registration_file (rp); ASSERT (rp->registration_type > REGISTRATION_TYPE_SHMEM); - if (msg_id >= vec_len (am->api_trace_cfg)) + if (msg_id >= vec_len (am->msg_data)) { clib_warning ("id out of range: %d", msg_id); vl_msg_api_free ((void *) elem); @@ -179,7 +180,8 @@ vl_socket_free_registration_index (u32 pool_index) } rp = pool_elt_at_index (socket_main.registration_pool, pool_index); - vl_api_call_reaper_functions (pool_index); + vl_api_call_reaper_functions ( + clib_host_to_net_u32 (sock_api_registration_handle (rp))); ASSERT (rp->registration_type != REGISTRATION_TYPE_FREE); for (i = 0; i < vec_len (rp->additional_fds_to_close); i++) @@ -200,7 +202,7 @@ vl_socket_process_api_msg (vl_api_registration_t * rp, i8 * input_v) u8 *the_msg = (u8 *) (mbp->data); socket_main.current_rp = rp; - vl_msg_api_socket_handler (the_msg); + vl_msg_api_socket_handler (the_msg, ntohl (mbp->data_len)); socket_main.current_rp = 0; } @@ -216,6 +218,12 @@ static void socket_cleanup_pending_remove_registration_cb (u32 *preg_index) { vl_api_registration_t *rp = vl_socket_get_registration (*preg_index); + if (!rp) + { + /* Might already have gone */ + return; + } + clib_file_main_t *fm = &file_main; u32 pending_remove_file_index = vl_api_registration_file_index (rp); @@ -278,6 +286,10 @@ vl_socket_read_ready (clib_file_t * uf) } rp = vl_socket_get_registration (reg_index); + if (!rp) + { + return 0; + } /* Ignore unprocessed_input for now, n describes input_buffer for now. */ n = read (uf->file_descriptor, socket_main.input_buffer, @@ -398,7 +410,7 @@ vl_socket_write_ready (clib_file_t * uf) while (remaining_bytes > 0) { bytes_to_send = remaining_bytes > 4096 ? 4096 : remaining_bytes; - n = write (uf->file_descriptor, p, bytes_to_send); + n = send (uf->file_descriptor, p, bytes_to_send, MSG_NOSIGNAL); if (n < 0) { if (errno == EAGAIN) @@ -513,7 +525,6 @@ vl_api_sockclnt_create_t_handler (vl_api_sockclnt_create_t * mp) rp->response = htonl (rv); rp->count = htons (nmsg); - /* *INDENT-OFF* */ hash_foreach_pair (hp, am->msg_index_by_name_and_crc, ({ rp->message_table[i].index = htons(hp->value[0]); @@ -523,7 +534,6 @@ vl_api_sockclnt_create_t_handler (vl_api_sockclnt_create_t * mp) 64-1 /* chars to copy, without zero byte. */); i++; })); - /* *INDENT-ON* */ vl_api_send_msg (regp, (u8 *) rp); } @@ -692,7 +702,7 @@ vl_api_sock_init_shm_t_handler (vl_api_sock_init_shm_t * mp) /* delete the unused heap created in ssvm_server_init_memfd and mark it * accessible again for ASAN */ clib_mem_destroy_heap (memfd->sh->heap); - CLIB_MEM_UNPOISON ((void *) memfd->sh->ssvm_va, memfd->ssvm_size); + clib_mem_unpoison ((void *) memfd->sh->ssvm_va, memfd->ssvm_size); /* Remember to close this fd when the socket connection goes away */ vec_add1 (regp->additional_fds_to_close, memfd->fd); @@ -792,12 +802,19 @@ vl_sock_api_init (vlib_main_t * vm) return 0; #define _(N, n, t) \ - vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \ - vl_noop_handler, vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, sizeof (vl_api_##n##_t), t, \ - vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \ - vl_api_##n##_t_fromjson); \ - am->api_trace_cfg[VL_API_##N].replay_enable = 0; + vl_msg_api_config (&(vl_msg_api_msg_config_t){ \ + .id = VL_API_##N, \ + .name = #n, \ + .handler = vl_api_##n##_t_handler, \ + .endian = vl_api_##n##_t_endian, \ + .format_fn = vl_api_##n##_t_format, \ + .size = sizeof (vl_api_##n##_t), \ + .traced = t, \ + .tojson = vl_api_##n##_t_tojson, \ + .fromjson = vl_api_##n##_t_fromjson, \ + .calc_size = vl_api_##n##_t_calc_size, \ + }); \ + am->msg_data[VL_API_##N].replay_allowed = 0; foreach_vlib_api_msg; #undef _ @@ -834,13 +851,11 @@ socket_exit (vlib_main_t * vm) if (sm->registration_pool) { u32 index; - /* *INDENT-OFF* */ pool_foreach (rp, sm->registration_pool) { vl_api_registration_del_file (rp); index = rp->vl_api_registration_pool_index; vl_socket_free_registration_index (index); } -/* *INDENT-ON* */ } return 0; diff --git a/src/vlibmemory/socket_client.c b/src/vlibmemory/socket_client.c index 2fb6b8a0c4e..ad28136dc07 100644 --- a/src/vlibmemory/socket_client.c +++ b/src/vlibmemory/socket_client.c @@ -22,6 +22,14 @@ #define _GNU_SOURCE #include <sys/socket.h> +#ifdef __FreeBSD__ +#define _WANT_UCRED +#include <sys/types.h> +#include <sys/param.h> +#include <sys/ucred.h> +#include <sys/un.h> +#endif /* __FreeBSD__ */ + #include <svm/ssvm.h> #include <vlibmemory/socket_client.h> #include <vlibmemory/memory_client.h> @@ -36,8 +44,11 @@ #include <vlibmemory/vl_memory_api_h.h> #undef vl_endianfun +#define vl_calcsizefun +#include <vlibmemory/vl_memory_api_h.h> +#undef vl_calcsizefun + /* instantiate all the print functions we know about */ -#define vl_print(handle, ...) clib_warning (__VA_ARGS__) #define vl_printfun #include <vlibmemory/vl_memory_api_h.h> #undef vl_printfun @@ -84,12 +95,11 @@ vl_socket_client_read_internal (socket_client_main_t * scm, int wait) while (1) { - while (vec_len (scm->socket_rx_buffer) < sizeof (*mbp)) + current_rx_index = vec_len (scm->socket_rx_buffer); + while (current_rx_index < sizeof (*mbp)) { - current_rx_index = vec_len (scm->socket_rx_buffer); vec_validate (scm->socket_rx_buffer, current_rx_index + scm->socket_buffer_size - 1); - _vec_len (scm->socket_rx_buffer) = current_rx_index; n = read (scm->socket_fd, scm->socket_rx_buffer + current_rx_index, scm->socket_buffer_size); if (n < 0) @@ -98,10 +108,12 @@ vl_socket_client_read_internal (socket_client_main_t * scm, int wait) continue; clib_unix_warning ("socket_read"); + vec_set_len (scm->socket_rx_buffer, current_rx_index); return -1; } - _vec_len (scm->socket_rx_buffer) += n; + current_rx_index += n; } + vec_set_len (scm->socket_rx_buffer, current_rx_index); #if CLIB_DEBUG > 1 if (n > 0) @@ -112,32 +124,32 @@ vl_socket_client_read_internal (socket_client_main_t * scm, int wait) data_len = ntohl (mbp->data_len); current_rx_index = vec_len (scm->socket_rx_buffer); vec_validate (scm->socket_rx_buffer, current_rx_index + data_len); - _vec_len (scm->socket_rx_buffer) = current_rx_index; mbp = (msgbuf_t *) (scm->socket_rx_buffer); msg_size = data_len + sizeof (*mbp); - while (vec_len (scm->socket_rx_buffer) < msg_size) + while (current_rx_index < msg_size) { - n = read (scm->socket_fd, - scm->socket_rx_buffer + vec_len (scm->socket_rx_buffer), - msg_size - vec_len (scm->socket_rx_buffer)); + n = read (scm->socket_fd, scm->socket_rx_buffer + current_rx_index, + msg_size - current_rx_index); if (n < 0) { if (errno == EAGAIN) continue; clib_unix_warning ("socket_read"); + vec_set_len (scm->socket_rx_buffer, current_rx_index); return -1; } - _vec_len (scm->socket_rx_buffer) += n; + current_rx_index += n; } + vec_set_len (scm->socket_rx_buffer, current_rx_index); if (vec_len (scm->socket_rx_buffer) >= data_len + sizeof (*mbp)) { - vl_msg_api_socket_handler ((void *) (mbp->data)); + vl_msg_api_socket_handler ((void *) (mbp->data), data_len); if (vec_len (scm->socket_rx_buffer) == data_len + sizeof (*mbp)) - _vec_len (scm->socket_rx_buffer) = 0; + vec_set_len (scm->socket_rx_buffer, 0); else vec_delete (scm->socket_rx_buffer, data_len + sizeof (*mbp), 0); mbp = 0; @@ -175,11 +187,11 @@ static int vl_socket_client_write_internal (socket_client_main_t * scm) { int n; - + int len = vec_len (scm->socket_tx_buffer); msgbuf_t msgbuf = { .q = 0, .gc_mark_timestamp = 0, - .data_len = htonl (scm->socket_tx_nbytes), + .data_len = htonl (len), }; n = write (scm->socket_fd, &msgbuf, sizeof (msgbuf)); @@ -189,8 +201,11 @@ vl_socket_client_write_internal (socket_client_main_t * scm) return -1; } - n = write (scm->socket_fd, scm->socket_tx_buffer, scm->socket_tx_nbytes); - if (n < scm->socket_tx_nbytes) + n = write (scm->socket_fd, scm->socket_tx_buffer, len); + + vec_set_len (scm->socket_tx_buffer, 0); + + if (n < len) { clib_unix_warning ("socket write (msg)"); return -1; @@ -220,7 +235,7 @@ vl_socket_client_write2 (socket_client_main_t * scm) void * vl_socket_client_msg_alloc2 (socket_client_main_t * scm, int nbytes) { - scm->socket_tx_nbytes = nbytes; + vec_set_len (scm->socket_tx_buffer, nbytes); return ((void *) scm->socket_tx_buffer); } @@ -271,7 +286,11 @@ vl_sock_api_recv_fd_msg_internal (socket_client_main_t * scm, int fds[], struct msghdr mh = { 0 }; struct iovec iov[1]; ssize_t size = 0; +#ifdef __linux__ struct ucred *cr = 0; +#elif __FreeBSD__ + struct cmsgcred *cr = 0; +#endif /* __linux__ */ struct cmsghdr *cmsg; pid_t pid __attribute__ ((unused)); uid_t uid __attribute__ ((unused)); @@ -311,6 +330,7 @@ vl_sock_api_recv_fd_msg_internal (socket_client_main_t * scm, int fds[], { if (cmsg->cmsg_level == SOL_SOCKET) { +#ifdef __linux__ if (cmsg->cmsg_type == SCM_CREDENTIALS) { cr = (struct ucred *) CMSG_DATA (cmsg); @@ -318,6 +338,15 @@ vl_sock_api_recv_fd_msg_internal (socket_client_main_t * scm, int fds[], gid = cr->gid; pid = cr->pid; } +#elif __FreeBSD__ + if (cmsg->cmsg_type == SCM_CREDS) + { + cr = (struct cmsgcred *) CMSG_DATA (cmsg); + uid = cr->cmcred_uid; + gid = cr->cmcred_gid; + pid = cr->cmcred_pid; + } +#endif /* __linux__ */ else if (cmsg->cmsg_type == SCM_RIGHTS) { clib_memcpy_fast (fds, CMSG_DATA (cmsg), sizeof (int) * n_fds); @@ -423,21 +452,23 @@ vl_api_sockclnt_create_reply_t_handler (vl_api_sockclnt_create_reply_t * mp) _(SOCKCLNT_CREATE_REPLY, sockclnt_create_reply) \ _(SOCK_INIT_SHM_REPLY, sock_init_shm_reply) \ -static void -noop_handler (void *notused) -{ -} - void vl_sock_client_install_message_handlers (void) { #define _(N, n) \ - vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \ - noop_handler, vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0, \ - vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \ - vl_api_##n##_t_fromjson); + vl_msg_api_config (&(vl_msg_api_msg_config_t){ \ + .id = VL_API_##N, \ + .name = #n, \ + .handler = vl_api_##n##_t_handler, \ + .endian = vl_api_##n##_t_endian, \ + .format_fn = vl_api_##n##_t_format, \ + .size = sizeof (vl_api_##n##_t), \ + .traced = 0, \ + .tojson = vl_api_##n##_t_tojson, \ + .fromjson = vl_api_##n##_t_fromjson, \ + .calc_size = vl_api_##n##_t_calc_size, \ + }); foreach_sock_client_api_msg; #undef _ } @@ -476,8 +507,8 @@ vl_socket_client_connect_internal (socket_client_main_t * scm, SOCKET_CLIENT_DEFAULT_BUFFER_SIZE; vec_validate (scm->socket_tx_buffer, scm->socket_buffer_size - 1); vec_validate (scm->socket_rx_buffer, scm->socket_buffer_size - 1); - _vec_len (scm->socket_rx_buffer) = 0; - _vec_len (scm->socket_tx_buffer) = 0; + vec_set_len (scm->socket_rx_buffer, 0); + vec_set_len (scm->socket_tx_buffer, 0); scm->name = format (0, "%s", client_name); mp = vl_socket_client_msg_alloc2 (scm, sizeof (*mp)); diff --git a/src/vlibmemory/socket_client.h b/src/vlibmemory/socket_client.h index 231290088b3..a4b8bc7d6be 100644 --- a/src/vlibmemory/socket_client.h +++ b/src/vlibmemory/socket_client.h @@ -20,7 +20,7 @@ #include <vppinfra/file.h> #include <vppinfra/time.h> -#include <vlibmemory/memory_shared.h> +#include <vlibapi/memory_shared.h> typedef struct { @@ -34,7 +34,6 @@ typedef struct u32 socket_buffer_size; u8 *socket_tx_buffer; u8 *socket_rx_buffer; - u32 socket_tx_nbytes; int control_pings_outstanding; u8 *name; diff --git a/src/vlibmemory/vlib_api.c b/src/vlibmemory/vlib_api.c index b598f0b9852..705e9c241a6 100644 --- a/src/vlibmemory/vlib_api.c +++ b/src/vlibmemory/vlib_api.c @@ -340,7 +340,10 @@ vlib_apis_hookup (vlib_main_t *vm) */ msg_id_base = setup_message_id_table (); - am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1; + /* Mark messages as mp safe */ + vl_api_set_msg_thread_safe (am, msg_id_base + VL_API_GET_NODE_GRAPH, 1); + vl_api_set_msg_thread_safe (am, msg_id_base + VL_API_SHOW_THREADS, 1); + return 0; } diff --git a/src/vlibmemory/vlib_api_cli.c b/src/vlibmemory/vlib_api_cli.c index afd145fe620..6ae81cd13df 100644 --- a/src/vlibmemory/vlib_api_cli.c +++ b/src/vlibmemory/vlib_api_cli.c @@ -61,14 +61,12 @@ vl_api_show_histogram_command (vlib_main_t * vm, /*? * Display the binary api sleep-time histogram ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (cli_show_api_histogram_command, static) = { .path = "show api histogram", .short_help = "show api histogram", .function = vl_api_show_histogram_command, }; -/* *INDENT-ON* */ static clib_error_t * vl_api_clear_histogram_command (vlib_main_t * vm, @@ -85,14 +83,12 @@ vl_api_clear_histogram_command (vlib_main_t * vm, /*? * Clear the binary api sleep-time histogram ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (cli_clear_api_histogram_command, static) = { .path = "clear api histogram", .short_help = "clear api histogram", .function = vl_api_clear_histogram_command, }; -/* *INDENT-ON* */ static clib_error_t * vl_api_client_command (vlib_main_t * vm, @@ -110,7 +106,6 @@ vl_api_client_command (vlib_main_t * vm, vlib_cli_output (vm, "%20s %8s %14s %18s %s", "Name", "PID", "Queue Length", "Queue VA", "Health"); - /* *INDENT-OFF* */ pool_foreach (regpp, am->vl_clients) { regp = *regpp; @@ -135,7 +130,6 @@ vl_api_client_command (vlib_main_t * vm, vec_add1 (confused_indices, regpp - am->vl_clients); } } - /* *INDENT-ON* */ /* This should "never happen," but if it does, fix it... */ if (PREDICT_FALSE (vec_len (confused_indices) > 0)) @@ -191,37 +185,31 @@ vl_api_status_command (vlib_main_t * vm, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (cli_show_api_command, static) = { .path = "show api", .short_help = "Show API information", }; -/* *INDENT-ON* */ /*? * Display current api client connections ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (cli_show_api_clients_command, static) = { .path = "show api clients", .short_help = "Client information", .function = vl_api_client_command, }; -/* *INDENT-ON* */ /*? * Display the current api message tracing status ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (cli_show_api_status_command, static) = { .path = "show api trace-status", .short_help = "Display API trace status", .function = vl_api_status_command, }; -/* *INDENT-ON* */ static clib_error_t * vl_api_message_table_command (vlib_main_t * vm, @@ -242,20 +230,19 @@ vl_api_message_table_command (vlib_main_t * vm, vlib_cli_output (vm, "%-4s %-40s %6s %7s", "ID", "Name", "Bounce", "MP-safe"); - for (i = 1; i < vec_len (am->msg_names); i++) + for (i = 1; i < vec_len (am->msg_data); i++) { + vl_api_msg_data_t *m = vl_api_get_msg_data (am, i); if (verbose == 0) { vlib_cli_output (vm, "%-4d %s", i, - am->msg_names[i] ? am->msg_names[i] : - " [no handler]"); + m->name ? m->name : " [no handler]"); } else { vlib_cli_output (vm, "%-4d %-40s %6d %7d", i, - am->msg_names[i] ? am->msg_names[i] : - " [no handler]", am->message_bounce[i], - am->is_mp_safe[i]); + m->name ? m->name : " [no handler]", m->bounce, + m->is_mp_safe); } } @@ -265,14 +252,12 @@ vl_api_message_table_command (vlib_main_t * vm, /*? * Display the current api message decode tables ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (cli_show_api_message_table_command, static) = { .path = "show api message-table", .short_help = "Message Table", .function = vl_api_message_table_command, }; -/* *INDENT-ON* */ static int range_compare (vl_api_msg_range_t * a0, vl_api_msg_range_t * a1) @@ -332,14 +317,12 @@ vl_api_show_plugin_command (vlib_main_t * vm, /*? * Display the plugin binary API message range table ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (cli_show_api_plugin_command, static) = { .path = "show api plugin", .short_help = "show api plugin", .function = vl_api_show_plugin_command, }; -/* *INDENT-ON* */ typedef enum { @@ -435,7 +418,7 @@ vl_msg_api_process_file (vlib_main_t * vm, u8 * filename, } close (fd); - CLIB_MEM_UNPOISON (hp, file_size); + clib_mem_unpoison (hp, file_size); nitems = ntohl (hp->nitems); @@ -487,7 +470,11 @@ vl_msg_api_process_file (vlib_main_t * vm, u8 * filename, { u16 msg_index = unserialize_likely_small_unsigned_integer (sm); unserialize_cstring (sm, (char **) &name_and_crc); - u16 msg_index2 = vl_msg_api_get_msg_index (name_and_crc); + u32 msg_index2 = vl_msg_api_get_msg_index (name_and_crc); + ASSERT (~0 == msg_index2 || msg_index2 <= 65535); + if (~0 == msg_index2) + vlib_cli_output (vm, "warning: can't find msg index for id %d\n", + msg_index); vec_validate (msgid_vec, msg_index); msgid_vec[msg_index] = msg_index2; } @@ -496,7 +483,6 @@ vl_msg_api_process_file (vlib_main_t * vm, u8 * filename, for (i = 0; i < first_index; i++) { - trace_cfg_t *cfgp; int size; u16 msg_id; @@ -504,18 +490,13 @@ vl_msg_api_process_file (vlib_main_t * vm, u8 * filename, size = clib_host_to_net_u32 (*(u32 *) msg); msg += sizeof (u32); - assert_size (file_size_left, size); + assert_size (file_size_left, clib_max (size, sizeof (u16))); msg_id = ntohs (*((u16 *) msg)); - if (msg_id < vec_len (msgid_vec)) - msg_id = msgid_vec[msg_id]; - cfgp = am->api_trace_cfg + msg_id; - if (!cfgp) - { - vlib_cli_output (vm, "Ugh: msg id %d no trace config\n", msg_id); - munmap (hp, file_size); - vec_free (msgid_vec); - return; - } + if (msg_id >= vec_len (msgid_vec) || + msgid_vec[msg_id] >= vec_len (am->msg_data)) + vlib_cli_output (vm, "warning: unknown msg id %d for msg number %d\n", + msg_id, i); + msg += size; } @@ -524,32 +505,33 @@ vl_msg_api_process_file (vlib_main_t * vm, u8 * filename, for (; i <= last_index; i++) { - trace_cfg_t *cfgp; + vl_api_msg_data_t *m; u16 msg_id; int size; if (which == DUMP) vlib_cli_output (vm, "---------- trace %d -----------\n", i); + assert_size (file_size_left, sizeof (u32)); size = clib_host_to_net_u32 (*(u32 *) msg); msg += sizeof (u32); + assert_size (file_size_left, clib_max (size, sizeof (u16))); msg_id = ntohs (*((u16 *) msg)); - if (msg_id < vec_len (msgid_vec)) - { - msg_id = msgid_vec[msg_id]; - } - cfgp = am->api_trace_cfg + msg_id; - if (!cfgp) + if (msg_id >= vec_len (msgid_vec) || + msgid_vec[msg_id] >= vec_len (am->msg_data)) { - vlib_cli_output (vm, "Ugh: msg id %d no trace config\n", msg_id); - munmap (hp, file_size); - vec_free (tmpbuf); - am->replay_in_progress = 0; - return; + vlib_cli_output ( + vm, "warning: unknown msg id %d for msg number %d, skipping\n", + msg_id, i); + msg += size; + continue; } + msg_id = msgid_vec[msg_id]; + m = vl_api_get_msg_data (am, msg_id); + /* Copy the buffer (from the read-only mmap'ed file) */ vec_validate (tmpbuf, size - 1 + sizeof (uword)); clib_memcpy (tmpbuf + sizeof (uword), msg, size); @@ -562,9 +544,7 @@ vl_msg_api_process_file (vlib_main_t * vm, u8 * filename, if (((which == DUMP || which == DUMP_JSON) && clib_arch_is_little_endian)) { - void (*endian_fp) (void *); - if (msg_id >= vec_len (am->msg_endian_handlers) - || (am->msg_endian_handlers[msg_id] == 0)) + if (m && m->endian_handler == 0) { vlib_cli_output (vm, "Ugh: msg id %d no endian swap\n", msg_id); munmap (hp, file_size); @@ -572,8 +552,10 @@ vl_msg_api_process_file (vlib_main_t * vm, u8 * filename, am->replay_in_progress = 0; return; } - endian_fp = am->msg_endian_handlers[msg_id]; - (*endian_fp) (tmpbuf + sizeof (uword)); + if (m) + { + m->endian_handler (tmpbuf + sizeof (uword), 1 /* to network */); + } } /* msg_id always in network byte order */ @@ -586,59 +568,30 @@ vl_msg_api_process_file (vlib_main_t * vm, u8 * filename, switch (which) { case DUMP_JSON: - if (msg_id < vec_len (am->msg_print_json_handlers) && - am->msg_print_json_handlers[msg_id]) - { - u8 *(*print_fp) (void *, void *); - - print_fp = (void *) am->msg_print_json_handlers[msg_id]; - (*print_fp) (tmpbuf + sizeof (uword), vm); - } - else - { - vlib_cli_output (vm, "Skipping msg id %d: no JSON print fcn\n", - msg_id); - break; - } + vlib_cli_output (vm, "%U", format_vl_api_msg_json, am, msg_id, + tmpbuf + sizeof (uword)); break; case DUMP: - if (msg_id < vec_len (am->msg_print_handlers) && - am->msg_print_handlers[msg_id]) - { - u8 *(*print_fp) (void *, void *); - - print_fp = (void *) am->msg_print_handlers[msg_id]; - (*print_fp) (tmpbuf + sizeof (uword), vm); - } - else - { - vlib_cli_output (vm, "Skipping msg id %d: no print fcn\n", - msg_id); - break; - } + vlib_cli_output (vm, "%U", format_vl_api_msg_text, am, msg_id, + tmpbuf + sizeof (uword)); break; case INITIALIZERS: - if (msg_id < vec_len (am->msg_print_handlers) && - am->msg_print_handlers[msg_id]) + if (m) { u8 *s; int j; - u8 *(*print_fp) (void *, void *); - print_fp = (void *) am->msg_print_handlers[msg_id]; + vlib_cli_output (vm, "/*%U*/", format_vl_api_msg_text, am, + msg_id, tmpbuf + sizeof (uword)); - vlib_cli_output (vm, "/*"); - - (*print_fp) (tmpbuf + sizeof (uword), vm); vlib_cli_output (vm, "*/\n"); - s = format (0, "static u8 * vl_api_%s_%d[%d] = {", - am->msg_names[msg_id], i, - am->api_trace_cfg[msg_id].size); + s = format (0, "static u8 * vl_api_%s_%d[%d] = {", m->name, i, + m->trace_size); - for (j = 0; j < am->api_trace_cfg[msg_id].size; j++) + for (j = 0; j < m->trace_size; j++) { if ((j & 7) == 0) s = format (s, "\n "); @@ -651,22 +604,17 @@ vl_msg_api_process_file (vlib_main_t * vm, u8 * filename, break; case REPLAY: - if (msg_id < vec_len (am->msg_print_handlers) && - am->msg_print_handlers[msg_id] && cfgp->replay_enable) + if (m && m->handler && m->replay_allowed) { - void (*handler) (void *, vlib_main_t *); - - handler = (void *) am->msg_handlers[msg_id]; - - if (!am->is_mp_safe[msg_id]) + if (!m->is_mp_safe) vl_msg_api_barrier_sync (); - (*handler) (tmpbuf + sizeof (uword), vm); - if (!am->is_mp_safe[msg_id]) + m->handler (tmpbuf + sizeof (uword)); + if (!m->is_mp_safe) vl_msg_api_barrier_release (); } else { - if (cfgp->replay_enable) + if (m && m->replay_allowed) vlib_cli_output (vm, "Skipping msg id %d: no handler\n", msg_id); break; @@ -674,7 +622,7 @@ vl_msg_api_process_file (vlib_main_t * vm, u8 * filename, break; } - _vec_len (tmpbuf) = 0; + vec_set_len (tmpbuf, 0); msg += size; } @@ -709,37 +657,29 @@ vl_msg_print_trace (u8 *msg, void *ctx) vl_msg_print_args *a = ctx; api_main_t *am = vlibapi_get_main (); u16 msg_id = ntohs (*((u16 *) msg)); - void (*print_fp) (void *, void *); - void (**handlers) (void *, void *); + vl_api_msg_data_t *m = vl_api_get_msg_data (am, msg_id); u8 is_json = a->is_json; u8 *tmpbuf = 0; - if (clib_arch_is_little_endian) + if (!m) + { + vlib_cli_output (a->vm, "Unknown msg id %d\n", msg_id); + return 0; + } + + if (clib_arch_is_little_endian && (m->endian_handler != NULL)) { u32 msg_length = vec_len (msg); vec_validate (tmpbuf, msg_length - 1); clib_memcpy_fast (tmpbuf, msg, msg_length); msg = tmpbuf; - void (*endian_fp) (void *); - endian_fp = am->msg_endian_handlers[msg_id]; - (*endian_fp) (tmpbuf); + m->endian_handler (tmpbuf, 0 /* from network */); } - if (is_json) - handlers = am->msg_print_json_handlers; - else - handlers = am->msg_print_handlers; - - if (msg_id < vec_len (handlers) && handlers[msg_id]) - { - print_fp = (void *) handlers[msg_id]; - (*print_fp) (msg, a->vm); - } - else - { - vlib_cli_output (a->vm, "Skipping msg id %d: no print fcn\n", msg_id); - } + vlib_cli_output (a->vm, "%U\n", + is_json ? format_vl_api_msg_json : format_vl_api_msg_text, + am, msg_id, msg); vec_free (tmpbuf); return 0; @@ -826,9 +766,8 @@ vl_msg_exec_json_command (vlib_main_t *vm, cJSON *o) { api_main_t *am = vlibapi_get_main (); u16 msg_id; - void *(*fromjson) (cJSON *, int *); int len = 0, rv = -1; - trace_cfg_t *cfgp; + vl_api_msg_data_t *m; u8 *msg = 0; cJSON *msg_id_obj = cJSON_GetObjectItem (o, "_msgname"); @@ -850,6 +789,7 @@ vl_msg_exec_json_command (vlib_main_t *vm, cJSON *o) u8 *name_crc = format (0, "%s_%s%c", name, crc, 0); msg_id = vl_msg_find_id_by_name_and_crc (vm, am, (char *) name_crc); + m = vl_api_get_msg_data (am, msg_id); if (msg_id == (u16) ~0) { msg_id = vl_msg_find_id_by_name (vm, am, name); @@ -863,28 +803,19 @@ vl_msg_exec_json_command (vlib_main_t *vm, cJSON *o) } vec_free (name_crc); - cfgp = am->api_trace_cfg + msg_id; - if (!am->api_trace_cfg) - { - vlib_cli_output (vm, "msg id %d no trace config\n", msg_id); - return rv; - } - - if (cfgp->replay_enable) + if (m->replay_allowed) { - if (proc_warning) vlib_cli_output (vm, "warning: msg %d has different signature\n"); - fromjson = am->msg_fromjson_handlers[msg_id]; - if (!fromjson) + if (!m->fromjson_handler) { vlib_cli_output (vm, "missing fromjson convert function! id %d\n", msg_id); return rv; } - msg = (u8 *) fromjson (o, &len); + msg = (u8 *) m->fromjson_handler (o, &len); if (!msg) { vlib_cli_output (vm, "failed to convert JSON (msg id %d)!\n", @@ -893,25 +824,22 @@ vl_msg_exec_json_command (vlib_main_t *vm, cJSON *o) } if (clib_arch_is_little_endian) - { - void (*endian_fp) (void *); - endian_fp = am->msg_endian_handlers[msg_id]; - (*endian_fp) (msg); - } + m->endian_handler (msg, 1 /* to network */); - void (*handler) (void *, vlib_main_t *); - handler = (void *) am->msg_handlers[msg_id]; - if (!handler) + if (!m->handler) { vlib_cli_output (vm, "no handler for msg id %d!\n", msg_id); goto end; } - if (!am->is_mp_safe[msg_id]) - vl_msg_api_barrier_sync (); - (*handler) (msg, vm); - if (!am->is_mp_safe[msg_id]) - vl_msg_api_barrier_release (); + if (m->handler) + { + if (!m->is_mp_safe) + vl_msg_api_barrier_sync (); + m->handler (msg); + if (!m->is_mp_safe) + vl_msg_api_barrier_release (); + } } rv = 0; @@ -1205,7 +1133,6 @@ out: * Display, replay, or save a binary API trace ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (api_trace_command, static) = { .path = "api trace", .short_help = "api trace [tx][on|off][first <n>][last <n>][status][free]" @@ -1215,7 +1142,6 @@ VLIB_CLI_COMMAND (api_trace_command, static) = { .function = api_trace_command_fn, .is_mp_safe = 1, }; -/* *INDENT-ON* */ static clib_error_t * api_trace_config_fn (vlib_main_t * vm, unformat_input_t * input) @@ -1286,7 +1212,7 @@ extract_name (u8 * s) rv = vec_dup (s); while (vec_len (rv) && rv[vec_len (rv)] != '_') - _vec_len (rv)--; + vec_dec_len (rv, 1); rv[vec_len (rv)] = 0; @@ -1545,7 +1471,6 @@ cleanup: * decode table with the current image, to establish API differences. * ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (dump_api_table_file, static) = { .path = "show api dump", @@ -1553,7 +1478,6 @@ VLIB_CLI_COMMAND (dump_api_table_file, static) = .function = dump_api_table_file_command_fn, }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vlibmemory/vlibapi_test.c b/src/vlibmemory/vlibapi_test.c index 820096ab80d..bed4879030e 100644 --- a/src/vlibmemory/vlibapi_test.c +++ b/src/vlibmemory/vlibapi_test.c @@ -200,7 +200,7 @@ exec (vat_main_t *vam) static int api_cli (vat_main_t *vam) { - return exec (vam); + return exec_inband (vam); } static int |