X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvlibapi%2Fapi_shared.c;h=1e7f5c420c6fbeeedd6d328ff2c0d15256fe7903;hb=33a58171e;hp=5c1a9940dc749afa3e557c3ba47306b4678b9536;hpb=bfd9227e6da567e0e19e026afe94cd4c0b65f725;p=vpp.git diff --git a/src/vlibapi/api_shared.c b/src/vlibapi/api_shared.c index 5c1a9940dc7..1e7f5c420c6 100644 --- a/src/vlibapi/api_shared.c +++ b/src/vlibapi/api_shared.c @@ -70,7 +70,7 @@ vl_msg_api_trace (api_main_t * am, vl_api_trace_t * tp, void *msg) u8 *msg_copy; u32 length; trace_cfg_t *cfgp; - u16 msg_id = ntohs (*((u16 *) msg)); + u16 msg_id = clib_net_to_host_u16 (*((u16 *) msg)); msgbuf_t *header = (msgbuf_t *) (((u8 *) msg) - offsetof (msgbuf_t, data)); cfgp = am->api_trace_cfg + msg_id; @@ -97,14 +97,16 @@ vl_msg_api_trace (api_main_t * am, vl_api_trace_t * tp, void *msg) old_trace = tp->traces + tp->curindex++; if (tp->curindex == tp->nitems) tp->curindex = 0; - vec_free (*old_trace); + /* Reuse the trace record, may save some memory allocator traffic */ + msg_copy = *old_trace; + vec_reset_length (msg_copy); this_trace = old_trace; } length = clib_net_to_host_u32 (header->data_len); vec_validate (msg_copy, length - 1); - clib_memcpy (msg_copy, msg, length); + clib_memcpy_fast (msg_copy, msg, length); *this_trace = msg_copy; } @@ -187,6 +189,29 @@ vl_msg_api_trace_free (api_main_t * am, vl_api_trace_which_t which) return 0; } +u8 * +vl_api_serialize_message_table (api_main_t * am, u8 * vector) +{ + serialize_main_t _sm, *sm = &_sm; + hash_pair_t *hp; + u32 nmsg = hash_elts (am->msg_index_by_name_and_crc); + + serialize_open_vector (sm, vector); + + /* serialize the count */ + serialize_integer (sm, nmsg, sizeof (u32)); + + /* *INDENT-OFF* */ + hash_foreach_pair (hp, am->msg_index_by_name_and_crc, + ({ + serialize_likely_small_unsigned_integer (sm, hp->value[0]); + serialize_cstring (sm, (char *) hp->key); + })); + /* *INDENT-ON* */ + + return serialize_close_vector (sm); +} + int vl_msg_api_trace_save (api_main_t * am, vl_api_trace_which_t which, FILE * fp) { @@ -221,15 +246,23 @@ vl_msg_api_trace_save (api_main_t * am, vl_api_trace_which_t which, FILE * fp) } /* Write the file header */ - fh.nitems = vec_len (tp->traces); - fh.endian = tp->endian; fh.wrapped = tp->wrapped; + fh.nitems = clib_host_to_net_u32 (vec_len (tp->traces)); + u8 *m = vl_api_serialize_message_table (am, 0); + fh.msgtbl_size = clib_host_to_net_u32 (vec_len (m)); if (fwrite (&fh, sizeof (fh), 1, fp) != 1) { return (-10); } + /* Write the message table */ + if (fwrite (m, vec_len (m), 1, fp) != 1) + { + return (-14); + } + vec_free (m); + /* No-wrap case */ if (tp->wrapped == 0) { @@ -360,7 +393,7 @@ vl_msg_api_trace_configure (api_main_t * am, vl_api_trace_which_t which, vl_msg_api_trace_free (am, which); } - memset (tp, 0, sizeof (*tp)); + clib_memset (tp, 0, sizeof (*tp)); if (clib_arch_is_big_endian) { @@ -393,9 +426,29 @@ always_inline void msg_handler_internal (api_main_t * am, void *the_msg, int trace_it, int do_it, int free_it) { - u16 id = ntohs (*((u16 *) the_msg)); + u16 id = clib_net_to_host_u16 (*((u16 *) the_msg)); u8 *(*print_fp) (void *, void *); + if (PREDICT_FALSE (am->elog_trace_api_messages)) + { + /* *INDENT-OFF* */ + ELOG_TYPE_DECLARE (e) = + { + .format = "api-msg: %s", + .format_args = "T4", + }; + /* *INDENT-ON* */ + struct + { + u32 c; + } *ed; + ed = ELOG_DATA (am->elog_main, e); + if (id < vec_len (am->msg_names)) + ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]); + else + ed->c = elog_string (am->elog_main, "BOGUS"); + } + if (id < vec_len (am->msg_handlers) && am->msg_handlers[id]) { if (trace_it) @@ -418,7 +471,10 @@ msg_handler_internal (api_main_t * am, if (do_it) { if (!am->is_mp_safe[id]) - vl_msg_api_barrier_sync (); + { + vl_msg_api_barrier_trace_context (am->msg_names[id]); + vl_msg_api_barrier_sync (); + } (*am->msg_handlers[id]) (the_msg); if (!am->is_mp_safe[id]) vl_msg_api_barrier_release (); @@ -431,34 +487,41 @@ msg_handler_internal (api_main_t * am, if (free_it) vl_msg_api_free (the_msg); -} - -/* set to 1 if you want before/after message handler event logging */ -#define ELOG_API_MESSAGE_HANDLERS 0 - -#if ELOG_API_MESSAGE_HANDLERS > 0 -static u32 -elog_id_for_msg_name (vlib_main_t * vm, char *msg_name) -{ - uword *p, r; - static uword *h; - u8 *name_copy; - - if (!h) - h = hash_create_string (0, sizeof (uword)); - - p = hash_get_mem (h, msg_name); - if (p) - return p[0]; - r = elog_string (&vm->elog_main, "%s", msg_name); - name_copy = format (0, "%s%c", msg_name, 0); - - hash_set_mem (h, name_copy, r); - - return r; + if (PREDICT_FALSE (am->elog_trace_api_messages)) + { + /* *INDENT-OFF* */ + ELOG_TYPE_DECLARE (e) = + { + .format = "api-msg-done(%s): %s", + .format_args = "t4T4", + .n_enum_strings = 2, + .enum_strings = + { + "barrier", + "mp-safe", + } + }; + /* *INDENT-ON* */ + + struct + { + u32 barrier; + u32 c; + } *ed; + ed = ELOG_DATA (am->elog_main, e); + if (id < vec_len (am->msg_names)) + { + ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]); + ed->barrier = !am->is_mp_safe[id]; + } + else + { + ed->c = elog_string (am->elog_main, "BOGUS"); + ed->barrier = 0; + } + } } -#endif /* This is only to be called from a vlib/vnet app */ void @@ -466,41 +529,60 @@ vl_msg_api_handler_with_vm_node (api_main_t * am, void *the_msg, vlib_main_t * vm, vlib_node_runtime_t * node) { - u16 id = ntohs (*((u16 *) the_msg)); + u16 id = clib_net_to_host_u16 (*((u16 *) the_msg)); u8 *(*handler) (void *, void *, void *); + u8 *(*print_fp) (void *, void *); + int is_mp_safe = 1; -#if ELOG_API_MESSAGE_HANDLERS > 0 - { - /* *INDENT-OFF* */ - ELOG_TYPE_DECLARE (e) = + if (PREDICT_FALSE (am->elog_trace_api_messages)) + { + /* *INDENT-OFF* */ + ELOG_TYPE_DECLARE (e) = + { + .format = "api-msg: %s", + .format_args = "T4", + }; + /* *INDENT-ON* */ + struct { - .format = "api-msg: %s", - .format_args = "T4", - }; - /* *INDENT-ON* */ - struct - { - u32 c; - } *ed; - ed = ELOG_DATA (&vm->elog_main, e); - if (id < vec_len (am->msg_names)) - ed->c = elog_id_for_msg_name (vm, am->msg_names[id]); - else - ed->c = elog_id_for_msg_name (vm, "BOGUS"); - } -#endif + u32 c; + } *ed; + ed = ELOG_DATA (am->elog_main, e); + if (id < vec_len (am->msg_names)) + ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]); + else + ed->c = elog_string (am->elog_main, "BOGUS"); + } if (id < vec_len (am->msg_handlers) && am->msg_handlers[id]) { handler = (void *) am->msg_handlers[id]; - if (am->rx_trace && am->rx_trace->enabled) + if (PREDICT_FALSE (am->rx_trace && am->rx_trace->enabled)) vl_msg_api_trace (am, am->rx_trace, the_msg); - if (!am->is_mp_safe[id]) - vl_msg_api_barrier_sync (); + if (PREDICT_FALSE (am->msg_print_flag)) + { + fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]); + print_fp = (void *) am->msg_print_handlers[id]; + if (print_fp == 0) + { + fformat (stdout, " [no registered print fn for msg %d]\n", id); + } + else + { + (*print_fp) (the_msg, vm); + } + } + is_mp_safe = am->is_mp_safe[id]; + + if (!is_mp_safe) + { + vl_msg_api_barrier_trace_context (am->msg_names[id]); + vl_msg_api_barrier_sync (); + } (*handler) (the_msg, vm, node); - if (!am->is_mp_safe[id]) + if (!is_mp_safe) vl_msg_api_barrier_release (); } else @@ -515,26 +597,34 @@ vl_msg_api_handler_with_vm_node (api_main_t * am, if (!(am->message_bounce[id])) vl_msg_api_free (the_msg); -#if ELOG_API_MESSAGE_HANDLERS > 0 - { - /* *INDENT-OFF* */ - ELOG_TYPE_DECLARE (e) = { - .format = "api-msg-done: %s", - .format_args = "T4", - }; - /* *INDENT-ON* */ - - struct + if (PREDICT_FALSE (am->elog_trace_api_messages)) { - u32 c; - } *ed; - ed = ELOG_DATA (&vm->elog_main, e); - if (id < vec_len (am->msg_names)) - ed->c = elog_id_for_msg_name (vm, am->msg_names[id]); - else - ed->c = elog_id_for_msg_name (vm, "BOGUS"); - } -#endif + /* *INDENT-OFF* */ + ELOG_TYPE_DECLARE (e) = + { + .format = "api-msg-done(%s): %s", + .format_args = "t4T4", + .n_enum_strings = 2, + .enum_strings = + { + "barrier", + "mp-safe", + } + }; + /* *INDENT-ON* */ + + struct + { + u32 barrier; + u32 c; + } *ed; + ed = ELOG_DATA (am->elog_main, e); + if (id < vec_len (am->msg_names)) + ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]); + else + ed->c = elog_string (am->elog_main, "BOGUS"); + ed->barrier = is_mp_safe; + } } void @@ -590,7 +680,7 @@ void vl_msg_api_cleanup_handler (void *the_msg) { api_main_t *am = &api_main; - u16 id = ntohs (*((u16 *) the_msg)); + u16 id = clib_net_to_host_u16 (*((u16 *) the_msg)); if (PREDICT_FALSE (id >= vec_len (am->msg_cleanup_handlers))) { @@ -611,7 +701,7 @@ vl_msg_api_replay_handler (void *the_msg) { api_main_t *am = &api_main; - u16 id = ntohs (*((u16 *) the_msg)); + u16 id = clib_net_to_host_u16 (*((u16 *) the_msg)); if (PREDICT_FALSE (id >= vec_len (am->msg_handlers))) { @@ -659,15 +749,32 @@ vl_msg_api_config (vl_msg_api_msg_config_t * c) { api_main_t *am = &api_main; - ASSERT (c->id > 0); + /* + * This happens during the java core tests if the message + * dictionary is missing newly added xxx_reply_t messages. + * Should never happen, but since I shot myself in the foot once + * this way, I thought I'd make it easy to debug if I ever do + * it again... (;-)... + */ + if (c->id == 0) + { + if (c->name) + clib_warning ("Trying to register %s with a NULL msg id!", c->name); + else + clib_warning ("Trying to register a NULL msg with a NULL msg id!"); + clib_warning ("Did you forget to call setup_message_id_table?"); + return; + } #define _(a) vec_validate (am->a, c->id); foreach_msg_api_vector; #undef _ - if (am->msg_names[c->id]) - clib_warning ("BUG: multiple registrations of 'vl_api_%s_t_handler'", - c->name); + if (am->msg_handlers[c->id] && am->msg_handlers[c->id] != c->handler) + clib_warning + ("BUG: re-registering 'vl_api_%s_t_handler'." + "Handler was %llx, replaced by %llx", + c->name, am->msg_handlers[c->id], c->handler); am->msg_names[c->id] = c->name; am->msg_handlers[c->id] = c->handler; @@ -693,7 +800,7 @@ vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup, vl_msg_api_msg_config_t cfg; vl_msg_api_msg_config_t *c = &cfg; - memset (c, 0, sizeof (*c)); + clib_memset (c, 0, sizeof (*c)); c->id = id; c->name = name; @@ -708,6 +815,18 @@ vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup, vl_msg_api_config (c); } +void +vl_msg_api_clean_handlers (int msg_id) +{ + vl_msg_api_msg_config_t cfg; + vl_msg_api_msg_config_t *c = &cfg; + + clib_memset (c, 0, sizeof (*c)); + + c->id = msg_id; + vl_msg_api_config (c); +} + void vl_msg_api_set_cleanup_handler (int msg_id, void *fp) { @@ -719,11 +838,11 @@ vl_msg_api_set_cleanup_handler (int msg_id, void *fp) } void -vl_msg_api_queue_handler (unix_shared_memory_queue_t * q) +vl_msg_api_queue_handler (svm_queue_t * q) { uword msg; - while (!unix_shared_memory_queue_sub (q, (u8 *) & msg, 0)) + while (!svm_queue_sub (q, (u8 *) & msg, SVM_Q_WAIT, 0)) vl_msg_api_handler ((void *) msg); } @@ -895,6 +1014,122 @@ vl_msg_api_add_msg_name_crc (api_main_t * am, const char *string, u32 id) hash_set_mem (am->msg_index_by_name_and_crc, string, id); } +void +vl_msg_api_add_version (api_main_t * am, const char *string, + u32 major, u32 minor, u32 patch) +{ + api_version_t version = {.major = major,.minor = minor,.patch = patch }; + ASSERT (strlen (string) < 64); + strncpy (version.name, string, 64 - 1); + vec_add1 (am->api_version_list, version); +} + +u32 +vl_msg_api_get_msg_index (u8 * name_and_crc) +{ + api_main_t *am = &api_main; + uword *p; + + if (am->msg_index_by_name_and_crc) + { + p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc); + if (p) + return p[0]; + } + return ~0; +} + +void * +vl_msg_push_heap (void) +{ + api_main_t *am = &api_main; + pthread_mutex_lock (&am->vlib_rp->mutex); + return svm_push_data_heap (am->vlib_rp); +} + +void +vl_msg_pop_heap (void *oldheap) +{ + api_main_t *am = &api_main; + svm_pop_heap (oldheap); + pthread_mutex_unlock (&am->vlib_rp->mutex); +} + +int +vl_api_to_api_string (u32 len, const char *buf, vl_api_string_t * str) +{ + if (len) + clib_memcpy_fast (str->buf, buf, len); + str->length = htonl (len); + return len + sizeof (u32); +} + +int +vl_api_vec_to_api_string (const u8 * vec, vl_api_string_t * str) +{ + u32 len = vec_len (vec); + clib_memcpy (str->buf, vec, len); + str->length = htonl (len); + return len + sizeof (u32); +} + +/* Return a pointer to the API string (not nul terminated */ +u8 * +vl_api_from_api_string (vl_api_string_t * astr) +{ + return astr->buf; +} + +u32 +vl_api_string_len (vl_api_string_t * astr) +{ + return clib_net_to_host_u32 (astr->length); +} + +u8 * +vl_api_format_string (u8 * s, va_list * args) +{ + vl_api_string_t *a = va_arg (*args, vl_api_string_t *); + vec_add (s, a->buf, clib_net_to_host_u32 (a->length)); + return s; +} + +/* + * Returns a new vector. Remember to free it after use. + */ +u8 * +vl_api_from_api_to_vec (vl_api_string_t * astr) +{ + u8 *v = 0; + vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length)); + return v; +} + +void +vl_api_set_elog_main (elog_main_t * m) +{ + api_main_t *am = &api_main; + am->elog_main = m; +} + +int +vl_api_set_elog_trace_api_messages (int enable) +{ + int rv; + api_main_t *am = &api_main; + + rv = am->elog_trace_api_messages; + am->elog_trace_api_messages = enable; + return rv; +} + +int +vl_api_get_elog_trace_api_messages (void) +{ + api_main_t *am = &api_main; + + return am->elog_trace_api_messages; +} /* * fd.io coding-style-patch-verification: ON