aboutsummaryrefslogtreecommitdiffstats
path: root/src/vlibmemory
diff options
context:
space:
mode:
Diffstat (limited to 'src/vlibmemory')
-rw-r--r--src/vlibmemory/CMakeLists.txt16
-rw-r--r--src/vlibmemory/api.h1
-rw-r--r--src/vlibmemory/memclnt.api39
-rw-r--r--src/vlibmemory/memclnt_api.c111
-rw-r--r--src/vlibmemory/memory_api.c266
-rw-r--r--src/vlibmemory/memory_api.h2
-rw-r--r--src/vlibmemory/memory_client.c78
-rw-r--r--src/vlibmemory/memory_client.h3
-rw-r--r--src/vlibmemory/memory_shared.c818
-rw-r--r--src/vlibmemory/memory_shared.h147
-rw-r--r--src/vlibmemory/socket_api.c51
-rw-r--r--src/vlibmemory/socket_client.c91
-rw-r--r--src/vlibmemory/socket_client.h3
-rw-r--r--src/vlibmemory/vlib_api.c5
-rw-r--r--src/vlibmemory/vlib_api_cli.c234
-rw-r--r--src/vlibmemory/vlibapi_test.c2
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